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 : }
|