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