1/* Common core note type descriptions for Linux.
2   Copyright (C) 2007, 2008 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/* The including CPU_corenote.c file provides prstatus_regs and
27   defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
28
29   Here we describe the common layout used in <linux/elfcore.h>.  */
30
31#define	CHAR			int8_t
32#define	ALIGN_CHAR		1
33#define	TYPE_CHAR		ELF_T_BYTE
34#define	SHORT			uint16_t
35#define ALIGN_SHORT		2
36#define TYPE_SHORT		ELF_T_HALF
37#define	INT			int32_t
38#define ALIGN_INT		4
39#define TYPE_INT		ELF_T_SWORD
40
41#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
42
43struct EBLHOOK(siginfo)
44{
45  FIELD (INT, si_signo);
46  FIELD (INT, si_code);
47  FIELD (INT, si_errno);
48};
49
50struct EBLHOOK(timeval)
51{
52  FIELD (ULONG, tv_sec);
53  FIELD (ULONG, tv_usec);
54};
55
56/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
57   The 'T'|0x80 value for .format indicates this as a special kludge.  */
58#if SUSECONDS_HALF
59# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
60#else
61# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
62#endif
63
64
65struct EBLHOOK(prstatus)
66{
67  struct EBLHOOK(siginfo) pr_info;
68  FIELD (SHORT, pr_cursig);
69  FIELD (ULONG, pr_sigpend);
70  FIELD (ULONG, pr_sighold);
71  FIELD (PID_T, pr_pid);
72  FIELD (PID_T, pr_ppid);
73  FIELD (PID_T, pr_pgrp);
74  FIELD (PID_T, pr_sid);
75  struct EBLHOOK(timeval) pr_utime;
76  struct EBLHOOK(timeval) pr_stime;
77  struct EBLHOOK(timeval) pr_cutime;
78  struct EBLHOOK(timeval) pr_cstime;
79  FIELD (ULONG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (ULONG)]);
80  FIELD (INT, pr_fpvalid);
81};
82
83#define	FNAMESZ	16
84#define	PRARGSZ	80
85
86struct EBLHOOK(prpsinfo)
87{
88  FIELD (CHAR, pr_state);
89  FIELD (CHAR, pr_sname);
90  FIELD (CHAR, pr_zomb);
91  FIELD (CHAR, pr_nice);
92  FIELD (ULONG, pr_flag);
93  FIELD (UID_T, pr_uid);
94  FIELD (GID_T, pr_gid);
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  FIELD (CHAR, pr_fname[FNAMESZ]);
100  FIELD (CHAR, pr_psargs[PRARGSZ]);
101};
102
103#undef	FIELD
104
105#define FIELD(igroup, itype, item, fmt, ...)			\
106    {								\
107      .name = #item,						\
108      .group = #igroup,					\
109      .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
110      .type = TYPE_##itype,					\
111      .format = fmt,						\
112      __VA_ARGS__						\
113    }
114
115static const Ebl_Core_Item prstatus_items[] =
116  {
117    FIELD (signal, INT, info.si_signo, 'd'),
118    FIELD (signal, INT, info.si_code, 'd'),
119    FIELD (signal, INT, info.si_errno, 'd'),
120    FIELD (signal, SHORT, cursig, 'd'),
121    FIELD (signal, ULONG, sigpend, 'B'),
122    FIELD (signal, ULONG, sighold, 'B'),
123    FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
124    FIELD (identity, PID_T, ppid, 'd'),
125    FIELD (identity, PID_T, pgrp, 'd'),
126    FIELD (identity, PID_T, sid, 'd'),
127    TIMEVAL_FIELD (utime),
128    TIMEVAL_FIELD (stime),
129    TIMEVAL_FIELD (cutime),
130    TIMEVAL_FIELD (cstime),
131#ifdef PRSTATUS_REGSET_ITEMS
132    PRSTATUS_REGSET_ITEMS,
133#endif
134    FIELD (register, INT, fpvalid, 'd'),
135  };
136
137#undef	FIELD
138
139#define FIELD(igroup, itype, item, fmt, ...)			\
140    {								\
141      .name = #item,						\
142      .group = #igroup,					\
143      .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
144      .type = TYPE_##itype,					\
145      .format = fmt,						\
146      __VA_ARGS__						\
147    }
148
149static const Ebl_Core_Item prpsinfo_items[] =
150  {
151    FIELD (state, CHAR, state, 'd'),
152    FIELD (state, CHAR, sname, 'c'),
153    FIELD (state, CHAR, zomb, 'd'),
154    FIELD (state, CHAR, nice, 'd'),
155    FIELD (state, ULONG, flag, 'x'),
156    FIELD (identity, UID_T, uid, 'd'),
157    FIELD (identity, GID_T, gid, 'd'),
158    FIELD (identity, PID_T, pid, 'd'),
159    FIELD (identity, PID_T, ppid, 'd'),
160    FIELD (identity, PID_T, pgrp, 'd'),
161    FIELD (identity, PID_T, sid, 'd'),
162    FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
163    FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
164  };
165
166#undef	FIELD
167
168int
169EBLHOOK(core_note) (n_type, descsz,
170		    regs_offset, nregloc, reglocs, nitems, items)
171     GElf_Word n_type;
172     GElf_Word descsz;
173     GElf_Word *regs_offset;
174     size_t *nregloc;
175     const Ebl_Register_Location **reglocs;
176     size_t *nitems;
177     const Ebl_Core_Item **items;
178{
179  switch (n_type)
180    {
181    case NT_PRSTATUS:
182      if (descsz != sizeof (struct EBLHOOK(prstatus)))
183	return 0;
184      *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
185      *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
186      *reglocs = prstatus_regs;
187      *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
188      *items = prstatus_items;
189      return 1;
190
191    case NT_PRPSINFO:
192      if (descsz != sizeof (struct EBLHOOK(prpsinfo)))
193	return 0;
194      *regs_offset = 0;
195      *nregloc = 0;
196      *reglocs = NULL;
197      *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
198      *items = prpsinfo_items;
199      return 1;
200
201#define EXTRA_REGSET(type, size, table)					      \
202    case type:								      \
203      if (descsz != size)						      \
204	return 0;							      \
205      *regs_offset = 0;							      \
206      *nregloc = sizeof table / sizeof table[0];			      \
207      *reglocs = table;							      \
208      *nitems = 0;							      \
209      *items = NULL;							      \
210      return 1;
211
212#ifdef FPREGSET_SIZE
213    EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
214#endif
215
216#ifdef EXTRA_NOTES
217    EXTRA_NOTES
218#endif
219    }
220
221  return 0;
222}
223