summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2013-09-26 00:39:34 +0200
committerPetr Machata <pmachata@redhat.com>2013-09-30 13:43:57 +0200
commitab22410aed2732016c598c47102d47df659ede0c (patch)
treeb1c50ab75e8f9b3ee8a575fdd47a156bb37f8521
parent74f9b7337562c06a93722ad757d258db8f082663 (diff)
downloadelfutils-ab22410aed2732016c598c47102d47df659ede0c.tar.gz
Show contents NT_SIGINFO core note in readelf
Signed-off-by: Petr Machata <pmachata@redhat.com>
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c103
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/run-readelf-mixed-corenote.sh59
-rw-r--r--tests/testfile71.bz2bin0 -> 18164 bytes
6 files changed, 174 insertions, 2 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 6788087d..9d4c2e2c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-26 Petr Machata <pmachata@redhat.com>
+
+ * readelf.c (handle_siginfo_note): New function.
+ (handle_notes_data): Call it to handle NT_SIGINFO notes.
+ (buf_read_int, buf_read_ulong, buf_has_data): New functions.
+
2013-08-13 Mark Wielaard <mjw@redhat.com>
* addr2line.c (options): Add "inlines", 'i'.
diff --git a/src/readelf.c b/src/readelf.c
index 119c1000..da3661c0 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -42,6 +42,7 @@
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
+#include <signal.h>
#include <system.h>
#include "../libelf/libelfP.h"
@@ -8616,6 +8617,104 @@ handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
}
}
+static bool
+buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
+{
+ return ptr < end && (size_t) (end - ptr) >= sz;
+}
+
+static bool
+buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
+ int *retp)
+{
+ if (! buf_has_data (*ptrp, end, 4))
+ return false;
+
+ *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
+ return true;
+}
+
+static bool
+buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
+ uint64_t *retp)
+{
+ size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
+ if (! buf_has_data (*ptrp, end, sz))
+ return false;
+
+ union
+ {
+ uint64_t u64;
+ uint32_t u32;
+ } u;
+
+ *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sizeof u);
+
+ if (sz == 4)
+ *retp = u.u32;
+ else
+ *retp = u.u64;
+ return true;
+}
+
+static void
+handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
+{
+ Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
+ if (data == NULL)
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
+
+ unsigned char const *ptr = data->d_buf;
+ unsigned char const *const end = data->d_buf + data->d_size;
+
+ /* Siginfo head is three ints: signal number, error number, origin
+ code. */
+ int si_signo, si_errno, si_code;
+ if (! buf_read_int (core, &ptr, end, &si_signo)
+ || ! buf_read_int (core, &ptr, end, &si_errno)
+ || ! buf_read_int (core, &ptr, end, &si_code))
+ {
+ fail:
+ printf (" Not enough data in NT_SIGINFO note.\n");
+ return;
+ }
+
+ /* Next is a pointer-aligned union of structures. On 64-bit
+ machines, that implies a word of padding. */
+ if (gelf_getclass (core) == ELFCLASS64)
+ ptr += 4;
+
+ printf (" si_signo: %d, si_errno: %d, si_code: %d\n",
+ si_signo, si_errno, si_code);
+
+ if (si_code > 0)
+ switch (si_signo)
+ {
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ {
+ uint64_t addr;
+ if (! buf_read_ulong (core, &ptr, end, &addr))
+ goto fail;
+ printf (" fault address: %#" PRIx64 "\n", addr);
+ break;
+ }
+ default:
+ ;
+ }
+ else if (si_code == SI_USER)
+ {
+ int pid, uid;
+ if (! buf_read_int (core, &ptr, end, &pid)
+ || ! buf_read_int (core, &ptr, end, &uid))
+ goto fail;
+ printf (" sender PID: %d, sender UID: %d\n", pid, uid);
+ }
+}
+
static void
handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
const char *name, const void *desc)
@@ -8689,6 +8788,10 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
&& !memcmp (name, "CORE", 4))
handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
start + desc_offset);
+ else if (nhdr.n_type == NT_SIGINFO
+ && nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
+ handle_siginfo_note (ebl->elf, nhdr.n_descsz,
+ start + desc_offset);
else
handle_core_note (ebl, &nhdr, name, desc);
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 34cffd42..7e716616 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-26 Petr Machata <pmachata@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): Add testfile71.bz2.
+ * run-readelf-mixed-corenote.sh: New test for this file.
+ * testfile71.bz2: New file.
+
2013-09-20 Mark Wielaard <mjw@redhat.com>
* allfcts.c (cb): Return DWARF_CB_ABORT.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 58db6c36..0024395d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -198,7 +198,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-readelf-mixed-corenote.sh testfile63.bz2 testfile64.bz2 \
testfile65.bz2 testfile67.bz2 testfile68.bz2 \
testfile69.core.bz2 testfile69.so.bz2 \
- testfile70.core.bz2 testfile70.exec.bz2 \
+ testfile70.core.bz2 testfile70.exec.bz2 testfile71.bz2 \
run-dwfllines.sh run-dwfl-report-elf-align.sh \
testfile-dwfl-report-elf-align-shlib.so.bz2 \
testfilenolines.bz2 test-core-lib.so.bz2 test-core.core.bz2 \
diff --git a/tests/run-readelf-mixed-corenote.sh b/tests/run-readelf-mixed-corenote.sh
index 915bdebd..8823c3ed 100755
--- a/tests/run-readelf-mixed-corenote.sh
+++ b/tests/run-readelf-mixed-corenote.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2012 Red Hat, Inc.
+# Copyright (C) 2012, 2013 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -217,4 +217,61 @@ Note segment of 852 bytes at offset 0x94:
high_r15: 0x00000000
EOF
+# To reproduce this core dump, do this on x86_64 machine with Linux
+# 3.7 or later:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile71
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile71 <<\EOF
+
+Note segment of 1476 bytes at offset 0x430:
+ Owner Data size Type
+ CORE 336 PRSTATUS
+ info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+ sigpend: <>
+ sighold: <>
+ pid: 9664, ppid: 2868, pgrp: 9664, sid: 2868
+ utime: 0.000000, stime: 0.004000, cutime: 0.000000, cstime: 0.000000
+ orig_rax: -1, fpvalid: 0
+ r15: 0 r14: 0
+ r13: 140734971656848 r12: 4195328
+ rbp: 0x00007fff69fe39b0 rbx: 0
+ r11: 266286012928 r10: 140734971656256
+ r9: 0 r8: 266289790592
+ rax: 305419896 rcx: 4195584
+ rdx: 140734971656872 rsi: 140734971656856
+ rdi: 1 rip: 0x00000000004004f9
+ rflags: 0x0000000000010246 rsp: 0x00007fff69fe39b0
+ fs.base: 0x00007fa1c8933740 gs.base: 0x0000000000000000
+ cs: 0x0033 ss: 0x002b ds: 0x0000 es: 0x0000 fs: 0x0000 gs: 0x0000
+ CORE 136 PRPSINFO
+ state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000000200
+ uid: 1000, gid: 1000, pid: 9664, ppid: 2868, pgrp: 9664, sid: 2868
+ fname: a.out, psargs: ./a.out
+ CORE 128 SIGINFO
+ si_signo: 11, si_errno: 0, si_code: 1
+ fault address: 0x12345678
+ CORE 304 AUXV
+ SYSINFO_EHDR: 0x7fff69ffe000
+ HWCAP: 0xafebfbff <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss tm pbe>
+ PAGESZ: 4096
+ CLKTCK: 100
+ PHDR: 0x400040
+ PHENT: 56
+ PHNUM: 9
+ BASE: 0
+ FLAGS: 0
+ ENTRY: 0x400400
+ UID: 1000
+ EUID: 1000
+ GID: 1000
+ EGID: 1000
+ SECURE: 0
+ RANDOM: 0x7fff69fe3d19
+ EXECFN: 0x7fff69fe4ff0
+ PLATFORM: 0x7fff69fe3d29
+ NULL
+ CORE 469 FILE
+EOF
+
exit 0
diff --git a/tests/testfile71.bz2 b/tests/testfile71.bz2
new file mode 100644
index 00000000..ce5b08fe
--- /dev/null
+++ b/tests/testfile71.bz2
Binary files differ