• 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 #define ALIGN_INT		4
45 #define TYPE_INT		ELF_T_SWORD
46 #ifndef PR_REG
47 # define PR_REG			ULONG
48 #endif
49 #ifndef ALIGN_PR_REG
50 # define ALIGN_PR_REG		ALIGN_ULONG
51 #endif
52 #ifndef PRPSINFO_UID_T
53 # define PRPSINFO_UID_T		UID_T
54 # define ALIGN_PRPSINFO_UID_T	ALIGN_UID_T
55 # define TYPE_PRPSINFO_UID_T	TYPE_UID_T
56 #endif
57 #ifndef PRPSINFO_GID_T
58 # define PRPSINFO_GID_T		GID_T
59 # define ALIGN_PRPSINFO_GID_T	ALIGN_GID_T
60 # define TYPE_PRPSINFO_GID_T	TYPE_GID_T
61 #endif
62 
63 #define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
64 
EBLHOOK(siginfo)65 struct EBLHOOK(siginfo)
66 {
67   FIELD (INT, si_signo);
68   FIELD (INT, si_code);
69   FIELD (INT, si_errno);
70 };
71 
EBLHOOK(timeval)72 struct EBLHOOK(timeval)
73 {
74   FIELD (ULONG, tv_sec);
75   FIELD (ULONG, tv_usec);
76 };
77 
78 /* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
79    The 'T'|0x80 value for .format indicates this as a special kludge.  */
80 #if SUSECONDS_HALF
81 # define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
82 #else
83 # define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
84 #endif
85 
86 
EBLHOOK(prstatus)87 struct EBLHOOK(prstatus)
88 {
89   struct EBLHOOK(siginfo) pr_info;
90   FIELD (SHORT, pr_cursig);
91   FIELD (ULONG, pr_sigpend);
92   FIELD (ULONG, pr_sighold);
93   FIELD (PID_T, pr_pid);
94   FIELD (PID_T, pr_ppid);
95   FIELD (PID_T, pr_pgrp);
96   FIELD (PID_T, pr_sid);
97   struct EBLHOOK(timeval) pr_utime;
98   struct EBLHOOK(timeval) pr_stime;
99   struct EBLHOOK(timeval) pr_cutime;
100   struct EBLHOOK(timeval) pr_cstime;
101   struct
102   {
103     FIELD (PR_REG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (PR_REG)]);
104   }
105 #ifdef ALIGN_PR_REG
106     __attribute__ ((aligned (ALIGN_PR_REG)))
107 #endif
108     ;
109   FIELD (INT, pr_fpvalid);
110 };
111 
112 #define	FNAMESZ	16
113 #define	PRARGSZ	80
114 
EBLHOOK(prpsinfo)115 struct EBLHOOK(prpsinfo)
116 {
117   FIELD (CHAR, pr_state);
118   FIELD (CHAR, pr_sname);
119   FIELD (CHAR, pr_zomb);
120   FIELD (CHAR, pr_nice);
121   FIELD (ULONG, pr_flag);
122   FIELD (PRPSINFO_UID_T, pr_uid);
123   FIELD (PRPSINFO_GID_T, pr_gid);
124   FIELD (PID_T, pr_pid);
125   FIELD (PID_T, pr_ppid);
126   FIELD (PID_T, pr_pgrp);
127   FIELD (PID_T, pr_sid);
128   FIELD (CHAR, pr_fname[FNAMESZ]);
129   FIELD (CHAR, pr_psargs[PRARGSZ]);
130 };
131 
132 #undef	FIELD
133 
134 #define FIELD(igroup, itype, item, fmt, ...)			\
135     {								\
136       .name = #item,						\
137       .group = #igroup,					\
138       .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
139       .type = TYPE_##itype,					\
140       .format = fmt,						\
141       __VA_ARGS__						\
142     }
143 
144 static const Ebl_Core_Item prstatus_items[] =
145   {
146     FIELD (signal, INT, info.si_signo, 'd'),
147     FIELD (signal, INT, info.si_code, 'd'),
148     FIELD (signal, INT, info.si_errno, 'd'),
149     FIELD (signal, SHORT, cursig, 'd'),
150 
151     /* Use different group name for a newline delimiter.  */
152     FIELD (signal2, ULONG, sigpend, 'B'),
153     FIELD (signal3, ULONG, sighold, 'B'),
154     FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
155     FIELD (identity, PID_T, ppid, 'd'),
156     FIELD (identity, PID_T, pgrp, 'd'),
157     FIELD (identity, PID_T, sid, 'd'),
158     TIMEVAL_FIELD (utime),
159     TIMEVAL_FIELD (stime),
160     TIMEVAL_FIELD (cutime),
161     TIMEVAL_FIELD (cstime),
162 #ifdef PRSTATUS_REGSET_ITEMS
163     PRSTATUS_REGSET_ITEMS,
164 #endif
165     FIELD (register, INT, fpvalid, 'd'),
166   };
167 
168 #undef	FIELD
169 
170 #define FIELD(igroup, itype, item, fmt, ...)			\
171     {								\
172       .name = #item,						\
173       .group = #igroup,					\
174       .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
175       .type = TYPE_##itype,					\
176       .format = fmt,						\
177       __VA_ARGS__						\
178     }
179 
180 static const Ebl_Core_Item prpsinfo_items[] =
181   {
182     FIELD (state, CHAR, state, 'd'),
183     FIELD (state, CHAR, sname, 'c'),
184     FIELD (state, CHAR, zomb, 'd'),
185     FIELD (state, CHAR, nice, 'd'),
186     FIELD (state, ULONG, flag, 'x'),
187     FIELD (identity, PRPSINFO_UID_T, uid, 'd'),
188     FIELD (identity, PRPSINFO_GID_T, gid, 'd'),
189     FIELD (identity, PID_T, pid, 'd'),
190     FIELD (identity, PID_T, ppid, 'd'),
191     FIELD (identity, PID_T, pgrp, 'd'),
192     FIELD (identity, PID_T, sid, 'd'),
193     FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
194     FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
195   };
196 
197 static const Ebl_Core_Item vmcoreinfo_items[] =
198   {
199     {
200       .type = ELF_T_BYTE, .format = '\n'
201     }
202   };
203 
204 #undef	FIELD
205 
206 int
EBLHOOK(core_note)207 EBLHOOK(core_note) (const GElf_Nhdr *nhdr, const char *name,
208 		    GElf_Word *regs_offset, size_t *nregloc,
209 		    const Ebl_Register_Location **reglocs,
210 		    size_t *nitems, const Ebl_Core_Item **items)
211 {
212   switch (nhdr->n_namesz)
213     {
214     case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
215       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
216 	break;
217       return 0;
218 
219     case sizeof "CORE":
220       if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
221 	break;
222       /* Buggy old Linux kernels didn't terminate "LINUX".
223          Fall through.  */
224 
225     case sizeof "LINUX":
226       if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
227 	break;
228       return 0;
229 
230     case sizeof "VMCOREINFO":
231       if (nhdr->n_type != 0
232 	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
233 	return 0;
234       *regs_offset = 0;
235       *nregloc = 0;
236       *nitems = 1;
237       *items = vmcoreinfo_items;
238       return 1;
239 
240     default:
241       return 0;
242     }
243 
244   switch (nhdr->n_type)
245     {
246     case NT_PRSTATUS:
247       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
248 	return 0;
249       *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
250       *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
251       *reglocs = prstatus_regs;
252       *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
253       *items = prstatus_items;
254       return 1;
255 
256     case NT_PRPSINFO:
257       if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
258 	return 0;
259       *regs_offset = 0;
260       *nregloc = 0;
261       *reglocs = NULL;
262       *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
263       *items = prpsinfo_items;
264       return 1;
265 
266 #define EXTRA_REGSET(type, size, table)					      \
267     case type:								      \
268       if (nhdr->n_descsz != size)					      \
269 	return 0;							      \
270       *regs_offset = 0;							      \
271       *nregloc = sizeof table / sizeof table[0];			      \
272       *reglocs = table;							      \
273       *nitems = 0;							      \
274       *items = NULL;							      \
275       return 1;
276 
277 #define EXTRA_REGSET_ITEMS(type, size, table, extra_items)		      \
278     case type:								      \
279       if (nhdr->n_descsz != size)					      \
280 	return 0;							      \
281       *regs_offset = 0;							      \
282       *nregloc = sizeof table / sizeof table[0];			      \
283       *reglocs = table;							      \
284       *nitems = sizeof extra_items / sizeof extra_items[0];		      \
285       *items = extra_items;						      \
286       return 1;
287 
288 #define EXTRA_ITEMS(type, size, extra_items)				      \
289     case type:								      \
290       if (nhdr->n_descsz != size)					      \
291 	return 0;							      \
292       *regs_offset = 0;							      \
293       *nregloc = 0;							      \
294       *reglocs = NULL;							      \
295       *nitems = sizeof extra_items / sizeof extra_items[0];		      \
296       *items = extra_items;						      \
297       return 1;
298 
299 #ifdef FPREGSET_SIZE
300     EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
301 #endif
302 
303 #ifdef EXTRA_NOTES
304     EXTRA_NOTES
305 #endif
306     }
307 
308   return 0;
309 }
310