diff options
author | Roland McGrath <roland@redhat.com> | 2010-11-12 16:46:47 -0800 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2010-11-12 16:46:47 -0800 |
commit | 1743d7f010bead5e869d097e23ce840583913381 (patch) | |
tree | 31a98ee593aca90ff62b849bb3c3a580b1465d48 | |
parent | 58af2001b92a8a8ee21a81b2845449ae8d038b7c (diff) | |
download | elfutils-1743d7f010bead5e869d097e23ce840583913381.tar.gz |
libdwfl: Revamp bias bookkeeping, account correctly for prelink REL->RELA segment inflation.
-rw-r--r-- | libdwfl/ChangeLog | 48 | ||||
-rw-r--r-- | libdwfl/cu.c | 2 | ||||
-rw-r--r-- | libdwfl/derelocate.c | 8 | ||||
-rw-r--r-- | libdwfl/dwfl_dwarf_line.c | 2 | ||||
-rw-r--r-- | libdwfl/dwfl_lineinfo.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_addrsym.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_build_id.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_dwarf_cfi.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_eh_cfi.c | 6 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getdwarf.c | 30 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getelf.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getsym.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_module_info.c | 8 | ||||
-rw-r--r-- | libdwfl/dwfl_nextcu.c | 4 | ||||
-rw-r--r-- | libdwfl/dwfl_report_elf.c | 13 | ||||
-rw-r--r-- | libdwfl/dwfl_segment_report_module.c | 12 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 62 | ||||
-rw-r--r-- | libdwfl/link_map.c | 10 | ||||
-rw-r--r-- | libdwfl/relocate.c | 4 |
19 files changed, 172 insertions, 61 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index cc6dfb5b..dd4eb10c 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,51 @@ +2010-11-12 Roland McGrath <roland@redhat.com> + + * libdwflP.h (struct Dwfl_Module): New member main_bias. + (dwfl_adjusted_address, dwfl_deadjust_address): Use it. + * dwfl_module_getdwarf.c (__libdwfl_getelf): Initialize it. + + * libdwflP.h (dwfl_deadjust_address): New function. + (dwfl_deadjust_dwarf_addr, dwfl_deadjust_st_value): New functions. + * cu.c (addrarange): Use dwfl_deadjust_dwarf_addr. + * dwfl_module_addrsym.c: Use dwfl_deadjust_st_value. + +2010-11-11 Roland McGrath <roland@redhat.com> + + * libdwflP.h (struct dwfl_file): Remove bias member. + Add vaddr and address_sync members instead. + (dwfl_adjusted_address): Calculate using vaddr. + (dwfl_adjusted_dwarf_addr): Calculate using address_sync and call that. + (dwfl_adjusted_st_value): Use one of those calls. + * dwfl_module_getdwarf.c (open_elf): Initialize vaddr and address_sync. + * dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise. + * derelocate.c (dwfl_module_relocations): Update ET_EXEC assertions. + * link_map.c (consider_executable): Adjust only MOD->low_addr for + detected PIE bias change. + + * libdwflP.h (dwfl_adjusted_dwarf_addr): New function. + * dwfl_module_info.c: Use it. + * cu.c (addrarange): Likewise. + * dwfl_dwarf_line.c: Likewise. + * dwfl_module_dwarf_cfi.c: Likewise. + * dwfl_lineinfo.c: Likewise. + * dwfl_nextcu.c: Likewise. + * dwfl_module_getdwarf.c (dwfl_module_getdwarf): Likewise. + + * libdwflP.h (dwfl_adjusted_st_value): New function. + * relocate.c (resolve_symbol): Use it. + * dwfl_module_getsym.c: Likewise. + * dwfl_module_addrsym.c: Likewise. + * dwfl_module_info.c: Likewise. + + * libdwflP.h (dwfl_adjusted_address): New function. + * dwfl_module_build_id.c (__libdwfl_find_build_id): Use it. + * relocate.c (__libdwfl_relocate_value): Likewise. + * derelocate.c (cache_sections): Likewise. + (dwfl_module_address_section): Likewise. + * dwfl_module_getelf.c: Likewise. + * dwfl_module_eh_cfi.c: Likewise. + * link_map.c (consider_executable): Likewise. + 2010-08-24 Roland McGrath <roland@redhat.com> * dwfl_dwarf_line.c: New file. diff --git a/libdwfl/cu.c b/libdwfl/cu.c index 5f73d2a3..515aff3b 100644 --- a/libdwfl/cu.c +++ b/libdwfl/cu.c @@ -106,7 +106,7 @@ addrarange (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_arange **arange) } /* The address must be inside the module to begin with. */ - addr -= mod->debug.bias; + addr = dwfl_deadjust_dwarf_addr (mod, addr); /* The ranges are sorted by address, so we can use binary search. */ size_t l = 0, u = mod->naranges; diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c index 56ba25af..483b75eb 100644 --- a/libdwfl/derelocate.c +++ b/libdwfl/derelocate.c @@ -134,7 +134,7 @@ cache_sections (Dwfl_Module *mod) newref->scn = scn; newref->relocs = NULL; newref->name = name; - newref->start = shdr->sh_addr + mod->main.bias; + newref->start = dwfl_adjusted_address (mod, shdr->sh_addr); newref->end = newref->start + shdr->sh_size; newref->next = refs; refs = newref; @@ -239,8 +239,8 @@ dwfl_module_relocations (Dwfl_Module *mod) return 1; case ET_EXEC: - assert (mod->main.bias == 0); - assert (mod->debug.bias == 0); + assert (mod->main.vaddr == mod->low_addr); + assert (mod->debug.address_sync == mod->main.address_sync); break; } @@ -406,7 +406,7 @@ dwfl_module_address_section (Dwfl_Module *mod, Dwarf_Addr *address, } } - *bias = mod->main.bias; + *bias = dwfl_adjusted_address (mod, 0); return mod->reloc_info->refs[idx].scn; } INTDEF (dwfl_module_address_section) diff --git a/libdwfl/dwfl_dwarf_line.c b/libdwfl/dwfl_dwarf_line.c index ee522db4..eb085e4a 100644 --- a/libdwfl/dwfl_dwarf_line.c +++ b/libdwfl/dwfl_dwarf_line.c @@ -59,6 +59,6 @@ dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias) struct dwfl_cu *cu = dwfl_linecu (line); const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; - *bias = cu->mod->debug.bias; + *bias = dwfl_adjusted_dwarf_addr (cu->mod, 0); return (Dwarf_Line *) info; } diff --git a/libdwfl/dwfl_lineinfo.c b/libdwfl/dwfl_lineinfo.c index 0d8a6887..6049de84 100644 --- a/libdwfl/dwfl_lineinfo.c +++ b/libdwfl/dwfl_lineinfo.c @@ -1,5 +1,5 @@ /* Get information from a source line record returned by libdwfl. - Copyright (C) 2005, 2006 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -61,7 +61,7 @@ dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; if (addr != NULL) - *addr = info->addr + cu->mod->debug.bias; + *addr = dwfl_adjusted_dwarf_addr (cu->mod, info->addr); if (linep != NULL) *linep = info->line; if (colp != NULL) diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c index 72280d11..a9f98f44 100644 --- a/libdwfl/dwfl_module_addrsym.c +++ b/libdwfl/dwfl_module_addrsym.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -71,7 +71,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, /* Figure out what section ADDR lies in. */ if (addr_shndx == SHN_UNDEF) { - GElf_Addr mod_addr = addr - mod->symfile->bias; + GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, addr); Elf_Scn *scn = NULL; addr_shndx = SHN_ABS; while ((scn = elf_nextscn (mod->symfile->elf, scn)) != NULL) diff --git a/libdwfl/dwfl_module_build_id.c b/libdwfl/dwfl_module_build_id.c index 9dc7f678..f9888660 100644 --- a/libdwfl/dwfl_module_build_id.c +++ b/libdwfl/dwfl_module_build_id.c @@ -124,7 +124,7 @@ __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf) phdr->p_offset, phdr->p_filesz, ELF_T_NHDR), - phdr->p_vaddr + mod->main.bias); + dwfl_adjusted_address (mod, phdr->p_vaddr)); } } else @@ -139,7 +139,7 @@ __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf) if (!(shdr->sh_flags & SHF_ALLOC)) vaddr = NO_VADDR; else if (mod->e_type != ET_REL) - vaddr = shdr->sh_addr + mod->main.bias; + vaddr = dwfl_adjusted_address (mod, shdr->sh_addr); else if (__libdwfl_relocate_value (mod, elf, &shstrndx, elf_ndxscn (scn), &vaddr)) vaddr = NO_VADDR; diff --git a/libdwfl/dwfl_module_dwarf_cfi.c b/libdwfl/dwfl_module_dwarf_cfi.c index e851a1f4..96e60fbf 100644 --- a/libdwfl/dwfl_module_dwarf_cfi.c +++ b/libdwfl/dwfl_module_dwarf_cfi.c @@ -1,5 +1,5 @@ /* Find DWARF CFI for a module in libdwfl. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -81,7 +81,7 @@ dwfl_module_dwarf_cfi (mod, bias) if (mod->dwarf_cfi != NULL) { - *bias = mod->debug.bias; + *bias = dwfl_adjusted_dwarf_addr (mod, 0); return mod->dwarf_cfi; } diff --git a/libdwfl/dwfl_module_eh_cfi.c b/libdwfl/dwfl_module_eh_cfi.c index 36a495f1..79c8279c 100644 --- a/libdwfl/dwfl_module_eh_cfi.c +++ b/libdwfl/dwfl_module_eh_cfi.c @@ -1,5 +1,5 @@ /* Find EH CFI for a module in libdwfl. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -60,7 +60,7 @@ dwfl_module_eh_cfi (mod, bias) if (mod->eh_cfi != NULL) { - *bias = mod->main.bias; + *bias = dwfl_adjusted_address (mod, 0); return mod->eh_cfi; } @@ -71,7 +71,7 @@ dwfl_module_eh_cfi (mod, bias) return NULL; } - *bias = mod->main.bias; + *bias = dwfl_adjusted_address (mod, 0); return __libdwfl_set_cfi (mod, &mod->eh_cfi, INTUSE(dwarf_getcfi_elf) (mod->main.elf)); } diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 41ed0730..d89081b7 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -93,35 +93,23 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file) return DWFL_E (LIBELF, elf_errno ()); } - /* The addresses in an ET_EXEC file are absolute. The lowest p_vaddr of - the main file can differ from that of the debug file due to prelink. - But that doesn't not change addresses that symbols, debuginfo, or - sh_addr of any program sections refer to. */ - file->bias = 0; - if (mod->e_type != ET_EXEC) + if (mod->e_type != ET_REL) { size_t phnum; if (unlikely (elf_getphdrnum (file->elf, &phnum) != 0)) goto elf_error; + file->vaddr = file->address_sync = 0; for (size_t i = 0; i < phnum; ++i) { GElf_Phdr ph_mem; GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem); - if (ph == NULL) + if (unlikely (ph == NULL)) goto elf_error; if (ph->p_type == PT_LOAD) { - GElf_Addr align = mod->dwfl->segment_align; - if (align <= 1) - { - if ((mod->low_addr & (ph->p_align - 1)) == 0) - align = ph->p_align; - else - align = ((GElf_Addr) 1 << ffsll (mod->low_addr)) >> 1; - } - - file->bias = ((mod->low_addr & -align) - (ph->p_vaddr & -align)); + file->vaddr = ph->p_vaddr & -ph->p_align; + file->address_sync = ph->p_vaddr + ph->p_memsz; break; } } @@ -130,7 +118,7 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file) mod->e_type = ehdr->e_type; /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN. */ - if (mod->e_type == ET_EXEC && file->bias != 0) + if (mod->e_type == ET_EXEC && file->vaddr != mod->low_addr) mod->e_type = ET_DYN; return DWFL_E_NOERROR; @@ -198,6 +186,8 @@ __libdwfl_getelf (Dwfl_Module *mod) mod->main.fd = -1; } } + + mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr; } /* Search an ELF file for a ".gnu_debuglink" section. */ @@ -733,7 +723,7 @@ find_dw (Dwfl_Module *mod) { case DWFL_E_NOERROR: mod->debug.elf = mod->main.elf; - mod->debug.bias = mod->main.bias; + mod->debug.address_sync = mod->main.address_sync; return; case DWFL_E_NO_DWARF: @@ -782,7 +772,7 @@ dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias) (void) __libdwfl_relocate (mod, mod->debug.elf, false); } - *bias = mod->debug.bias; + *bias = dwfl_adjusted_dwarf_addr (mod, 0); return mod->dw; } diff --git a/libdwfl/dwfl_module_getelf.c b/libdwfl/dwfl_module_getelf.c index 6414a9d3..b4e4a2b7 100644 --- a/libdwfl/dwfl_module_getelf.c +++ b/libdwfl/dwfl_module_getelf.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -78,7 +78,7 @@ dwfl_module_getelf (Dwfl_Module *mod, GElf_Addr *loadbase) } } - *loadbase = mod->main.bias; + *loadbase = dwfl_adjusted_address (mod, 0); return mod->main.elf; } diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c index f78e6ec0..6bc063bb 100644 --- a/libdwfl/dwfl_module_getsym.c +++ b/libdwfl/dwfl_module_getsym.c @@ -1,5 +1,5 @@ /* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2006,2007,2009 Red Hat, Inc. + Copyright (C) 2006-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -114,7 +114,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx, } else if (alloc) /* Apply the bias to the symbol value. */ - sym->st_value += mod->symfile->bias; + sym->st_value = dwfl_adjusted_st_value (mod, sym->st_value); break; } diff --git a/libdwfl/dwfl_module_info.c b/libdwfl/dwfl_module_info.c index 759cb621..bfde6fc1 100644 --- a/libdwfl/dwfl_module_info.c +++ b/libdwfl/dwfl_module_info.c @@ -1,5 +1,5 @@ /* Return information about a module. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -66,9 +66,11 @@ dwfl_module_info (Dwfl_Module *mod, void ***userdata, *end = mod->high_addr; if (dwbias) - *dwbias = mod->debug.elf == NULL ? (Dwarf_Addr) -1 : mod->debug.bias; + *dwbias = (mod->debug.elf == NULL ? (Dwarf_Addr) -1 + : dwfl_adjusted_dwarf_addr (mod, 0)); if (symbias) - *symbias = mod->symfile == NULL ? (Dwarf_Addr) -1 : mod->symfile->bias; + *symbias = (mod->symfile == NULL ? (Dwarf_Addr) -1 + : dwfl_adjusted_st_value (mod, 0)); if (mainfile) *mainfile = mod->main.name; diff --git a/libdwfl/dwfl_nextcu.c b/libdwfl/dwfl_nextcu.c index 6db3e0f1..90862d20 100644 --- a/libdwfl/dwfl_nextcu.c +++ b/libdwfl/dwfl_nextcu.c @@ -1,5 +1,5 @@ /* Iterate through DWARF compilation units across all modules. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -75,7 +75,7 @@ dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias) if (cu != NULL) { - *bias = mod->debug.bias; + *bias = dwfl_adjusted_dwarf_addr (mod, 0); return &cu->die; } diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c index 062a647f..4c4132b1 100644 --- a/libdwfl/dwfl_report_elf.c +++ b/libdwfl/dwfl_report_elf.c @@ -72,6 +72,8 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, return NULL; } + GElf_Addr vaddr = 0; + GElf_Addr address_sync = 0; GElf_Addr start = 0, end = 0, bias = 0; switch (ehdr->e_type) { @@ -198,13 +200,15 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, goto elf_error; if (ph->p_type == PT_LOAD) { + vaddr = ph->p_vaddr & -ph->p_align; + address_sync = ph->p_vaddr + ph->p_memsz; if ((base & (ph->p_align - 1)) != 0) base = (base + ph->p_align - 1) & -ph->p_align; start = base + (ph->p_vaddr & -ph->p_align); break; } } - bias = base; + bias = start - vaddr; for (size_t i = phnum; i-- > 0;) { @@ -248,13 +252,16 @@ __libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, if (m->main.elf == NULL) { m->main.elf = elf; - m->main.bias = bias; + m->main.vaddr = vaddr; + m->main.address_sync = address_sync; + m->main_bias = bias; m->e_type = ehdr->e_type; } else { elf_end (elf); - if (m->main.bias != base) + if (m->main_bias != bias + || m->main.vaddr != vaddr || m->main.address_sync != address_sync) goto overlap; } } diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 3f77cfc7..012a0fde 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -270,6 +270,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, /* Collect the unbiased bounds of the module here. */ GElf_Addr module_start = -1l; GElf_Addr module_end = 0; + GElf_Addr module_address_sync = 0; /* If we see PT_DYNAMIC, record it here. */ GElf_Addr dyn_vaddr = 0; @@ -400,9 +401,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, found_bias = true; } - vaddr &= -align; - if (vaddr < module_start) - module_start = vaddr; + if ((vaddr & -align) < module_start) + { + module_start = vaddr & -align; + module_address_sync = vaddr + memsz; + } if (module_end < vaddr_end) module_end = vaddr_end; @@ -662,7 +665,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, { /* Install the file in the module. */ mod->main.elf = elf; - mod->main.bias = bias; + mod->main.vaddr = module_start - bias; + mod->main.address_sync = module_address_sync; } return finish (); diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index e4c7e7c8..1003b2d3 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -140,7 +140,22 @@ struct dwfl_file bool relocated; /* Partial relocation of all sections done. */ Elf *elf; - GElf_Addr bias; /* Actual load address - p_vaddr. */ + + /* This is the lowest p_vaddr in this ELF file, aligned to p_align. + For a file without phdrs, this is zero. */ + GElf_Addr vaddr; + + /* This is an address chosen for synchronization between the main file + and the debug file. In a file without phdrs, this is zero. In + other files it is the address at the end of the first PT_LOAD + segment. When prelink converts REL to RELA in an ET_DYN file, it + expands the space between the beginning of the segment and the + actual code/data addresses. Since that change wasn't made in the + debug file, the distance from p_vaddr to an address of interest (in + an st_value or DWARF data) now differs between the main and debug + files. The distance from address_sync to an address of interest + remains consistent. */ + GElf_Addr address_sync; }; struct Dwfl_Module @@ -154,6 +169,7 @@ struct Dwfl_Module GElf_Addr low_addr, high_addr; struct dwfl_file main, debug; + GElf_Addr main_bias; Ebl *ebl; GElf_Half e_type; /* GElf_Ehdr.e_type cache. */ Dwfl_Error elferr; /* Previous failure to open main file. */ @@ -236,6 +252,50 @@ dwfl_linecu_inline (const Dwfl_Line *line) } #define dwfl_linecu dwfl_linecu_inline +static inline GElf_Addr +dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr) +{ + return addr + mod->main_bias; +} + +static inline GElf_Addr +dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr) +{ + return addr - mod->main_bias; +} + +static inline Dwarf_Addr +dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr) +{ + return dwfl_adjusted_address (mod, (addr + - mod->debug.address_sync + + mod->main.address_sync)); +} + +static inline Dwarf_Addr +dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr) +{ + return (dwfl_deadjust_address (mod, addr) + - mod->main.address_sync + + mod->debug.address_sync); +} + +static inline GElf_Addr +dwfl_adjusted_st_value (Dwfl_Module *mod, GElf_Addr addr) +{ + if (mod->symfile == &mod->main) + return dwfl_adjusted_address (mod, addr); + return dwfl_adjusted_dwarf_addr (mod, addr); +} + +static inline GElf_Addr +dwfl_deadjust_st_value (Dwfl_Module *mod, GElf_Addr addr) +{ + if (mod->symfile == &mod->main) + return dwfl_deadjust_address (mod, addr); + return dwfl_deadjust_dwarf_addr (mod, addr); +} + /* This describes a contiguous address range that lies in a single CU. We condense runs of Dwarf_Arange entries for the same CU into this. */ struct dwfl_arange diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index 8ec06269..05839b3a 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -515,11 +515,11 @@ consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, /* If we're changing the module's address range, we've just invalidated the module lookup table. */ - if (bias != mod->main.bias) + GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0); + if (bias != mod_bias) { - mod->low_addr -= mod->main.bias; - mod->high_addr -= mod->main.bias; - mod->main.bias = bias; + mod->low_addr -= mod_bias; + mod->high_addr -= mod_bias; mod->low_addr += bias; mod->high_addr += bias; @@ -554,7 +554,7 @@ consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, if (d_val_vaddr != 0) { /* Now we have the final address from which to read &r_debug. */ - d_val_vaddr += mod->main.bias; + d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr); void *buffer = NULL; size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]); diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 0075c7f9..95206f47 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -99,7 +99,7 @@ __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, if (refshdr->sh_flags & SHF_ALLOC) /* Apply the adjustment. */ - *value += refshdr->sh_addr + mod->main.bias; + *value += dwfl_adjusted_address (mod, refshdr->sh_addr); return DWFL_E_NOERROR; } @@ -275,7 +275,7 @@ resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab, if (m->e_type != ET_REL) { - sym->st_value += m->symfile->bias; + sym->st_value = dwfl_adjusted_st_value (m, sym->st_value); return DWFL_E_NOERROR; } |