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