Hi Roland, jankratochvil/auxv32
On Thu, 11 Oct 2012 00:27:35 +0200, Roland McGrath wrote: > The problem is indeed obvious. I really wish there were a better way to > detect the bit-width of the process than looking at /proc/PID/exe, but > perhaps there really isn't. > > What about just looking at the first 8 bytes of the auxv data? The first > element is never AT_NULL, so it will have a nonzero a_type. No a_type > value will ever be more than UINT32_MAX. So for big-endian, the first four > bytes being zero says it's 64-bit. For little-endian, it's not so easy > without assuming that the first a_val is nonzero. That's actually reliable > enough in practice, but it feels wrong. Maybe there is something better > for little-endian that I'm not thinking of. I had similar concerns. Done the other changes. Thanks, Jan commit 6c7496074e45f285312ceb076c08091652998dfb Author: Jan Kratochvil <[email protected]> Date: Wed Oct 10 20:42:30 2012 +0200 libdwfl/ linux-proc-maps.c: Include system.h. (PROCEXEFMT, get_pid_class): New. (grovel_auxv): New parameter pid_class. Use it. (dwfl_linux_proc_report): New variable pid_class, initialize it by get_pid_class, use it for grovel_auxv. Signed-off-by: Jan Kratochvil <[email protected]> diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 189d3b7..c18362c 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,11 @@ +2012-10-11 Jan Kratochvil <[email protected]> + + * linux-proc-maps.c: Include system.h. + (PROCEXEFMT, get_pid_class): New. + (grovel_auxv): New parameter pid_class. Use it. + (dwfl_linux_proc_report): New variable pid_class, initialize it by + get_pid_class, use it for grovel_auxv. + 2012-10-10 Jan Kratochvil <[email protected]> * dwfl_segment_report_module.c (dwfl_segment_report_module): diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c index 4fbe90d..2ac0e3e 100644 --- a/libdwfl/linux-proc-maps.c +++ b/libdwfl/linux-proc-maps.c @@ -39,17 +39,47 @@ #include <unistd.h> #include <assert.h> #include <endian.h> +#include "system.h" #define PROCMAPSFMT "/proc/%d/maps" #define PROCMEMFMT "/proc/%d/mem" #define PROCAUXVFMT "/proc/%d/auxv" +#define PROCEXEFMT "/proc/%d/exe" +/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable. Return + ELFCLASSNONE for an error. */ + +static unsigned char +get_pid_class (pid_t pid) +{ + char *fname; + if (asprintf (&fname, PROCEXEFMT, pid) < 0) + return ELFCLASSNONE; + + int fd = open64 (fname, O_RDONLY); + free (fname); + if (fd < 0) + return ELFCLASSNONE; + + unsigned char buf[EI_CLASS + 1]; + ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0); + close (fd); + if (nread != sizeof (buf) || buf[EI_MAG0] != ELFMAG0 + || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2 + || buf[EI_MAG3] != ELFMAG3 + || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32)) + return ELFCLASSNONE; + + return buf[EI_CLASS]; +} + /* 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, unsigned char pid_class, + GElf_Addr *sysinfo_ehdr) { char *fname; if (asprintf (&fname, PROCAUXVFMT, pid) < 0) @@ -72,9 +102,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 (pid_class) { - case 4: + case ELFCLASS32: for (size_t i = 0; (char *) &d.a32[i] < &d.buffer[nread]; ++i) if (d.a32[i].a_type == AT_SYSINFO_EHDR) { @@ -89,7 +119,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 ELFCLASS64: for (size_t i = 0; (char *) &d.a64[i] < &d.buffer[nread]; ++i) if (d.a64[i].a_type == AT_SYSINFO_EHDR) { @@ -227,9 +257,13 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid) if (dwfl == NULL) return -1; + unsigned char pid_class = get_pid_class (pid); + if (pid_class == ELFCLASSNONE) + 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, pid_class, &sysinfo_ehdr); if (result != 0) return result; _______________________________________________ elfutils-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel
