From ab22410aed2732016c598c47102d47df659ede0c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 26 Sep 2013 00:39:34 +0200 Subject: [PATCH] Show contents NT_SIGINFO core note in readelf Signed-off-by: Petr Machata --- src/ChangeLog | 6 ++ src/readelf.c | 103 ++++++++++++++++++++++++++++ tests/ChangeLog | 6 ++ tests/Makefile.am | 2 +- tests/run-readelf-mixed-corenote.sh | 59 +++++++++++++++- tests/testfile71.bz2 | Bin 0 -> 18164 bytes 6 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 tests/testfile71.bz2 diff --git a/src/ChangeLog b/src/ChangeLog index 6788087d0..9d4c2e2ca 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-09-26 Petr Machata + + * 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 * addr2line.c (options): Add "inlines", 'i'. diff --git a/src/readelf.c b/src/readelf.c index 119c10003..da3661c0d 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #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 34cffd42e..7e7166167 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2013-09-26 Petr Machata + + * 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 * allfcts.c (cb): Return DWARF_CB_ABORT. diff --git a/tests/Makefile.am b/tests/Makefile.am index 58db6c361..0024395df 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 915bdebdb..8823c3edf 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 + 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 0000000000000000000000000000000000000000..ce5b08fea4cad214c72e1d7773cfc34357957a1f GIT binary patch literal 18164 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