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