LCOV - code coverage report
Current view: top level - backends - linux-core-note.c (source / functions) Hit Total Coverage
Test: elfutils- Lines: 33 35 94.3 %
Date: 2020-06-11 18:20:19 Functions: 12 18 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Common core note type descriptions for Linux.
       2             :    Copyright (C) 2007-2010 Red Hat, Inc.
       3             :    Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
       4             :    This file is part of elfutils.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of either
       8             : 
       9             :      * the GNU Lesser General Public License as published by the Free
      10             :        Software Foundation; either version 3 of the License, or (at
      11             :        your option) any later version
      12             : 
      13             :    or
      14             : 
      15             :      * the GNU General Public License as published by the Free
      16             :        Software Foundation; either version 2 of the License, or (at
      17             :        your option) any later version
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    elfutils is distributed in the hope that it will be useful, but
      22             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    General Public License for more details.
      25             : 
      26             :    You should have received copies of the GNU General Public License and
      27             :    the GNU Lesser General Public License along with this program.  If
      28             :    not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : #include <string.h>
      31             : 
      32             : /* The including CPU_corenote.c file provides prstatus_regs and
      33             :    defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
      34             : 
      35             :    Here we describe the common layout used in <linux/elfcore.h>.  */
      36             : 
      37             : #define CHAR                    int8_t
      38             : #define ALIGN_CHAR              1
      39             : #define TYPE_CHAR               ELF_T_BYTE
      40             : #define SHORT                   uint16_t
      41             : #define ALIGN_SHORT             2
      42             : #define TYPE_SHORT              ELF_T_HALF
      43             : #define INT                     int32_t
      44             : #ifndef ALIGN_INT
      45             : # define ALIGN_INT              4
      46             : #endif
      47             : #define TYPE_INT                ELF_T_SWORD
      48             : #ifndef PR_REG
      49             : # define PR_REG                 ULONG
      50             : #endif
      51             : #ifndef ALIGN_PR_REG
      52             : # define ALIGN_PR_REG           ALIGN_ULONG
      53             : #endif
      54             : #ifndef PRPSINFO_UID_T
      55             : # define PRPSINFO_UID_T         UID_T
      56             : # define ALIGN_PRPSINFO_UID_T   ALIGN_UID_T
      57             : # define TYPE_PRPSINFO_UID_T    TYPE_UID_T
      58             : #endif
      59             : #ifndef PRPSINFO_GID_T
      60             : # define PRPSINFO_GID_T         GID_T
      61             : # define ALIGN_PRPSINFO_GID_T   ALIGN_GID_T
      62             : # define TYPE_PRPSINFO_GID_T    TYPE_GID_T
      63             : #endif
      64             : 
      65             : #define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
      66             : 
      67             : struct EBLHOOK(siginfo)
      68             : {
      69             :   FIELD (INT, si_signo);
      70             :   FIELD (INT, si_code);
      71             :   FIELD (INT, si_errno);
      72             : };
      73             : 
      74             : struct EBLHOOK(timeval)
      75             : {
      76             :   FIELD (ULONG, tv_sec);
      77             :   FIELD (ULONG, tv_usec);
      78             : };
      79             : 
      80             : /* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
      81             :    The 'T'|0x80 value for .format indicates this as a special kludge.  */
      82             : #if SUSECONDS_HALF
      83             : # define TIMEVAL_FIELD(name)    FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
      84             : #else
      85             : # define TIMEVAL_FIELD(name)    FIELD (time, ULONG, name, 'T', .count = 2)
      86             : #endif
      87             : 
      88             : 
      89             : struct EBLHOOK(prstatus)
      90             : {
      91             :   struct EBLHOOK(siginfo) pr_info;
      92             :   FIELD (SHORT, pr_cursig);
      93             :   FIELD (ULONG, pr_sigpend);
      94             :   FIELD (ULONG, pr_sighold);
      95             :   FIELD (PID_T, pr_pid);
      96             :   FIELD (PID_T, pr_ppid);
      97             :   FIELD (PID_T, pr_pgrp);
      98             :   FIELD (PID_T, pr_sid);
      99             :   struct EBLHOOK(timeval) pr_utime;
     100             :   struct EBLHOOK(timeval) pr_stime;
     101             :   struct EBLHOOK(timeval) pr_cutime;
     102             :   struct EBLHOOK(timeval) pr_cstime;
     103             :   struct
     104             :   {
     105             :     FIELD (PR_REG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (PR_REG)]);
     106             :   }
     107             : #ifdef ALIGN_PR_REG
     108             :     __attribute__ ((aligned (ALIGN_PR_REG)))
     109             : #endif
     110             :     ;
     111             :   FIELD (INT, pr_fpvalid);
     112             : }
     113             : #ifdef ALIGN_PRSTATUS
     114             :   attribute_packed __attribute__ ((aligned (ALIGN_PRSTATUS)))
     115             : #endif
     116             : ;
     117             : 
     118             : #define FNAMESZ 16
     119             : #define PRARGSZ 80
     120             : 
     121             : struct EBLHOOK(prpsinfo)
     122             : {
     123             :   FIELD (CHAR, pr_state);
     124             :   FIELD (CHAR, pr_sname);
     125             :   FIELD (CHAR, pr_zomb);
     126             :   FIELD (CHAR, pr_nice);
     127             :   FIELD (ULONG, pr_flag);
     128             :   FIELD (PRPSINFO_UID_T, pr_uid);
     129             :   FIELD (PRPSINFO_GID_T, pr_gid);
     130             :   FIELD (PID_T, pr_pid);
     131             :   FIELD (PID_T, pr_ppid);
     132             :   FIELD (PID_T, pr_pgrp);
     133             :   FIELD (PID_T, pr_sid);
     134             :   FIELD (CHAR, pr_fname[FNAMESZ]);
     135             :   FIELD (CHAR, pr_psargs[PRARGSZ]);
     136             : };
     137             : 
     138             : #undef  FIELD
     139             : 
     140             : #define FIELD(igroup, itype, item, fmt, ...)                    \
     141             :     {                                                           \
     142             :       .name = #item,                                            \
     143             :       .group = #igroup,                                 \
     144             :       .offset = offsetof (struct EBLHOOK(prstatus), pr_##item), \
     145             :       .type = TYPE_##itype,                                     \
     146             :       .format = fmt,                                            \
     147             :       __VA_ARGS__                                               \
     148             :     }
     149             : 
     150             : static const Ebl_Core_Item prstatus_items[] =
     151             :   {
     152             :     FIELD (signal, INT, info.si_signo, 'd'),
     153             :     FIELD (signal, INT, info.si_code, 'd'),
     154             :     FIELD (signal, INT, info.si_errno, 'd'),
     155             :     FIELD (signal, SHORT, cursig, 'd'),
     156             : 
     157             :     /* Use different group name for a newline delimiter.  */
     158             :     FIELD (signal2, ULONG, sigpend, 'B'),
     159             :     FIELD (signal3, ULONG, sighold, 'B'),
     160             :     FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
     161             :     FIELD (identity, PID_T, ppid, 'd'),
     162             :     FIELD (identity, PID_T, pgrp, 'd'),
     163             :     FIELD (identity, PID_T, sid, 'd'),
     164             :     TIMEVAL_FIELD (utime),
     165             :     TIMEVAL_FIELD (stime),
     166             :     TIMEVAL_FIELD (cutime),
     167             :     TIMEVAL_FIELD (cstime),
     168             : #ifdef PRSTATUS_REGSET_ITEMS
     169             :     PRSTATUS_REGSET_ITEMS,
     170             : #endif
     171             :     FIELD (register, INT, fpvalid, 'd'),
     172             :   };
     173             : 
     174             : #undef  FIELD
     175             : 
     176             : #define FIELD(igroup, itype, item, fmt, ...)                    \
     177             :     {                                                           \
     178             :       .name = #item,                                            \
     179             :       .group = #igroup,                                 \
     180             :       .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item), \
     181             :       .type = TYPE_##itype,                                     \
     182             :       .format = fmt,                                            \
     183             :       __VA_ARGS__                                               \
     184             :     }
     185             : 
     186             : static const Ebl_Core_Item prpsinfo_items[] =
     187             :   {
     188             :     FIELD (state, CHAR, state, 'd'),
     189             :     FIELD (state, CHAR, sname, 'c'),
     190             :     FIELD (state, CHAR, zomb, 'd'),
     191             :     FIELD (state, CHAR, nice, 'd'),
     192             :     FIELD (state, ULONG, flag, 'x'),
     193             :     FIELD (identity, PRPSINFO_UID_T, uid, 'd'),
     194             :     FIELD (identity, PRPSINFO_GID_T, gid, 'd'),
     195             :     FIELD (identity, PID_T, pid, 'd'),
     196             :     FIELD (identity, PID_T, ppid, 'd'),
     197             :     FIELD (identity, PID_T, pgrp, 'd'),
     198             :     FIELD (identity, PID_T, sid, 'd'),
     199             :     FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
     200             :     FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
     201             :   };
     202             : 
     203             : static const Ebl_Core_Item vmcoreinfo_items[] =
     204             :   {
     205             :     {
     206             :       .type = ELF_T_BYTE, .format = '\n'
     207             :     }
     208             :   };
     209             : 
     210             : #undef  FIELD
     211             : 
     212             : int
     213         359 : EBLHOOK(core_note) (const GElf_Nhdr *nhdr, const char *name,
     214             :                     GElf_Word *regs_offset, size_t *nregloc,
     215             :                     const Ebl_Register_Location **reglocs,
     216             :                     size_t *nitems, const Ebl_Core_Item **items)
     217             : {
     218         359 :   switch (nhdr->n_namesz)
     219             :     {
     220           0 :     case sizeof "CORE" - 1:   /* Buggy old Linux kernels.  */
     221           0 :       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
     222             :         break;
     223             :       return 0;
     224             : 
     225         300 :     case sizeof "CORE":
     226         300 :       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
     227             :         break;
     228             :       /* Buggy old Linux kernels didn't terminate "LINUX".  */
     229          58 :       FALLTHROUGH;
     230             : 
     231             :     case sizeof "LINUX":
     232          58 :       if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
     233             :         break;
     234             :       return 0;
     235             : 
     236           1 :     case sizeof "VMCOREINFO":
     237           1 :       if (nhdr->n_type != 0
     238           1 :           || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
     239             :         return 0;
     240           1 :       *regs_offset = 0;
     241           1 :       *nregloc = 0;
     242           1 :       *nitems = 1;
     243           1 :       *items = vmcoreinfo_items;
     244           1 :       return 1;
     245             : 
     246             :     default:
     247             :       return 0;
     248             :     }
     249             : 
     250         358 :   switch (nhdr->n_type)
     251             :     {
     252         127 :     case NT_PRSTATUS:
     253         127 :       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
     254             :         return 0;
     255         127 :       *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
     256         127 :       *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
     257         127 :       *reglocs = prstatus_regs;
     258         127 :       *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
     259         127 :       *items = prstatus_items;
     260         127 :       return 1;
     261             : 
     262          71 :     case NT_PRPSINFO:
     263          71 :       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
     264             :         return 0;
     265          71 :       *regs_offset = 0;
     266          71 :       *nregloc = 0;
     267          71 :       *reglocs = NULL;
     268          71 :       *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
     269          71 :       *items = prpsinfo_items;
     270          71 :       return 1;
     271             : 
     272             : #define EXTRA_REGSET(type, size, table)                                       \
     273             :     case type:                                                                \
     274             :       if (nhdr->n_descsz != size)                                          \
     275             :         return 0;                                                             \
     276             :       *regs_offset = 0;                                                       \
     277             :       *nregloc = sizeof table / sizeof table[0];                              \
     278             :       *reglocs = table;                                                       \
     279             :       *nitems = 0;                                                            \
     280             :       *items = NULL;                                                          \
     281             :       return 1;
     282             : 
     283             : #define EXTRA_REGSET_ITEMS(type, size, table, extra_items)                    \
     284             :     case type:                                                                \
     285             :       if (nhdr->n_descsz != size)                                          \
     286             :         return 0;                                                             \
     287             :       *regs_offset = 0;                                                       \
     288             :       *nregloc = sizeof table / sizeof table[0];                              \
     289             :       *reglocs = table;                                                       \
     290             :       *nitems = sizeof extra_items / sizeof extra_items[0];                   \
     291             :       *items = extra_items;                                                   \
     292             :       return 1;
     293             : 
     294             : #define EXTRA_ITEMS(type, size, extra_items)                                  \
     295             :     case type:                                                                \
     296             :       if (nhdr->n_descsz != size)                                          \
     297             :         return 0;                                                             \
     298             :       *regs_offset = 0;                                                       \
     299             :       *nregloc = 0;                                                           \
     300             :       *reglocs = NULL;                                                        \
     301             :       *nitems = sizeof extra_items / sizeof extra_items[0];                   \
     302             :       *items = extra_items;                                                   \
     303             :       return 1;
     304             : 
     305             : #ifdef FPREGSET_SIZE
     306          21 :     EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
     307             : #endif
     308             : 
     309             : #ifdef EXTRA_NOTES
     310          54 :     EXTRA_NOTES
     311             : #endif
     312             :     }
     313             : 
     314             :   return 0;
     315             : }

Generated by: LCOV version 1.13