You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
5.5 KiB
144 lines
5.5 KiB
From 9fe6594da91e86280c9d71877a91cee83aaedae6 Mon Sep 17 00:00:00 2001
|
|
Message-Id: <9fe6594da91e86280c9d71877a91cee83aaedae6.1566225007.git.aquini@redhat.com>
|
|
In-Reply-To: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
|
|
References: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
|
|
From: Sandipan Das <sandipan@linux.ibm.com>
|
|
Date: Wed, 12 Jun 2019 12:34:30 +0530
|
|
Subject: [RHEL7 PATCH 13/31] elflink: Fix program header address calculation
|
|
|
|
This fixes the virtual address calculation for the ELF program
|
|
header. Based on the man page of dl_iterate_phdr(), the location
|
|
of a particular program header in virtual memory should be the
|
|
sum of the base address of the shared object and the segment's
|
|
virtual address.
|
|
|
|
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
|
|
Signed-off-by: Eric B Munson <emunson@mgebm.net>
|
|
Signed-off-by: Rafael Aquini <aquini@redhat.com>
|
|
---
|
|
elflink.c | 40 ++++++++++++++++++++++++----------------
|
|
1 file changed, 24 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/elflink.c b/elflink.c
|
|
index ffc84dd..1150bde 100644
|
|
--- a/elflink.c
|
|
+++ b/elflink.c
|
|
@@ -374,7 +374,8 @@ static int get_shared_file_name(struct seg_info *htlb_seg_info, char *file_path)
|
|
}
|
|
|
|
/* Find the .dynamic program header */
|
|
-static int find_dynamic(Elf_Dyn **dyntab, const Elf_Phdr *phdr, int phnum)
|
|
+static int find_dynamic(Elf_Dyn **dyntab, const ElfW(Addr) addr,
|
|
+ const Elf_Phdr *phdr, int phnum)
|
|
{
|
|
int i = 1;
|
|
|
|
@@ -382,7 +383,7 @@ static int find_dynamic(Elf_Dyn **dyntab, const Elf_Phdr *phdr, int phnum)
|
|
++i;
|
|
}
|
|
if (phdr[i].p_type == PT_DYNAMIC) {
|
|
- *dyntab = (Elf_Dyn *)phdr[i].p_vaddr;
|
|
+ *dyntab = (Elf_Dyn *)(addr + phdr[i].p_vaddr);
|
|
return 0;
|
|
} else {
|
|
DEBUG("No dynamic segment found\n");
|
|
@@ -473,7 +474,8 @@ ElfW(Word) __attribute__ ((weak)) plt_extrasz(ElfW(Dyn) *dyntab)
|
|
* include these initialized variables in our copy.
|
|
*/
|
|
|
|
-static void get_extracopy(struct seg_info *seg, const Elf_Phdr *phdr, int phnum)
|
|
+static void get_extracopy(struct seg_info *seg, const ElfW(Addr) addr,
|
|
+ const Elf_Phdr *phdr, int phnum)
|
|
{
|
|
Elf_Dyn *dyntab; /* dynamic segment table */
|
|
Elf_Sym *symtab = NULL; /* dynamic symbol table */
|
|
@@ -492,7 +494,7 @@ static void get_extracopy(struct seg_info *seg, const Elf_Phdr *phdr, int phnum)
|
|
goto bail2;
|
|
|
|
/* Find dynamic program header */
|
|
- ret = find_dynamic(&dyntab, phdr, phnum);
|
|
+ ret = find_dynamic(&dyntab, addr, phdr, phnum);
|
|
if (ret < 0)
|
|
goto bail;
|
|
|
|
@@ -608,7 +610,8 @@ static unsigned long hugetlb_prev_slice_end(unsigned long addr)
|
|
/*
|
|
* Store a copy of the given program header
|
|
*/
|
|
-static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
|
|
+static int save_phdr(int table_idx, int phnum, const ElfW(Addr) addr,
|
|
+ const ElfW(Phdr) *phdr)
|
|
{
|
|
int prot = 0;
|
|
|
|
@@ -626,7 +629,7 @@ static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
|
|
if (phdr->p_flags & PF_X)
|
|
prot |= PROT_EXEC;
|
|
|
|
- htlb_seg_table[table_idx].vaddr = (void *) phdr->p_vaddr;
|
|
+ htlb_seg_table[table_idx].vaddr = (void *)(addr + phdr->p_vaddr);
|
|
htlb_seg_table[table_idx].filesz = phdr->p_filesz;
|
|
htlb_seg_table[table_idx].memsz = phdr->p_memsz;
|
|
htlb_seg_table[table_idx].prot = prot;
|
|
@@ -634,8 +637,8 @@ static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
|
|
|
|
INFO("Segment %d (phdr %d): %#0lx-%#0lx (filesz=%#0lx) "
|
|
"(prot = %#0x)\n", table_idx, phnum,
|
|
- (unsigned long) phdr->p_vaddr,
|
|
- (unsigned long) phdr->p_vaddr + phdr->p_memsz,
|
|
+ (unsigned long) addr + phdr->p_vaddr,
|
|
+ (unsigned long) addr + phdr->p_vaddr + phdr->p_memsz,
|
|
(unsigned long) phdr->p_filesz, (unsigned int) prot);
|
|
|
|
return 0;
|
|
@@ -718,16 +721,19 @@ int parse_elf_normal(struct dl_phdr_info *info, size_t size, void *data)
|
|
|
|
seg_psize = segment_requested_page_size(&info->dlpi_phdr[i]);
|
|
if (seg_psize != page_size) {
|
|
- if (save_phdr(htlb_num_segs, i, &info->dlpi_phdr[i]))
|
|
+ if (save_phdr(htlb_num_segs, i, info->dlpi_addr,
|
|
+ &info->dlpi_phdr[i]))
|
|
return 1;
|
|
get_extracopy(&htlb_seg_table[htlb_num_segs],
|
|
- &info->dlpi_phdr[0], info->dlpi_phnum);
|
|
+ info->dlpi_addr, info->dlpi_phdr,
|
|
+ info->dlpi_phnum);
|
|
htlb_seg_table[htlb_num_segs].page_size = seg_psize;
|
|
htlb_num_segs++;
|
|
}
|
|
- start = ALIGN_DOWN(info->dlpi_phdr[i].p_vaddr, seg_psize);
|
|
- end = ALIGN(info->dlpi_phdr[i].p_vaddr +
|
|
- info->dlpi_phdr[i].p_memsz, seg_psize);
|
|
+ start = ALIGN_DOWN(info->dlpi_addr +
|
|
+ info->dlpi_phdr[i].p_vaddr, seg_psize);
|
|
+ end = ALIGN(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr +
|
|
+ info->dlpi_phdr[i].p_memsz, seg_psize);
|
|
|
|
segments[num_segs].page_size = seg_psize;
|
|
segments[num_segs].start = start;
|
|
@@ -771,8 +777,9 @@ int parse_elf_partial(struct dl_phdr_info *info, size_t size, void *data)
|
|
* in this forced way won't violate any contiguity
|
|
* constraints.
|
|
*/
|
|
- vaddr = hugetlb_next_slice_start(info->dlpi_phdr[i].p_vaddr);
|
|
- gap = vaddr - info->dlpi_phdr[i].p_vaddr;
|
|
+ vaddr = hugetlb_next_slice_start(info->dlpi_addr +
|
|
+ info->dlpi_phdr[i].p_vaddr);
|
|
+ gap = vaddr - (info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
|
|
slice_end = hugetlb_slice_end(vaddr);
|
|
/*
|
|
* we should stop remapping just before the slice
|
|
@@ -795,7 +802,8 @@ int parse_elf_partial(struct dl_phdr_info *info, size_t size, void *data)
|
|
}
|
|
memsz = hugetlb_prev_slice_end(vaddr + memsz) - vaddr;
|
|
|
|
- if (save_phdr(htlb_num_segs, i, &info->dlpi_phdr[i]))
|
|
+ if (save_phdr(htlb_num_segs, i, info->dlpi_addr,
|
|
+ &info->dlpi_phdr[i]))
|
|
return 1;
|
|
|
|
/*
|
|
--
|
|
1.8.3.1
|
|
|