From a0635db0fbe13ad7b531ee99eeb063a8eded923c Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 20 May 2010 00:04:59 -0700 Subject: Fix some libdwfl bias calculations. --- libdwfl/ChangeLog | 9 +++++++++ libdwfl/dwfl_module_getdwarf.c | 12 ++++++++++-- libdwfl/linux-proc-maps.c | 26 +++++++++++++++++++------- 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 + + * 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 * 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; -- cgit v1.2.1