LCOV - code coverage report
Current view: top level - backends - linux-core-note.c (source / functions) Hit Total Coverage
Test: elfutils-0.189 Lines: 34 36 94.4 %
Date: 2023-05-09 12:09:07 Functions: 12 18 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 22 39 56.4 %

           Branch data     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                 :        327 : 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   [ -  +  +  +  :        327 :   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                 :        276 :     case sizeof "CORE":
     226         [ +  - ]:        276 :       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
     227                 :            :         break;
     228                 :            :       /* Buggy old Linux kernels didn't terminate "LINUX".  */
     229                 :         50 :       FALLTHROUGH;
     230                 :            : 
     231                 :            :     case sizeof "LINUX":
     232         [ +  - ]:         50 :       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 :       *reglocs = NULL;
     243                 :          1 :       *nitems = 1;
     244                 :          1 :       *items = vmcoreinfo_items;
     245                 :          1 :       return 1;
     246                 :            : 
     247                 :            :     default:
     248                 :            :       return 0;
     249                 :            :     }
     250                 :            : 
     251   [ +  +  +  +  :        326 :   switch (nhdr->n_type)
             +  +  +  + ]
     252                 :            :     {
     253                 :        117 :     case NT_PRSTATUS:
     254         [ +  - ]:        117 :       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
     255                 :            :         return 0;
     256                 :        117 :       *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
     257                 :        117 :       *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
     258                 :        117 :       *reglocs = prstatus_regs;
     259                 :        117 :       *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
     260                 :        117 :       *items = prstatus_items;
     261                 :        117 :       return 1;
     262                 :            : 
     263                 :         67 :     case NT_PRPSINFO:
     264         [ +  - ]:         67 :       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
     265                 :            :         return 0;
     266                 :         67 :       *regs_offset = 0;
     267                 :         67 :       *nregloc = 0;
     268                 :         67 :       *reglocs = NULL;
     269                 :         67 :       *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
     270                 :         67 :       *items = prpsinfo_items;
     271                 :         67 :       return 1;
     272                 :            : 
     273                 :            : #define EXTRA_REGSET(type, size, table)                                       \
     274                 :            :     case type:                                                                \
     275                 :            :       if (nhdr->n_descsz != size)                                          \
     276                 :            :         return 0;                                                             \
     277                 :            :       *regs_offset = 0;                                                       \
     278                 :            :       *nregloc = sizeof table / sizeof table[0];                              \
     279                 :            :       *reglocs = table;                                                       \
     280                 :            :       *nitems = 0;                                                            \
     281                 :            :       *items = NULL;                                                          \
     282                 :            :       return 1;
     283                 :            : 
     284                 :            : #define EXTRA_REGSET_ITEMS(type, size, table, extra_items)                    \
     285                 :            :     case type:                                                                \
     286                 :            :       if (nhdr->n_descsz != size)                                          \
     287                 :            :         return 0;                                                             \
     288                 :            :       *regs_offset = 0;                                                       \
     289                 :            :       *nregloc = sizeof table / sizeof table[0];                              \
     290                 :            :       *reglocs = table;                                                       \
     291                 :            :       *nitems = sizeof extra_items / sizeof extra_items[0];                   \
     292                 :            :       *items = extra_items;                                                   \
     293                 :            :       return 1;
     294                 :            : 
     295                 :            : #define EXTRA_ITEMS(type, size, extra_items)                                  \
     296                 :            :     case type:                                                                \
     297                 :            :       if (nhdr->n_descsz != size)                                          \
     298                 :            :         return 0;                                                             \
     299                 :            :       *regs_offset = 0;                                                       \
     300                 :            :       *nregloc = 0;                                                           \
     301                 :            :       *reglocs = NULL;                                                        \
     302                 :            :       *nitems = sizeof extra_items / sizeof extra_items[0];                   \
     303                 :            :       *items = extra_items;                                                   \
     304                 :            :       return 1;
     305                 :            : 
     306                 :            : #ifdef FPREGSET_SIZE
     307         [ +  - ]:         17 :     EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
     308                 :            : #endif
     309                 :            : 
     310                 :            : #ifdef EXTRA_NOTES
     311   [ +  -  +  -  :         50 :     EXTRA_NOTES
          +  -  +  -  -  
                      - ]
     312                 :            : #endif
     313                 :            :     }
     314                 :            : 
     315                 :            :   return 0;
     316                 :            : }

Generated by: LCOV version 1.14