summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2010-05-20 00:04:59 -0700
committerRoland McGrath <roland@redhat.com>2010-05-20 00:04:59 -0700
commita0635db0fbe13ad7b531ee99eeb063a8eded923c (patch)
tree9daf2f20c1577bc03ba783acf72a41ec9390a74d
parentbe9c4d7683a759ac13162c11af3e04907dccd922 (diff)
downloadelfutils-a0635db0fbe13ad7b531ee99eeb063a8eded923c.tar.gz
Fix some libdwfl bias calculations.
-rw-r--r--libdwfl/ChangeLog9
-rw-r--r--libdwfl/dwfl_module_getdwarf.c12
-rw-r--r--libdwfl/linux-proc-maps.c26
3 files changed, 38 insertions, 9 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 019dd1c0..347ebcf4 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -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.
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 6065257d..41ed0730 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -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;
}
}
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 2206f63c..8504a5f3 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -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;