packaging: update homepage url
[platform/upstream/elfutils.git] / backends / linux-core-note.c
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
65 struct EBLHOOK(siginfo)
66 {
67   FIELD (INT, si_signo);
68   FIELD (INT, si_code);
69   FIELD (INT, si_errno);
70 };
71
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
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
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
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 }