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 : 329 : 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 [ - + + + : 329 : 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 : 278 : case sizeof "CORE":
226 [ - + ]: 278 : 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 [ + + + + : 328 : switch (nhdr->n_type)
+ + + + ]
252 : : {
253 : 118 : case NT_PRSTATUS:
254 [ + - ]: 118 : if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
255 : : return 0;
256 : 118 : *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
257 : 118 : *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
258 : 118 : *reglocs = prstatus_regs;
259 : 118 : *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
260 : 118 : *items = prstatus_items;
261 : 118 : return 1;
262 : :
263 : 68 : case NT_PRPSINFO:
264 [ + - ]: 68 : if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
265 : : return 0;
266 : 68 : *regs_offset = 0;
267 : 68 : *nregloc = 0;
268 : 68 : *reglocs = NULL;
269 : 68 : *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
270 : 68 : *items = prpsinfo_items;
271 : 68 : 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 : : }
|