1 /* $NetBSD: db_elf.c,v 1.27 2009/03/14 15:36:16 dsl 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.27 2009/03/14 15:36:16 dsl Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/proc.h> 39 40 #include <ddb/ddb.h> 41 42 #include <machine/pmap.h> 43 #include <machine/vmparam.h> 44 45 #ifdef DB_ELF_SYMBOLS 46 47 #ifndef DB_ELFSIZE 48 #error Must define DB_ELFSIZE! 49 #endif 50 51 #define ELFSIZE DB_ELFSIZE 52 53 #include <sys/exec_elf.h> 54 55 static char *db_elf_find_strtab(db_symtab_t *); 56 57 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) 58 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) 59 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) 60 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) 61 62 static bool db_elf_sym_init(int, void *, void *, const char *); 63 static db_sym_t db_elf_lookup(db_symtab_t *, const char *); 64 static db_sym_t db_elf_search_symbol(db_symtab_t *, db_addr_t, db_strategy_t, 65 db_expr_t *); 66 static void db_elf_symbol_values(db_symtab_t *, db_sym_t, const char **, 67 db_expr_t *); 68 static bool db_elf_line_at_pc(db_symtab_t *, db_sym_t, char **, int *, 69 db_expr_t); 70 static bool db_elf_sym_numargs(db_symtab_t *, db_sym_t, int *, char **); 71 static void db_elf_forall(db_symtab_t *, db_forall_func_t db_forall_func, 72 void *); 73 74 const db_symformat_t db_symformat_elf = { 75 "ELF", 76 db_elf_sym_init, 77 db_elf_lookup, 78 db_elf_search_symbol, 79 db_elf_symbol_values, 80 db_elf_line_at_pc, 81 db_elf_sym_numargs, 82 db_elf_forall 83 }; 84 85 static db_symtab_t db_symtabs; 86 87 /* 88 * Add symbol table, with given name, to symbol tables. 89 */ 90 static int 91 db_add_symbol_table(char *start, char *end, const char *name, char *ref) 92 { 93 94 db_symtabs.start = start; 95 db_symtabs.end = end; 96 db_symtabs.name = name; 97 db_symtabs.private = ref; 98 99 return(0); 100 } 101 102 /* 103 * Find the symbol table and strings; tell ddb about them. 104 */ 105 static bool 106 db_elf_sym_init( 107 int symsize, /* size of symbol table */ 108 void *symtab, /* pointer to start of symbol table */ 109 void *esymtab, /* pointer to end of string table, 110 for checking - rounded up to integer 111 boundary */ 112 const char *name 113 ) 114 { 115 Elf_Ehdr *elf; 116 Elf_Shdr *shp; 117 Elf_Sym *symp, *symtab_start, *symtab_end; 118 char *strtab_start, *strtab_end; 119 int i, j; 120 121 if (ALIGNED_POINTER(symtab, long) == 0) { 122 printf("[ %s symbol table has bad start address %p ]\n", 123 name, symtab); 124 return (false); 125 } 126 127 symtab_start = symtab_end = NULL; 128 strtab_start = strtab_end = NULL; 129 130 /* 131 * The format of the symbols loaded by the boot program is: 132 * 133 * Elf exec header 134 * first section header 135 * . . . 136 * . . . 137 * last section header 138 * first symbol or string table section 139 * . . . 140 * . . . 141 * last symbol or string table section 142 */ 143 144 /* 145 * Validate the Elf header. 146 */ 147 elf = (Elf_Ehdr *)symtab; 148 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || 149 elf->e_ident[EI_CLASS] != ELFCLASS) 150 goto badheader; 151 152 switch (elf->e_machine) { 153 154 ELFDEFNNAME(MACHDEP_ID_CASES) 155 156 default: 157 goto badheader; 158 } 159 160 /* 161 * Find the first (and, we hope, only) SHT_SYMTAB section in 162 * the file, and the SHT_STRTAB section that goes with it. 163 */ 164 if (elf->e_shoff == 0) 165 goto badheader; 166 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); 167 for (i = 0; i < elf->e_shnum; i++) { 168 if (shp[i].sh_type == SHT_SYMTAB) { 169 if (shp[i].sh_offset == 0) 170 continue; 171 /* Got the symbol table. */ 172 symtab_start = (Elf_Sym *)((char *)symtab + 173 shp[i].sh_offset); 174 symtab_end = (Elf_Sym *)((char *)symtab + 175 shp[i].sh_offset + shp[i].sh_size); 176 /* Find the string table to go with it. */ 177 j = shp[i].sh_link; 178 if (shp[j].sh_offset == 0) 179 continue; 180 strtab_start = (char *)symtab + shp[j].sh_offset; 181 strtab_end = (char *)symtab + shp[j].sh_offset + 182 shp[j].sh_size; 183 /* There should only be one symbol table. */ 184 break; 185 } 186 } 187 188 /* 189 * Now, sanity check the symbols against the string table. 190 */ 191 if (symtab_start == NULL || strtab_start == NULL || 192 ALIGNED_POINTER(symtab_start, long) == 0 || 193 ALIGNED_POINTER(strtab_start, long) == 0) 194 goto badheader; 195 for (symp = symtab_start; symp < symtab_end; symp++) 196 if (symp->st_name + strtab_start > strtab_end) 197 goto badheader; 198 199 /* 200 * Link the symbol table into the debugger. 201 */ 202 if (db_add_symbol_table((char *)symtab_start, 203 (char *)symtab_end, name, (char *)symtab) != -1) { 204 return (true); 205 } 206 207 return (false); 208 209 badheader: 210 printf("[ %s ELF symbol table not valid ]\n", name); 211 return (false); 212 } 213 214 /* 215 * Internal helper function - return a pointer to the string table 216 * for the current symbol table. 217 */ 218 static char * 219 db_elf_find_strtab(db_symtab_t *stab) 220 { 221 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 222 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 223 int i; 224 225 stab = &db_symtabs; 226 227 /* 228 * We don't load ELF header for ELF modules. 229 * Find out if this is a loadable module. If so, 230 * string table comes right after symbol table. 231 */ 232 if ((Elf_Sym *)elf == STAB_TO_SYMSTART(stab)) { 233 return ((char *)STAB_TO_SYMEND(stab)); 234 } 235 for (i = 0; i < elf->e_shnum; i++) { 236 if (shp[i].sh_type == SHT_SYMTAB) 237 return ((char*)elf + shp[shp[i].sh_link].sh_offset); 238 } 239 240 return (NULL); 241 } 242 243 /* 244 * Lookup the symbol with the given name. 245 */ 246 static db_sym_t 247 db_elf_lookup(db_symtab_t *stab, const char *symstr) 248 { 249 Elf_Sym *symp, *symtab_start, *symtab_end; 250 char *strtab; 251 252 stab = &db_symtabs; 253 254 symtab_start = STAB_TO_SYMSTART(stab); 255 symtab_end = STAB_TO_SYMEND(stab); 256 257 strtab = db_elf_find_strtab(stab); 258 if (strtab == NULL) 259 return ((db_sym_t)0); 260 261 for (symp = symtab_start; symp < symtab_end; symp++) { 262 if (symp->st_name != 0 && 263 db_eqname(strtab + symp->st_name, symstr, 0)) 264 return ((db_sym_t)symp); 265 } 266 267 return ((db_sym_t)0); 268 } 269 270 /* 271 * Search for the symbol with the given address (matching within the 272 * provided threshold). 273 */ 274 static db_sym_t 275 db_elf_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy, 276 db_expr_t *diffp) 277 { 278 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 279 db_addr_t diff = *diffp; 280 281 symtab = &db_symtabs; 282 283 symtab_start = STAB_TO_SYMSTART(symtab); 284 symtab_end = STAB_TO_SYMEND(symtab); 285 286 rsymp = NULL; 287 288 for (symp = symtab_start; symp < symtab_end; symp++) { 289 if (symp->st_name == 0) 290 continue; 291 292 #if 0 293 /* This prevents me from seeing anythin in locore.s -- eeh */ 294 if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT && 295 ELF_ST_TYPE(symp->st_info) != STT_FUNC) 296 continue; 297 #endif 298 299 if (off >= symp->st_value) { 300 if (off - symp->st_value < diff) { 301 diff = off - symp->st_value; 302 rsymp = symp; 303 if (diff == 0) { 304 if (strategy == DB_STGY_PROC && 305 ELFDEFNNAME(ST_TYPE)(symp->st_info) 306 == STT_FUNC && 307 ELFDEFNNAME(ST_BIND)(symp->st_info) 308 != STB_LOCAL) 309 break; 310 if (strategy == DB_STGY_ANY && 311 ELFDEFNNAME(ST_BIND)(symp->st_info) 312 != STB_LOCAL) 313 break; 314 } 315 } else if (off - symp->st_value == diff) { 316 if (rsymp == NULL) 317 rsymp = symp; 318 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info) 319 == STB_LOCAL && 320 ELFDEFNNAME(ST_BIND)(symp->st_info) 321 != STB_LOCAL) { 322 /* pick the external symbol */ 323 rsymp = symp; 324 } 325 } 326 } 327 } 328 329 if (rsymp == NULL) 330 *diffp = off; 331 else 332 *diffp = diff; 333 334 return ((db_sym_t)rsymp); 335 } 336 337 /* 338 * Return the name and value for a symbol. 339 */ 340 static void 341 db_elf_symbol_values(db_symtab_t *symtab, db_sym_t sym, const char **namep, 342 db_expr_t *valuep) 343 { 344 Elf_Sym *symp = (Elf_Sym *)sym; 345 char *strtab; 346 347 symtab = &db_symtabs; 348 349 if (namep) { 350 strtab = db_elf_find_strtab(symtab); 351 if (strtab == NULL) 352 *namep = NULL; 353 else 354 *namep = strtab + symp->st_name; 355 } 356 357 if (valuep) 358 *valuep = symp->st_value; 359 } 360 361 /* 362 * Return the file and line number of the current program counter 363 * if we can find the appropriate debugging symbol. 364 */ 365 static bool 366 db_elf_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename, int *linenum, db_expr_t off) 367 { 368 369 /* 370 * XXX We don't support this (yet). 371 */ 372 return (false); 373 } 374 375 /* 376 * Returns the number of arguments to a function and their 377 * names if we can find the appropriate debugging symbol. 378 */ 379 static bool 380 db_elf_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp, 381 char **argnamep) 382 { 383 384 /* 385 * XXX We don't support this (yet). 386 */ 387 return (false); 388 } 389 390 static void 391 db_elf_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg) 392 { 393 char *strtab; 394 static char suffix[2]; 395 Elf_Sym *symp, *symtab_start, *symtab_end; 396 397 stab = &db_symtabs; 398 399 symtab_start = STAB_TO_SYMSTART(stab); 400 symtab_end = STAB_TO_SYMEND(stab); 401 402 strtab = db_elf_find_strtab(stab); 403 if (strtab == NULL) 404 return; 405 406 for (symp = symtab_start; symp < symtab_end; symp++) 407 if (symp->st_name != 0) { 408 suffix[1] = '\0'; 409 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) { 410 case STT_OBJECT: 411 suffix[0] = '+'; 412 break; 413 case STT_FUNC: 414 suffix[0] = '*'; 415 break; 416 case STT_SECTION: 417 suffix[0] = '&'; 418 break; 419 case STT_FILE: 420 suffix[0] = '/'; 421 break; 422 default: 423 suffix[0] = '\0'; 424 } 425 (*db_forall_func)(stab, (db_sym_t)symp, 426 strtab + symp->st_name, suffix, 0, arg); 427 } 428 return; 429 } 430 #endif /* DB_ELF_SYMBOLS */ 431