Hi Roland, jankratochvil/auxv32
the problem is obvious I think. I do not see how to write an easy testcase. It is tested on the jankratochvil/unwind branch but a more minimal testcase would just be a partial duplication of that testcase also involving biarch compilation and ptrace attachment. FAIL->PASS 0xf7502000 0xf76b0000 /lib/libc-2.14.90.so 0xf76b3000 0xf76cc000 /lib/libpthread-2.14.90.so 0xf76ec000 0xf770f000 /lib/ld-2.14.90.so 0xf770f000 0xf7711000 /home/jkratoch/redhat/elfutils-clean/tests/backtrace-child-biarch TID 29871: # 0 0xf76eb430 (null) No DWARF information found [...] -> 0xf74ff000 0xf76ad000 /lib/libc-2.14.90.so 0xf76b0000 0xf76c9000 /lib/libpthread-2.14.90.so 0xf76e8000 0xf76e9000 [vdso: 29682] 0xf76e9000 0xf770c000 /lib/ld-2.14.90.so 0xf770c000 0xf770e000 /home/jkratoch/redhat/elfutils-clean/tests/backtrace-child-biarch TID 29683: # 0 0xf76e8430 __kernel_vsyscall [...] One can see [vdso: 29682] is not reported above at all. Thanks, Jan commit 77d700999426dec7004ea41af89376580aab264c Author: Jan Kratochvil <[email protected]> Date: Wed Oct 10 20:42:30 2012 +0200 libdwfl/ 2012-10-10 Jan Kratochvil <[email protected]> * linux-proc-maps.c (PROCEXEFMT, get_pid_width): New. (grovel_auxv): New parameter width. Use it. (dwfl_linux_proc_report): New variable width, initialize it by get_pid_width, use it for grovel_auxv. Signed-off-by: Jan Kratochvil <[email protected]> diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c index 4fbe90d..327eb32 100644 --- a/libdwfl/linux-proc-maps.c +++ b/libdwfl/linux-proc-maps.c @@ -44,12 +44,39 @@ #define PROCMAPSFMT "/proc/%d/maps" #define PROCMEMFMT "/proc/%d/mem" #define PROCAUXVFMT "/proc/%d/auxv" +#define PROCEXEFMT "/proc/%d/exe" +/* Return 64 for 64-bit main ELF executable, 32 accordingly otherwise. + Return -1 for errors. */ + +static int +get_pid_width (pid_t pid) +{ + char *fname; + if (asprintf (&fname, PROCEXEFMT, pid) < 0) + return -1; + + int fd = open64 (fname, O_RDONLY); + free (fname); + if (fd < 0) + return -1; + + unsigned char buf[5]; + ssize_t nread = read (fd, &buf, sizeof buf); + close (fd); + if (nread != sizeof (buf) || buf[0] != ELFMAG0 || buf[1] != ELFMAG1 + || buf[2] != ELFMAG2 || buf[3] != ELFMAG3 + || (buf[4] != ELFCLASS64 && buf[4] != ELFCLASS32)) + return -1; + + return buf[4] == ELFCLASS64 ? 64 : 32; +} + /* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag. */ static int -grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr) +grovel_auxv (pid_t pid, Dwfl *dwfl, int width, GElf_Addr *sysinfo_ehdr) { char *fname; if (asprintf (&fname, PROCAUXVFMT, pid) < 0) @@ -72,9 +99,9 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr) nread = read (fd, &d, sizeof d); if (nread > 0) { - switch (sizeof (long int)) + switch (width) { - case 4: + case 32: for (size_t i = 0; (char *) &d.a32[i] < &d.buffer[nread]; ++i) if (d.a32[i].a_type == AT_SYSINFO_EHDR) { @@ -89,7 +116,7 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr) && dwfl->segment_align <= 1) dwfl->segment_align = d.a32[i].a_un.a_val; break; - case 8: + case 64: for (size_t i = 0; (char *) &d.a64[i] < &d.buffer[nread]; ++i) if (d.a64[i].a_type == AT_SYSINFO_EHDR) { @@ -227,9 +254,13 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid) if (dwfl == NULL) return -1; + int width = get_pid_width (pid); + if (width == -1) + return -1; + /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it. */ GElf_Addr sysinfo_ehdr = 0; - int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr); + int result = grovel_auxv (pid, dwfl, width, &sysinfo_ehdr); if (result != 0) return result; _______________________________________________ elfutils-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel
