1 /* $NetBSD: db_elf.c,v 1.29 2017/11/06 04:08:02 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center, and by Andrew Doran. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: db_elf.c,v 1.29 2017/11/06 04:08:02 christos Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/proc.h> 39 40 #include <machine/db_machdep.h> 41 #include <machine/pmap.h> 42 #include <machine/vmparam.h> 43 44 #ifdef DB_ELF_SYMBOLS 45 46 #include <ddb/ddb.h> 47 #include <sys/exec_elf.h> 48 49 static char *db_elf_find_strtab(db_symtab_t *); 50 51 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) 52 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) 53 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) 54 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) 55 56 static bool db_elf_sym_init(int, void *, void *, const char *); 57 static db_sym_t db_elf_lookup(db_symtab_t *, const char *); 58 static db_sym_t db_elf_search_symbol(db_symtab_t *, db_addr_t, db_strategy_t, 59 db_expr_t *); 60 static void db_elf_symbol_values(db_symtab_t *, db_sym_t, const char **, 61 db_expr_t *); 62 static bool db_elf_line_at_pc(db_symtab_t *, db_sym_t, char **, int *, 63 db_expr_t); 64 static bool db_elf_sym_numargs(db_symtab_t *, db_sym_t, int *, char **); 65 static void db_elf_forall(db_symtab_t *, db_forall_func_t db_forall_func, 66 void *); 67 68 const db_symformat_t db_symformat_elf = { 69 "ELF", 70 db_elf_sym_init, 71 db_elf_lookup, 72 db_elf_search_symbol, 73 db_elf_symbol_values, 74 db_elf_line_at_pc, 75 db_elf_sym_numargs, 76 db_elf_forall 77 }; 78 79 static db_symtab_t db_symtabs; 80 81 /* 82 * Add symbol table, with given name, to symbol tables. 83 */ 84 static int 85 db_add_symbol_table(char *start, char *end, const char *name, char *ref) 86 { 87 88 db_symtabs.start = start; 89 db_symtabs.end = end; 90 db_symtabs.name = name; 91 db_symtabs.private = ref; 92 93 return(0); 94 } 95 96 /* 97 * Find the symbol table and strings; tell ddb about them. 98 */ 99 static bool 100 db_elf_sym_init( 101 int symsize, /* size of symbol table */ 102 void *symtab, /* pointer to start of symbol table */ 103 void *esymtab, /* pointer to end of string table, 104 for checking - rounded up to integer 105 boundary */ 106 const char *name 107 ) 108 { 109 Elf_Ehdr *elf; 110 Elf_Shdr *shp; 111 Elf_Sym *symp, *symtab_start, *symtab_end; 112 char *strtab_start, *strtab_end; 113 int i, j; 114 115 if (ALIGNED_POINTER(symtab, long) == 0) { 116 printf("[ %s symbol table has bad start address %p ]\n", 117 name, symtab); 118 return (false); 119 } 120 121 symtab_start = symtab_end = NULL; 122 strtab_start = strtab_end = NULL; 123 124 /* 125 * The format of the symbols loaded by the boot program is: 126 * 127 * Elf exec header 128 * first section header 129 * . . . 130 * . . . 131 * last section header 132 * first symbol or string table section 133 * . . . 134 * . . . 135 * last symbol or string table section 136 */ 137 138 /* 139 * Validate the Elf header. 140 */ 141 elf = (Elf_Ehdr *)symtab; 142 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || 143 elf->e_ident[EI_CLASS] != ELFCLASS) 144 goto badheader; 145 146 switch (elf->e_machine) { 147 148 ELFDEFNNAME(MACHDEP_ID_CASES) 149 150 default: 151 goto badheader; 152 } 153 154 /* 155 * Find the first (and, we hope, only) SHT_SYMTAB section in 156 * the file, and the SHT_STRTAB section that goes with it. 157 */ 158 if (elf->e_shoff == 0) 159 goto badheader; 160 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); 161 for (i = 0; i < elf->e_shnum; i++) { 162 if (shp[i].sh_type == SHT_SYMTAB) { 163 if (shp[i].sh_offset == 0) 164 continue; 165 /* Got the symbol table. */ 166 symtab_start = (Elf_Sym *)((char *)symtab + 167 shp[i].sh_offset); 168 symtab_end = (Elf_Sym *)((char *)symtab + 169 shp[i].sh_offset + shp[i].sh_size); 170 /* Find the string table to go with it. */ 171 j = shp[i].sh_link; 172 if (shp[j].sh_offset == 0) 173 continue; 174 strtab_start = (char *)symtab + shp[j].sh_offset; 175 strtab_end = (char *)symtab + shp[j].sh_offset + 176 shp[j].sh_size; 177 /* There should only be one symbol table. */ 178 break; 179 } 180 } 181 182 /* 183 * Now, sanity check the symbols against the string table. 184 */ 185 if (symtab_start == NULL || strtab_start == NULL || 186 ALIGNED_POINTER(symtab_start, long) == 0 || 187 ALIGNED_POINTER(strtab_start, long) == 0) 188 goto badheader; 189 for (symp = symtab_start; symp < symtab_end; symp++) 190 if (symp->st_name + strtab_start > strtab_end) 191 goto badheader; 192 193 /* 194 * Link the symbol table into the debugger. 195 */ 196 if (db_add_symbol_table((char *)symtab_start, 197 (char *)symtab_end, name, (char *)symtab) != -1) { 198 return (true); 199 } 200 201 return (false); 202 203 badheader: 204 printf("[ %s ELF symbol table not valid ]\n", name); 205 return (false); 206 } 207 208 /* 209 * Internal helper function - return a pointer to the string table 210 * for the current symbol table. 211 */ 212 static char * 213 db_elf_find_strtab(db_symtab_t *stab) 214 { 215 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 216 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 217 int i; 218 219 stab = &db_symtabs; 220 221 /* 222 * We don't load ELF header for ELF modules. 223 * Find out if this is a loadable module. If so, 224 * string table comes right after symbol table. 225 */ 226 if ((Elf_Sym *)elf == STAB_TO_SYMSTART(stab)) { 227 return ((char *)STAB_TO_SYMEND(stab)); 228 } 229 for (i = 0; i < elf->e_shnum; i++) { 230 if (shp[i].sh_type == SHT_SYMTAB) 231 return ((char*)elf + shp[shp[i].sh_link].sh_offset); 232 } 233 234 return (NULL); 235 } 236 237 /* 238 * Lookup the symbol with the given name. 239 */ 240 static db_sym_t 241 db_elf_lookup(db_symtab_t *stab, const char *symstr) 242 { 243 Elf_Sym *symp, *symtab_start, *symtab_end; 244 char *strtab; 245 246 stab = &db_symtabs; 247 248 symtab_start = STAB_TO_SYMSTART(stab); 249 symtab_end = STAB_TO_SYMEND(stab); 250 251 strtab = db_elf_find_strtab(stab); 252 if (strtab == NULL) 253 return ((db_sym_t)0); 254 255 for (symp = symtab_start; symp < symtab_end; symp++) { 256 if (symp->st_name != 0 && 257 db_eqname(strtab + symp->st_name, symstr, 0)) 258 return ((db_sym_t)symp); 259 } 260 261 return ((db_sym_t)0); 262 } 263 264 /* 265 * Search for the symbol with the given address (matching within the 266 * provided threshold). 267 */ 268 static db_sym_t 269 db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy, 270 db_expr_t *diffp) 271 { 272 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 273 db_addr_t diff = *diffp; 274 275 symtab = &db_symtabs; 276 277 symtab_start = STAB_TO_SYMSTART(symtab); 278 symtab_end = STAB_TO_SYMEND(symtab); 279 280 rsymp = NULL; 281 282 for (symp = symtab_start; symp < symtab_end; symp++) { 283 if (symp->st_name == 0) 284 continue; 285 286 #if 0 287 /* This prevents me from seeing anythin in locore.s -- eeh */ 288 if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT && 289 ELF_ST_TYPE(symp->st_info) != STT_FUNC) 290 continue; 291 #endif 292 293 if (off >= symp->st_value) { 294 if (off - symp->st_value < diff) { 295 diff = off - symp->st_value; 296 rsymp = symp; 297 if (diff == 0) { 298 if (strategy == DB_STGY_PROC && 299 ELFDEFNNAME(ST_TYPE)(symp->st_info) 300 == STT_FUNC && 301 ELFDEFNNAME(ST_BIND)(symp->st_info) 302 != STB_LOCAL) 303 break; 304 if (strategy == DB_STGY_ANY && 305 ELFDEFNNAME(ST_BIND)(symp->st_info) 306 != STB_LOCAL) 307 break; 308 } 309 } else if (off - symp->st_value == diff) { 310 if (rsymp == NULL) 311 rsymp = symp; 312 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info) 313 == STB_LOCAL && 314 ELFDEFNNAME(ST_BIND)(symp->st_info) 315 != STB_LOCAL) { 316 /* pick the external symbol */ 317 rsymp = symp; 318 } 319 } 320 } 321 } 322 323 if (rsymp == NULL) 324 *diffp = off; 325 else 326 *diffp = diff; 327 328 return ((db_sym_t)rsymp); 329 } 330 331 /* 332 * Return the name and value for a symbol. 333 */ 334 static void 335 db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, const char **namep, 336 db_expr_t *valuep) 337 { 338 Elf_Sym *symp = (Elf_Sym *)sym; 339 char *strtab; 340 341 symtab = &db_symtabs; 342 343 if (namep) { 344 strtab = db_elf_find_strtab(symtab); 345 if (strtab == NULL) 346 *namep = NULL; 347 else 348 *namep = strtab + symp->st_name; 349 } 350 351 if (valuep) 352 *valuep = symp->st_value; 353 } 354 355 /* 356 * Return the file and line number of the current program counter 357 * if we can find the appropriate debugging symbol. 358 */ 359 static bool 360 db_elf_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename, int *linenum, db_expr_t off) 361 { 362 363 /* 364 * XXX We don't support this (yet). 365 */ 366 return (false); 367 } 368 369 /* 370 * Returns the number of arguments to a function and their 371 * names if we can find the appropriate debugging symbol. 372 */ 373 static bool 374 db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp, 375 char **argnamep) 376 { 377 378 /* 379 * XXX We don't support this (yet). 380 */ 381 return (false); 382 } 383 384 static void 385 db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg) 386 { 387 char *strtab; 388 static char suffix[2]; 389 Elf_Sym *symp, *symtab_start, *symtab_end; 390 391 stab = &db_symtabs; 392 393 symtab_start = STAB_TO_SYMSTART(stab); 394 symtab_end = STAB_TO_SYMEND(stab); 395 396 strtab = db_elf_find_strtab(stab); 397 if (strtab == NULL) 398 return; 399 400 for (symp = symtab_start; symp < symtab_end; symp++) 401 if (symp->st_name != 0) { 402 suffix[1] = '\0'; 403 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) { 404 case STT_OBJECT: 405 suffix[0] = '+'; 406 break; 407 case STT_FUNC: 408 suffix[0] = '*'; 409 break; 410 case STT_SECTION: 411 suffix[0] = '&'; 412 break; 413 case STT_FILE: 414 suffix[0] = '/'; 415 break; 416 default: 417 suffix[0] = '\0'; 418 } 419 (*db_forall_func)(stab, (db_sym_t)symp, 420 strtab + symp->st_name, suffix, 0, arg); 421 } 422 return; 423 } 424 #endif /* DB_ELF_SYMBOLS */ 425