Show contents NT_SIGINFO core note in readelf
authorPetr Machata <pmachata@redhat.com>
Wed, 25 Sep 2013 22:39:34 +0000 (00:39 +0200)
committerPetr Machata <pmachata@redhat.com>
Mon, 30 Sep 2013 11:43:57 +0000 (13:43 +0200)
Signed-off-by: Petr Machata <pmachata@redhat.com>
src/ChangeLog
src/readelf.c
tests/ChangeLog
tests/Makefile.am
tests/run-readelf-mixed-corenote.sh
tests/testfile71.bz2 [new file with mode: 0644]

index 6788087..9d4c2e2 100644 (file)
@@ -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'.
index 119c100..da3661c 100644 (file)
@@ -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);
            }
index 34cffd4..7e71661 100644 (file)
@@ -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.
index 58db6c3..0024395 100644 (file)
@@ -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 \
index 915bdeb..8823c3e 100755 (executable)
@@ -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 (file)
index 0000000..ce5b08f
Binary files /dev/null and b/tests/testfile71.bz2 differ