blob: 9d01219c7662e0ef4a61e07f284577eed5bc358d [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.
3 This file is part of Red Hat elfutils.
4
5 Red Hat elfutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by the
7 Free Software Foundation; version 2 of the License.
8
9 Red Hat elfutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Red Hat elfutils; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18 Red Hat elfutils is an included package of the Open Invention Network.
19 An included package of the Open Invention Network is a package for which
20 Open Invention Network licensees cross-license their patents. No patent
21 license is granted, either expressly or impliedly, by designation as an
22 included package. Should you wish to participate in the Open Invention
23 Network licensing program, please visit www.openinventionnetwork.com
24 <http://www.openinventionnetwork.com>. */
25
26#include <string.h>
27
28/* The including CPU_corenote.c file provides prstatus_regs and
29 defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
30
31 Here we describe the common layout used in <linux/elfcore.h>. */
32
33#define CHAR int8_t
34#define ALIGN_CHAR 1
35#define TYPE_CHAR ELF_T_BYTE
36#define SHORT uint16_t
37#define ALIGN_SHORT 2
38#define TYPE_SHORT ELF_T_HALF
39#define INT int32_t
40#define ALIGN_INT 4
41#define TYPE_INT ELF_T_SWORD
42
43#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
44
45struct EBLHOOK(siginfo)
46{
47 FIELD (INT, si_signo);
48 FIELD (INT, si_code);
49 FIELD (INT, si_errno);
50};
51
52struct EBLHOOK(timeval)
53{
54 FIELD (ULONG, tv_sec);
55 FIELD (ULONG, tv_usec);
56};
57
58/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
59 The 'T'|0x80 value for .format indicates this as a special kludge. */
60#if SUSECONDS_HALF
61# define TIMEVAL_FIELD(name) FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
62#else
63# define TIMEVAL_FIELD(name) FIELD (time, ULONG, name, 'T', .count = 2)
64#endif
65
66
67struct EBLHOOK(prstatus)
68{
69 struct EBLHOOK(siginfo) pr_info;
70 FIELD (SHORT, pr_cursig);
71 FIELD (ULONG, pr_sigpend);
72 FIELD (ULONG, pr_sighold);
73 FIELD (PID_T, pr_pid);
74 FIELD (PID_T, pr_ppid);
75 FIELD (PID_T, pr_pgrp);
76 FIELD (PID_T, pr_sid);
77 struct EBLHOOK(timeval) pr_utime;
78 struct EBLHOOK(timeval) pr_stime;
79 struct EBLHOOK(timeval) pr_cutime;
80 struct EBLHOOK(timeval) pr_cstime;
81 FIELD (ULONG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (ULONG)]);
82 FIELD (INT, pr_fpvalid);
83};
84
85#define FNAMESZ 16
86#define PRARGSZ 80
87
88struct EBLHOOK(prpsinfo)
89{
90 FIELD (CHAR, pr_state);
91 FIELD (CHAR, pr_sname);
92 FIELD (CHAR, pr_zomb);
93 FIELD (CHAR, pr_nice);
94 FIELD (ULONG, pr_flag);
95 FIELD (UID_T, pr_uid);
96 FIELD (GID_T, pr_gid);
97 FIELD (PID_T, pr_pid);
98 FIELD (PID_T, pr_ppid);
99 FIELD (PID_T, pr_pgrp);
100 FIELD (PID_T, pr_sid);
101 FIELD (CHAR, pr_fname[FNAMESZ]);
102 FIELD (CHAR, pr_psargs[PRARGSZ]);
103};
104
105#undef FIELD
106
107#define FIELD(igroup, itype, item, fmt, ...) \
108 { \
109 .name = #item, \
110 .group = #igroup, \
111 .offset = offsetof (struct EBLHOOK(prstatus), pr_##item), \
112 .type = TYPE_##itype, \
113 .format = fmt, \
114 __VA_ARGS__ \
115 }
116
117static const Ebl_Core_Item prstatus_items[] =
118 {
119 FIELD (signal, INT, info.si_signo, 'd'),
120 FIELD (signal, INT, info.si_code, 'd'),
121 FIELD (signal, INT, info.si_errno, 'd'),
122 FIELD (signal, SHORT, cursig, 'd'),
123 FIELD (signal, ULONG, sigpend, 'B'),
124 FIELD (signal, ULONG, sighold, 'B'),
125 FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
126 FIELD (identity, PID_T, ppid, 'd'),
127 FIELD (identity, PID_T, pgrp, 'd'),
128 FIELD (identity, PID_T, sid, 'd'),
129 TIMEVAL_FIELD (utime),
130 TIMEVAL_FIELD (stime),
131 TIMEVAL_FIELD (cutime),
132 TIMEVAL_FIELD (cstime),
133#ifdef PRSTATUS_REGSET_ITEMS
134 PRSTATUS_REGSET_ITEMS,
135#endif
136 FIELD (register, INT, fpvalid, 'd'),
137 };
138
139#undef FIELD
140
141#define FIELD(igroup, itype, item, fmt, ...) \
142 { \
143 .name = #item, \
144 .group = #igroup, \
145 .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item), \
146 .type = TYPE_##itype, \
147 .format = fmt, \
148 __VA_ARGS__ \
149 }
150
151static const Ebl_Core_Item prpsinfo_items[] =
152 {
153 FIELD (state, CHAR, state, 'd'),
154 FIELD (state, CHAR, sname, 'c'),
155 FIELD (state, CHAR, zomb, 'd'),
156 FIELD (state, CHAR, nice, 'd'),
157 FIELD (state, ULONG, flag, 'x'),
158 FIELD (identity, UID_T, uid, 'd'),
159 FIELD (identity, GID_T, gid, 'd'),
160 FIELD (identity, PID_T, pid, 'd'),
161 FIELD (identity, PID_T, ppid, 'd'),
162 FIELD (identity, PID_T, pgrp, 'd'),
163 FIELD (identity, PID_T, sid, 'd'),
164 FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
165 FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
166 };
167
168static const Ebl_Core_Item vmcoreinfo_items[] =
169 {
170 {
171 .type = ELF_T_BYTE, .format = '\n'
172 }
173 };
174
175#undef FIELD
176
177int
178EBLHOOK(core_note) (nhdr, name, regs_offset, nregloc, reglocs, nitems, items)
179 const GElf_Nhdr *nhdr;
180 const char *name;
181 GElf_Word *regs_offset;
182 size_t *nregloc;
183 const Ebl_Register_Location **reglocs;
184 size_t *nitems;
185 const Ebl_Core_Item **items;
186{
187 switch (nhdr->n_namesz)
188 {
189 case sizeof "CORE" - 1: /* Buggy old Linux kernels. */
190 if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
191 break;
192 return 0;
193
194 case sizeof "CORE":
195 if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
196 break;
197 /* Buggy old Linux kernels didn't terminate "LINUX".
198 Fall through. */
199
200 case sizeof "LINUX":
201 if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
202 break;
203 return 0;
204
205 case sizeof "VMCOREINFO":
206 if (nhdr->n_type != 0
207 || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
208 return 0;
209 *regs_offset = 0;
210 *nregloc = 0;
211 *nitems = 1;
212 *items = vmcoreinfo_items;
213 return 1;
214
215 default:
216 return 0;
217 }
218
219 switch (nhdr->n_type)
220 {
221 case NT_PRSTATUS:
222 if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
223 return 0;
224 *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
225 *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
226 *reglocs = prstatus_regs;
227 *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
228 *items = prstatus_items;
229 return 1;
230
231 case NT_PRPSINFO:
232 if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
233 return 0;
234 *regs_offset = 0;
235 *nregloc = 0;
236 *reglocs = NULL;
237 *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
238 *items = prpsinfo_items;
239 return 1;
240
241#define EXTRA_REGSET(type, size, table) \
242 case type: \
243 if (nhdr->n_descsz != size) \
244 return 0; \
245 *regs_offset = 0; \
246 *nregloc = sizeof table / sizeof table[0]; \
247 *reglocs = table; \
248 *nitems = 0; \
249 *items = NULL; \
250 return 1;
251
252#ifdef FPREGSET_SIZE
253 EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
254#endif
255
256#ifdef EXTRA_NOTES
257 EXTRA_NOTES
258#endif
259 }
260
261 return 0;
262}