Coverage Report

Created: 2025-07-11 06:46

/src/elfutils/backends/linux-core-note.c
Line
Count
Source (jump to first uncovered line)
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
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
0
{
218
0
  switch (nhdr->n_namesz)
219
0
    {
220
0
    case sizeof "CORE" - 1: /* Buggy old Linux kernels.  */
221
0
      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
222
0
  break;
223
0
      return 0;
224
225
0
    case sizeof "CORE":
226
0
      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
227
0
  break;
228
      /* Buggy old Linux kernels didn't terminate "LINUX".  */
229
0
      FALLTHROUGH;
230
231
0
    case sizeof "LINUX":
232
0
      if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
233
0
  break;
234
0
      return 0;
235
236
0
    case sizeof "VMCOREINFO":
237
0
      if (nhdr->n_type != 0
238
0
    || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
239
0
  return 0;
240
0
      *regs_offset = 0;
241
0
      *nregloc = 0;
242
0
      *reglocs = NULL;
243
0
      *nitems = 1;
244
0
      *items = vmcoreinfo_items;
245
0
      return 1;
246
247
0
    default:
248
0
      return 0;
249
0
    }
250
251
0
  switch (nhdr->n_type)
252
0
    {
253
0
    case NT_PRSTATUS:
254
0
      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
255
0
  return 0;
256
0
      *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
257
0
      *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
258
0
      *reglocs = prstatus_regs;
259
0
      *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
260
0
      *items = prstatus_items;
261
0
      return 1;
262
263
0
    case NT_PRPSINFO:
264
0
      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
265
0
  return 0;
266
0
      *regs_offset = 0;
267
0
      *nregloc = 0;
268
0
      *reglocs = NULL;
269
0
      *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
270
0
      *items = prpsinfo_items;
271
0
      return 1;
272
273
0
#define EXTRA_REGSET(type, size, table)               \
274
0
    case type:                      \
275
0
      if (nhdr->n_descsz != size)               \
276
0
  return 0;                   \
277
0
      *regs_offset = 0;                   \
278
0
      *nregloc = sizeof table / sizeof table[0];            \
279
0
      *reglocs = table;                   \
280
0
      *nitems = 0;                    \
281
0
      *items = NULL;                    \
282
0
      return 1;
283
284
0
#define EXTRA_REGSET_ITEMS(type, size, table, extra_items)          \
285
0
    case type:                      \
286
0
      if (nhdr->n_descsz != size)               \
287
0
  return 0;                   \
288
0
      *regs_offset = 0;                   \
289
0
      *nregloc = sizeof table / sizeof table[0];            \
290
0
      *reglocs = table;                   \
291
0
      *nitems = sizeof extra_items / sizeof extra_items[0];         \
292
0
      *items = extra_items;                 \
293
0
      return 1;
294
295
0
#define EXTRA_ITEMS(type, size, extra_items)              \
296
0
    case type:                      \
297
0
      if (nhdr->n_descsz != size)               \
298
0
  return 0;                   \
299
0
      *regs_offset = 0;                   \
300
0
      *nregloc = 0;                   \
301
0
      *reglocs = NULL;                    \
302
0
      *nitems = sizeof extra_items / sizeof extra_items[0];         \
303
0
      *items = extra_items;                 \
304
0
      return 1;
305
306
#ifdef FPREGSET_SIZE
307
0
    EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
308
0
#endif
309
310
#ifdef EXTRA_NOTES
311
0
    EXTRA_NOTES
312
#endif
313
0
    }
314
315
0
  return 0;
316
0
}
Unexecuted instantiation: i386_core_note
Unexecuted instantiation: sh_core_note
Unexecuted instantiation: x86_64_core_note
Unexecuted instantiation: x32_core_note
Unexecuted instantiation: alpha_core_note
Unexecuted instantiation: arm_core_note
Unexecuted instantiation: aarch64_core_note
Unexecuted instantiation: sparc_core_note
Unexecuted instantiation: sparc64_core_note
Unexecuted instantiation: ppc_core_note
Unexecuted instantiation: ppc64_core_note
Unexecuted instantiation: s390_core_note
Unexecuted instantiation: s390x_core_note
Unexecuted instantiation: m68k_core_note
Unexecuted instantiation: riscv_core_note
Unexecuted instantiation: riscv64_core_note
Unexecuted instantiation: csky_core_note
Unexecuted instantiation: loongarch_core_note
Unexecuted instantiation: mips_core_note