/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 |