1 /* Common core note type descriptions for Linux. 2 Copyright (C) 2007-2010 Red Hat, Inc. 3 Copyright (C) H.J. Lu <hjl.tools (at) 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 67 struct EBLHOOK(siginfo) 68 { 69 FIELD (INT, si_signo); 70 FIELD (INT, si_code); 71 FIELD (INT, si_errno); 72 }; 73 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 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 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 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