• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EBLHOOK(siginfo)67 struct EBLHOOK(siginfo)
68 {
69   FIELD (INT, si_signo);
70   FIELD (INT, si_code);
71   FIELD (INT, si_errno);
72 };
73 
EBLHOOK(timeval)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 
EBLHOOK(prstatus)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 
EBLHOOK(prpsinfo)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
EBLHOOK(core_note)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 {
218   switch (nhdr->n_namesz)
219     {
220     case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
221       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
222 	break;
223       return 0;
224 
225     case sizeof "CORE":
226       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
227 	break;
228       /* Buggy old Linux kernels didn't terminate "LINUX".  */
229       FALLTHROUGH;
230 
231     case sizeof "LINUX":
232       if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
233 	break;
234       return 0;
235 
236     case sizeof "VMCOREINFO":
237       if (nhdr->n_type != 0
238 	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
239 	return 0;
240       *regs_offset = 0;
241       *nregloc = 0;
242       *nitems = 1;
243       *items = vmcoreinfo_items;
244       return 1;
245 
246     default:
247       return 0;
248     }
249 
250   switch (nhdr->n_type)
251     {
252     case NT_PRSTATUS:
253       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
254 	return 0;
255       *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
256       *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
257       *reglocs = prstatus_regs;
258       *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
259       *items = prstatus_items;
260       return 1;
261 
262     case NT_PRPSINFO:
263       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
264 	return 0;
265       *regs_offset = 0;
266       *nregloc = 0;
267       *reglocs = NULL;
268       *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
269       *items = prpsinfo_items;
270       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     EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
307 #endif
308 
309 #ifdef EXTRA_NOTES
310     EXTRA_NOTES
311 #endif
312     }
313 
314   return 0;
315 }
316