Home | History | Annotate | Download | only in backends
      1 /* Common core note type descriptions for Linux.
      2    Copyright (C) 2007-2010 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat elfutils is distributed in the hope that it will be useful, but
     10    WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    Red Hat elfutils is an included package of the Open Invention Network.
     19    An included package of the Open Invention Network is a package for which
     20    Open Invention Network licensees cross-license their patents.  No patent
     21    license is granted, either expressly or impliedly, by designation as an
     22    included package.  Should you wish to participate in the Open Invention
     23    Network licensing program, please visit www.openinventionnetwork.com
     24    <http://www.openinventionnetwork.com>.  */
     25 
     26 #include <string.h>
     27 
     28 /* The including CPU_corenote.c file provides prstatus_regs and
     29    defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
     30 
     31    Here we describe the common layout used in <linux/elfcore.h>.  */
     32 
     33 #define	CHAR			int8_t
     34 #define	ALIGN_CHAR		1
     35 #define	TYPE_CHAR		ELF_T_BYTE
     36 #define	SHORT			uint16_t
     37 #define ALIGN_SHORT		2
     38 #define TYPE_SHORT		ELF_T_HALF
     39 #define	INT			int32_t
     40 #define ALIGN_INT		4
     41 #define TYPE_INT		ELF_T_SWORD
     42 
     43 #define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
     44 
     45 struct EBLHOOK(siginfo)
     46 {
     47   FIELD (INT, si_signo);
     48   FIELD (INT, si_code);
     49   FIELD (INT, si_errno);
     50 };
     51 
     52 struct EBLHOOK(timeval)
     53 {
     54   FIELD (ULONG, tv_sec);
     55   FIELD (ULONG, tv_usec);
     56 };
     57 
     58 /* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
     59    The 'T'|0x80 value for .format indicates this as a special kludge.  */
     60 #if SUSECONDS_HALF
     61 # define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
     62 #else
     63 # define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
     64 #endif
     65 
     66 
     67 struct EBLHOOK(prstatus)
     68 {
     69   struct EBLHOOK(siginfo) pr_info;
     70   FIELD (SHORT, pr_cursig);
     71   FIELD (ULONG, pr_sigpend);
     72   FIELD (ULONG, pr_sighold);
     73   FIELD (PID_T, pr_pid);
     74   FIELD (PID_T, pr_ppid);
     75   FIELD (PID_T, pr_pgrp);
     76   FIELD (PID_T, pr_sid);
     77   struct EBLHOOK(timeval) pr_utime;
     78   struct EBLHOOK(timeval) pr_stime;
     79   struct EBLHOOK(timeval) pr_cutime;
     80   struct EBLHOOK(timeval) pr_cstime;
     81   FIELD (ULONG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (ULONG)]);
     82   FIELD (INT, pr_fpvalid);
     83 };
     84 
     85 #define	FNAMESZ	16
     86 #define	PRARGSZ	80
     87 
     88 struct EBLHOOK(prpsinfo)
     89 {
     90   FIELD (CHAR, pr_state);
     91   FIELD (CHAR, pr_sname);
     92   FIELD (CHAR, pr_zomb);
     93   FIELD (CHAR, pr_nice);
     94   FIELD (ULONG, pr_flag);
     95   FIELD (UID_T, pr_uid);
     96   FIELD (GID_T, pr_gid);
     97   FIELD (PID_T, pr_pid);
     98   FIELD (PID_T, pr_ppid);
     99   FIELD (PID_T, pr_pgrp);
    100   FIELD (PID_T, pr_sid);
    101   FIELD (CHAR, pr_fname[FNAMESZ]);
    102   FIELD (CHAR, pr_psargs[PRARGSZ]);
    103 };
    104 
    105 #undef	FIELD
    106 
    107 #define FIELD(igroup, itype, item, fmt, ...)			\
    108     {								\
    109       .name = #item,						\
    110       .group = #igroup,					\
    111       .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
    112       .type = TYPE_##itype,					\
    113       .format = fmt,						\
    114       __VA_ARGS__						\
    115     }
    116 
    117 static const Ebl_Core_Item prstatus_items[] =
    118   {
    119     FIELD (signal, INT, info.si_signo, 'd'),
    120     FIELD (signal, INT, info.si_code, 'd'),
    121     FIELD (signal, INT, info.si_errno, 'd'),
    122     FIELD (signal, SHORT, cursig, 'd'),
    123     FIELD (signal, ULONG, sigpend, 'B'),
    124     FIELD (signal, ULONG, sighold, 'B'),
    125     FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
    126     FIELD (identity, PID_T, ppid, 'd'),
    127     FIELD (identity, PID_T, pgrp, 'd'),
    128     FIELD (identity, PID_T, sid, 'd'),
    129     TIMEVAL_FIELD (utime),
    130     TIMEVAL_FIELD (stime),
    131     TIMEVAL_FIELD (cutime),
    132     TIMEVAL_FIELD (cstime),
    133 #ifdef PRSTATUS_REGSET_ITEMS
    134     PRSTATUS_REGSET_ITEMS,
    135 #endif
    136     FIELD (register, INT, fpvalid, 'd'),
    137   };
    138 
    139 #undef	FIELD
    140 
    141 #define FIELD(igroup, itype, item, fmt, ...)			\
    142     {								\
    143       .name = #item,						\
    144       .group = #igroup,					\
    145       .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
    146       .type = TYPE_##itype,					\
    147       .format = fmt,						\
    148       __VA_ARGS__						\
    149     }
    150 
    151 static const Ebl_Core_Item prpsinfo_items[] =
    152   {
    153     FIELD (state, CHAR, state, 'd'),
    154     FIELD (state, CHAR, sname, 'c'),
    155     FIELD (state, CHAR, zomb, 'd'),
    156     FIELD (state, CHAR, nice, 'd'),
    157     FIELD (state, ULONG, flag, 'x'),
    158     FIELD (identity, UID_T, uid, 'd'),
    159     FIELD (identity, GID_T, gid, 'd'),
    160     FIELD (identity, PID_T, pid, 'd'),
    161     FIELD (identity, PID_T, ppid, 'd'),
    162     FIELD (identity, PID_T, pgrp, 'd'),
    163     FIELD (identity, PID_T, sid, 'd'),
    164     FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
    165     FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
    166   };
    167 
    168 static const Ebl_Core_Item vmcoreinfo_items[] =
    169   {
    170     {
    171       .type = ELF_T_BYTE, .format = '\n'
    172     }
    173   };
    174 
    175 #undef	FIELD
    176 
    177 int
    178 EBLHOOK(core_note) (nhdr, name, regs_offset, nregloc, reglocs, nitems, items)
    179      const GElf_Nhdr *nhdr;
    180      const char *name;
    181      GElf_Word *regs_offset;
    182      size_t *nregloc;
    183      const Ebl_Register_Location **reglocs;
    184      size_t *nitems;
    185      const Ebl_Core_Item **items;
    186 {
    187   switch (nhdr->n_namesz)
    188     {
    189     case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
    190       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
    191 	break;
    192       return 0;
    193 
    194     case sizeof "CORE":
    195       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
    196 	break;
    197       /* Buggy old Linux kernels didn't terminate "LINUX".
    198          Fall through.  */
    199 
    200     case sizeof "LINUX":
    201       if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
    202 	break;
    203       return 0;
    204 
    205     case sizeof "VMCOREINFO":
    206       if (nhdr->n_type != 0
    207 	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
    208 	return 0;
    209       *regs_offset = 0;
    210       *nregloc = 0;
    211       *nitems = 1;
    212       *items = vmcoreinfo_items;
    213       return 1;
    214 
    215     default:
    216       return 0;
    217     }
    218 
    219   switch (nhdr->n_type)
    220     {
    221     case NT_PRSTATUS:
    222       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
    223 	return 0;
    224       *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
    225       *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
    226       *reglocs = prstatus_regs;
    227       *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
    228       *items = prstatus_items;
    229       return 1;
    230 
    231     case NT_PRPSINFO:
    232       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
    233 	return 0;
    234       *regs_offset = 0;
    235       *nregloc = 0;
    236       *reglocs = NULL;
    237       *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
    238       *items = prpsinfo_items;
    239       return 1;
    240 
    241 #define EXTRA_REGSET(type, size, table)					      \
    242     case type:								      \
    243       if (nhdr->n_descsz != size)					      \
    244 	return 0;							      \
    245       *regs_offset = 0;							      \
    246       *nregloc = sizeof table / sizeof table[0];			      \
    247       *reglocs = table;							      \
    248       *nitems = 0;							      \
    249       *items = NULL;							      \
    250       return 1;
    251 
    252 #ifdef FPREGSET_SIZE
    253     EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
    254 #endif
    255 
    256 #ifdef EXTRA_NOTES
    257     EXTRA_NOTES
    258 #endif
    259     }
    260 
    261   return 0;
    262 }
    263