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