]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwfl: Revamp bias bookkeeping, account correctly for prelink REL->RELA segment...
authorRoland McGrath <roland@redhat.com>
Sat, 13 Nov 2010 00:46:47 +0000 (16:46 -0800)
committerRoland McGrath <roland@redhat.com>
Sat, 13 Nov 2010 00:46:47 +0000 (16:46 -0800)
19 files changed:
libdwfl/ChangeLog
libdwfl/cu.c
libdwfl/derelocate.c
libdwfl/dwfl_dwarf_line.c
libdwfl/dwfl_lineinfo.c
libdwfl/dwfl_module_addrsym.c
libdwfl/dwfl_module_build_id.c
libdwfl/dwfl_module_dwarf_cfi.c
libdwfl/dwfl_module_eh_cfi.c
libdwfl/dwfl_module_getdwarf.c
libdwfl/dwfl_module_getelf.c
libdwfl/dwfl_module_getsym.c
libdwfl/dwfl_module_info.c
libdwfl/dwfl_nextcu.c
libdwfl/dwfl_report_elf.c
libdwfl/dwfl_segment_report_module.c
libdwfl/libdwflP.h
libdwfl/link_map.c
libdwfl/relocate.c

index cc6dfb5bb282ea4b752ce5b6bd4ed05d7489fc3e..dd4eb10c7bdcf36914ab5f1576bfa339cb498064 100644 (file)
@@ -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.
index 5f73d2a36da31b794c4ca10a4d32948497ff9456..515aff3bab4f1bc37a2213303c257e87b2efca46 100644 (file)
@@ -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;
index 56ba25af27f3129cb68938500591ed23d5826474..483b75eb40c750e2b6bec1aba023d9af950e2907 100644 (file)
@@ -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)
index ee522db4f1ee3835525286ee21fac7edf69e4351..eb085e4a70ebd39865baacb805dae47b5465328b 100644 (file)
@@ -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;
 }
index 0d8a6887ee40f0e5c7d10a44f64afb07527d0709..6049de84b7b5f51ae77f7fc5f4ed5fe2908911f3 100644 (file)
@@ -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)
index 72280d118c8418fe1ad029b3bcfff20183ef6f74..a9f98f4483484a5df885405f9c8815307b6a0483 100644 (file)
@@ -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)
index 9dc7f6780b731c12620c75782d0c661ec18a9c2e..f9888660d350a1faa5404d90ee796707cd1f9cdc 100644 (file)
@@ -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;
index e851a1f47c29c4263f60d8d59a8a59dcd096e04f..96e60fbf78648751b1db04a8e3be3f2605d861ff 100644 (file)
@@ -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;
     }
 
index 36a495f1c60823c2f92b5229787336872bd578cf..79c8279c523bcf3e301dd49041b5c3bdf8ddbbc5 100644 (file)
@@ -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));
 }
index 41ed0730e4a6b7e51772334c6c4d76f22c548f56..d89081b7f25d0300f1fbe52823f5ad3071ed80cb 100644 (file)
@@ -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;
     }
 
index 6414a9d3b887f4d43606b1ed9715d244e457a205..b4e4a2b7c11374bcf9b1807f69d8353e459e1c73 100644 (file)
@@ -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;
     }
 
index f78e6ec03fdcf3fc3296705d5bf319dbd8974b94..6bc063bb1f3d0502436f9af5ed7cd30e5594e372 100644 (file)
@@ -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;
     }
 
index 759cb6216e9271c4c2cc93f689922917ea59077e..bfde6fc1d899b0165bc0e3ea641744dc940b61ae 100644 (file)
@@ -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;
index 6db3e0f14cd687dd9cd123812e101a0a75fdfb6f..90862d208f9535b8ad92c9e53b629cb448ba0a9a 100644 (file)
@@ -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;
        }
 
index 062a647fd214f9f3b0b7f7069b382a2fdf9bace4..4c4132b1f8815af35655f15066624129a915b5fe 100644 (file)
@@ -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;
        }
     }
index 3f77cfc73f0cb36298e95160cef01b152a787889..012a0fdeb61be330dc262d0f9849f18336900cb4 100644 (file)
@@ -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 ();
index e4c7e7c828a809e17b2352cf5689202448bbf32b..1003b2d3d04055764ffdfe781018d922b6cb1f94 100644 (file)
@@ -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
index 8ec06269c92411df995ca7089a63e7df4f2de959..05839b3aad80e3b9fb8f39fe68396b1cefd57c33 100644 (file)
@@ -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]);
index 0075c7f90291b82d98389837712908dfa5197278..95206f479b8a85ccf7260bbb7a6eb79bbdfb129a 100644 (file)
@@ -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;
                  }