This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[patch] Fix 64-bit->32-bit vDSO reporting
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Wed, 10 Oct 2012 20:56:43 +0200
- Subject: [patch] Fix 64-bit->32-bit vDSO reporting
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 <jan.kratochvil@redhat.com>
Date: Wed Oct 10 20:42:30 2012 +0200
libdwfl/
2012-10-10 Jan Kratochvil <jan.kratochvil@redhat.com>
* 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 <jan.kratochvil@redhat.com>
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;