]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Fix some libdwfl bias calculations.
authorRoland McGrath <roland@redhat.com>
Thu, 20 May 2010 07:04:59 +0000 (00:04 -0700)
committerRoland McGrath <roland@redhat.com>
Thu, 20 May 2010 07:04:59 +0000 (00:04 -0700)
libdwfl/ChangeLog
libdwfl/dwfl_module_getdwarf.c
libdwfl/linux-proc-maps.c

index 019dd1c0ec7a20d2e0a23fa481307c9dbccc5d98..347ebcf4fec9e2a8893cd3db3022e828ecdb2e56 100644 (file)
@@ -1,3 +1,12 @@
+2010-05-20  Roland McGrath  <roland@redhat.com>
+
+       * linux-proc-maps.c (find_sysinfo_ehdr): Renamed to ...
+       (grovel_auxv): ... this.  Take DWFL argument.
+       (dwfl_linux_proc_report): Update caller.
+
+       * dwfl_module_getdwarf.c (open_elf): Calculate alignment for bias
+       based on dwfl->segment_align or manifest alignment of MOD->low_addr.
+
 2010-05-19  Roland McGrath  <roland@redhat.com>
 
        * linux-kernel-modules.c (intuit_kernel_bounds): Rewritten.
index 6065257dfcf721cca5ff70c61c336082b8e5f37c..41ed0730e4a6b7e51772334c6c4d76f22c548f56 100644 (file)
@@ -112,8 +112,16 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
            goto elf_error;
          if (ph->p_type == PT_LOAD)
            {
-             file->bias = ((mod->low_addr & -ph->p_align)
-                           - (ph->p_vaddr & -ph->p_align));
+             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));
              break;
            }
        }
index 2206f63cbe29061abbb3969fd1b97ce22f111cb8..8504a5f3afc1a88668e300edecd0b3f59dd22f90 100644 (file)
@@ -1,5 +1,5 @@
 /* Standard libdwfl callbacks for debugging a live Linux process.
-   Copyright (C) 2005, 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
@@ -70,7 +70,7 @@
 /* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag.  */
 
 static int
-find_sysinfo_ehdr (pid_t pid, GElf_Addr *sysinfo_ehdr)
+grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
 {
   char *fname;
   if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
@@ -100,18 +100,30 @@ find_sysinfo_ehdr (pid_t pid, GElf_Addr *sysinfo_ehdr)
                if (d.a32[i].a_type == AT_SYSINFO_EHDR)
                  {
                    *sysinfo_ehdr = d.a32[i].a_un.a_val;
-                   nread = 0;
-                   break;
+                   if (dwfl->segment_align > 1)
+                     {
+                       nread = 0;
+                       break;
+                     }
                  }
+               else if (d.a32[i].a_type == AT_PAGESZ
+                        && dwfl->segment_align <= 1)
+                 dwfl->segment_align = d.a32[i].a_un.a_val;
              break;
            case 8:
              for (size_t i = 0; (char *) &d.a64[i] < &d.buffer[nread]; ++i)
                if (d.a64[i].a_type == AT_SYSINFO_EHDR)
                  {
                    *sysinfo_ehdr = d.a64[i].a_un.a_val;
-                   nread = 0;
-                   break;
+                   if (dwfl->segment_align > 1)
+                     {
+                       nread = 0;
+                       break;
+                     }
                  }
+               else if (d.a64[i].a_type == AT_PAGESZ
+                        && dwfl->segment_align <= 1)
+                 dwfl->segment_align = d.a64[i].a_un.a_val;
              break;
            default:
              abort ();
@@ -238,7 +250,7 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
 
   /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it.  */
   GElf_Addr sysinfo_ehdr = 0;
-  int result = find_sysinfo_ehdr (pid, &sysinfo_ehdr);
+  int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr);
   if (result != 0)
     return result;