blob: e3c0109822f75e48946f52d3be1a0c3585c0660b [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Common core note type descriptions for Linux.
2 Copyright (C) 2007-2010 Red Hat, Inc.
Elliott Hughes03333822015-02-18 22:19:45 -08003 This file is part of elfutils.
Ben Cheng25b3c042013-11-20 14:45:36 -08004
Elliott Hughes03333822015-02-18 22:19:45 -08005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ben Cheng25b3c042013-11-20 14:45:36 -08007
Elliott Hughes03333822015-02-18 22:19:45 -08008 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
Ben Cheng25b3c042013-11-20 14:45:36 -080021 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
Elliott Hughes03333822015-02-18 22:19:45 -080025 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
Ben Cheng25b3c042013-11-20 14:45:36 -080028
29#include <string.h>
30
31/* The including CPU_corenote.c file provides prstatus_regs and
32 defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
33
34 Here we describe the common layout used in <linux/elfcore.h>. */
35
36#define CHAR int8_t
37#define ALIGN_CHAR 1
38#define TYPE_CHAR ELF_T_BYTE
39#define SHORT uint16_t
40#define ALIGN_SHORT 2
41#define TYPE_SHORT ELF_T_HALF
42#define INT int32_t
43#define ALIGN_INT 4
44#define TYPE_INT ELF_T_SWORD
Elliott Hughes03333822015-02-18 22:19:45 -080045#ifndef ALIGN_PR_REG
46# define ALIGN_PR_REG ALIGN_ULONG
47#endif
Ben Cheng25b3c042013-11-20 14:45:36 -080048
49#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
50
51struct EBLHOOK(siginfo)
52{
53 FIELD (INT, si_signo);
54 FIELD (INT, si_code);
55 FIELD (INT, si_errno);
56};
57
58struct EBLHOOK(timeval)
59{
60 FIELD (ULONG, tv_sec);
61 FIELD (ULONG, tv_usec);
62};
63
64/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
65 The 'T'|0x80 value for .format indicates this as a special kludge. */
66#if SUSECONDS_HALF
67# define TIMEVAL_FIELD(name) FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
68#else
69# define TIMEVAL_FIELD(name) FIELD (time, ULONG, name, 'T', .count = 2)
70#endif
71
72
73struct EBLHOOK(prstatus)
74{
75 struct EBLHOOK(siginfo) pr_info;
76 FIELD (SHORT, pr_cursig);
77 FIELD (ULONG, pr_sigpend);
78 FIELD (ULONG, pr_sighold);
79 FIELD (PID_T, pr_pid);
80 FIELD (PID_T, pr_ppid);
81 FIELD (PID_T, pr_pgrp);
82 FIELD (PID_T, pr_sid);
83 struct EBLHOOK(timeval) pr_utime;
84 struct EBLHOOK(timeval) pr_stime;
85 struct EBLHOOK(timeval) pr_cutime;
86 struct EBLHOOK(timeval) pr_cstime;
Elliott Hughes03333822015-02-18 22:19:45 -080087 struct
88 {
89 FIELD (ULONG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (ULONG)]);
90 }
91#ifdef ALIGN_PR_REG
92 __attribute__ ((aligned (ALIGN_PR_REG)))
93#endif
94 ;
Ben Cheng25b3c042013-11-20 14:45:36 -080095 FIELD (INT, pr_fpvalid);
96};
97
98#define FNAMESZ 16
99#define PRARGSZ 80
100
101struct EBLHOOK(prpsinfo)
102{
103 FIELD (CHAR, pr_state);
104 FIELD (CHAR, pr_sname);
105 FIELD (CHAR, pr_zomb);
106 FIELD (CHAR, pr_nice);
107 FIELD (ULONG, pr_flag);
108 FIELD (UID_T, pr_uid);
109 FIELD (GID_T, pr_gid);
110 FIELD (PID_T, pr_pid);
111 FIELD (PID_T, pr_ppid);
112 FIELD (PID_T, pr_pgrp);
113 FIELD (PID_T, pr_sid);
114 FIELD (CHAR, pr_fname[FNAMESZ]);
115 FIELD (CHAR, pr_psargs[PRARGSZ]);
116};
117
118#undef FIELD
119
120#define FIELD(igroup, itype, item, fmt, ...) \
121 { \
122 .name = #item, \
123 .group = #igroup, \
124 .offset = offsetof (struct EBLHOOK(prstatus), pr_##item), \
125 .type = TYPE_##itype, \
126 .format = fmt, \
127 __VA_ARGS__ \
128 }
129
130static const Ebl_Core_Item prstatus_items[] =
131 {
132 FIELD (signal, INT, info.si_signo, 'd'),
133 FIELD (signal, INT, info.si_code, 'd'),
134 FIELD (signal, INT, info.si_errno, 'd'),
135 FIELD (signal, SHORT, cursig, 'd'),
Elliott Hughes03333822015-02-18 22:19:45 -0800136
137 /* Use different group name for a newline delimiter. */
138 FIELD (signal2, ULONG, sigpend, 'B'),
139 FIELD (signal3, ULONG, sighold, 'B'),
Ben Cheng25b3c042013-11-20 14:45:36 -0800140 FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
141 FIELD (identity, PID_T, ppid, 'd'),
142 FIELD (identity, PID_T, pgrp, 'd'),
143 FIELD (identity, PID_T, sid, 'd'),
144 TIMEVAL_FIELD (utime),
145 TIMEVAL_FIELD (stime),
146 TIMEVAL_FIELD (cutime),
147 TIMEVAL_FIELD (cstime),
148#ifdef PRSTATUS_REGSET_ITEMS
149 PRSTATUS_REGSET_ITEMS,
150#endif
151 FIELD (register, INT, fpvalid, 'd'),
152 };
153
154#undef FIELD
155
156#define FIELD(igroup, itype, item, fmt, ...) \
157 { \
158 .name = #item, \
159 .group = #igroup, \
160 .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item), \
161 .type = TYPE_##itype, \
162 .format = fmt, \
163 __VA_ARGS__ \
164 }
165
166static const Ebl_Core_Item prpsinfo_items[] =
167 {
168 FIELD (state, CHAR, state, 'd'),
169 FIELD (state, CHAR, sname, 'c'),
170 FIELD (state, CHAR, zomb, 'd'),
171 FIELD (state, CHAR, nice, 'd'),
172 FIELD (state, ULONG, flag, 'x'),
173 FIELD (identity, UID_T, uid, 'd'),
174 FIELD (identity, GID_T, gid, 'd'),
175 FIELD (identity, PID_T, pid, 'd'),
176 FIELD (identity, PID_T, ppid, 'd'),
177 FIELD (identity, PID_T, pgrp, 'd'),
178 FIELD (identity, PID_T, sid, 'd'),
179 FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
180 FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
181 };
182
183static const Ebl_Core_Item vmcoreinfo_items[] =
184 {
185 {
186 .type = ELF_T_BYTE, .format = '\n'
187 }
188 };
189
190#undef FIELD
191
192int
193EBLHOOK(core_note) (nhdr, name, regs_offset, nregloc, reglocs, nitems, items)
194 const GElf_Nhdr *nhdr;
195 const char *name;
196 GElf_Word *regs_offset;
197 size_t *nregloc;
198 const Ebl_Register_Location **reglocs;
199 size_t *nitems;
200 const Ebl_Core_Item **items;
201{
202 switch (nhdr->n_namesz)
203 {
204 case sizeof "CORE" - 1: /* Buggy old Linux kernels. */
205 if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
206 break;
207 return 0;
208
209 case sizeof "CORE":
210 if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
211 break;
212 /* Buggy old Linux kernels didn't terminate "LINUX".
213 Fall through. */
214
215 case sizeof "LINUX":
216 if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
217 break;
218 return 0;
219
220 case sizeof "VMCOREINFO":
221 if (nhdr->n_type != 0
222 || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
223 return 0;
224 *regs_offset = 0;
225 *nregloc = 0;
226 *nitems = 1;
227 *items = vmcoreinfo_items;
228 return 1;
229
230 default:
231 return 0;
232 }
233
234 switch (nhdr->n_type)
235 {
236 case NT_PRSTATUS:
237 if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
238 return 0;
239 *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
240 *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
241 *reglocs = prstatus_regs;
242 *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
243 *items = prstatus_items;
244 return 1;
245
246 case NT_PRPSINFO:
247 if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
248 return 0;
249 *regs_offset = 0;
250 *nregloc = 0;
251 *reglocs = NULL;
252 *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
253 *items = prpsinfo_items;
254 return 1;
255
256#define EXTRA_REGSET(type, size, table) \
257 case type: \
258 if (nhdr->n_descsz != size) \
259 return 0; \
260 *regs_offset = 0; \
261 *nregloc = sizeof table / sizeof table[0]; \
262 *reglocs = table; \
263 *nitems = 0; \
264 *items = NULL; \
265 return 1;
266
Elliott Hughes03333822015-02-18 22:19:45 -0800267#define EXTRA_REGSET_ITEMS(type, size, table, extra_items) \
268 case type: \
269 if (nhdr->n_descsz != size) \
270 return 0; \
271 *regs_offset = 0; \
272 *nregloc = sizeof table / sizeof table[0]; \
273 *reglocs = table; \
274 *nitems = sizeof extra_items / sizeof extra_items[0]; \
275 *items = extra_items; \
276 return 1;
277
278#define EXTRA_ITEMS(type, size, extra_items) \
279 case type: \
280 if (nhdr->n_descsz != size) \
281 return 0; \
282 *regs_offset = 0; \
283 *nregloc = 0; \
284 *reglocs = NULL; \
285 *nitems = sizeof extra_items / sizeof extra_items[0]; \
286 *items = extra_items; \
287 return 1;
288
Ben Cheng25b3c042013-11-20 14:45:36 -0800289#ifdef FPREGSET_SIZE
290 EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
291#endif
292
293#ifdef EXTRA_NOTES
294 EXTRA_NOTES
295#endif
296 }
297
298 return 0;
299}