1 /* $OpenBSD: db_elf.c,v 1.23 2016/09/16 19:13:17 jasper 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/stdint.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/exec.h> 39 40 #include <machine/db_machdep.h> 41 42 #include <ddb/db_elf.h> 43 #include <ddb/db_sym.h> 44 #include <ddb/db_output.h> 45 46 #include <sys/exec_elf.h> 47 48 db_symtab_t db_symtab; 49 50 Elf_Sym *db_elf_sym_lookup(char *); 51 static char *db_elf_find_linetab(db_symtab_t *, size_t *); 52 53 /* 54 * Find the symbol table and strings; tell ddb about them. 55 * 56 * symsize: size of symbol table 57 * symtab: pointer to start of symbol table 58 * esymtab: pointer to end of string table, for checking - rounded up to 59 * integer boundry 60 */ 61 int 62 db_elf_sym_init(int symsize, void *symtab, void *esymtab, const char *name) 63 { 64 Elf_Ehdr *elf; 65 Elf_Shdr *shp; 66 Elf_Sym *symp, *symtab_start, *symtab_end; 67 char *shstrtab, *strtab_start, *strtab_end; 68 int i; 69 char *errstr = ""; 70 71 if (ALIGNED_POINTER(symtab, long) == 0) { 72 db_printf("[ %s symbol table has bad start address %p ]\n", 73 name, symtab); 74 return (0); 75 } 76 77 symtab_start = symtab_end = NULL; 78 strtab_start = strtab_end = NULL; 79 80 /* 81 * The format of the symbols loaded by the boot program is: 82 * 83 * Elf exec header 84 * first section header 85 * . . . 86 * . . . 87 * last section header 88 * first symbol, string, or line table section 89 * . . . 90 * . . . 91 * last symbol, string, or line table section 92 */ 93 94 /* 95 * Validate the Elf header. 96 */ 97 elf = (Elf_Ehdr *)symtab; 98 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || 99 elf->e_ident[EI_CLASS] != ELFCLASS) { 100 errstr = "bad magic"; 101 goto badheader; 102 } 103 104 if (elf->e_machine != ELF_TARG_MACH) { 105 errstr = "bad e_machine"; 106 goto badheader; 107 } 108 109 /* 110 * Find the section header string table (.shstrtab), and look up 111 * the symbol table (.symtab) and string table (.strtab) via their 112 * names in shstrtab, rather than by table type. 113 * This works in the presence of multiple string tables, such as 114 * stabs data found when booting bsd.gdb. 115 */ 116 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); 117 shstrtab = (char *)symtab + shp[elf->e_shstrndx].sh_offset; 118 for (i = 0; i < elf->e_shnum; i++) { 119 if (shp[i].sh_type == SHT_SYMTAB) { 120 int j; 121 122 if (shp[i].sh_offset == 0) 123 continue; 124 symtab_start = (Elf_Sym *)((char *)symtab + 125 shp[i].sh_offset); 126 symtab_end = (Elf_Sym *)((char *)symtab + 127 shp[i].sh_offset + shp[i].sh_size); 128 j = shp[i].sh_link; 129 if (shp[j].sh_offset == 0) 130 continue; 131 strtab_start = (char *)symtab + shp[j].sh_offset; 132 strtab_end = (char *)symtab + shp[j].sh_offset + 133 shp[j].sh_size; 134 break; 135 } 136 137 /* 138 * This is the old way of doing things. 139 * XXX - verify that it's not needed. 140 */ 141 if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) { 142 strtab_start = (char *)symtab + shp[i].sh_offset; 143 strtab_end = (char *)symtab + shp[i].sh_offset + 144 shp[i].sh_size; 145 } else if (strcmp(".symtab", shstrtab+shp[i].sh_name) == 0) { 146 symtab_start = (Elf_Sym *)((char *)symtab + 147 shp[i].sh_offset); 148 symtab_end = (Elf_Sym *)((char *)symtab + 149 shp[i].sh_offset + shp[i].sh_size); 150 } 151 } 152 153 /* 154 * Now, sanity check the symbols against the string table. 155 */ 156 if (symtab_start == NULL || strtab_start == NULL || 157 ALIGNED_POINTER(symtab_start, long) == 0 || 158 ALIGNED_POINTER(strtab_start, long) == 0) { 159 errstr = "symtab unaligned"; 160 goto badheader; 161 } 162 for (symp = symtab_start; symp < symtab_end; symp++) 163 if (symp->st_name + strtab_start > strtab_end) { 164 errstr = "symtab corrupted"; 165 goto badheader; 166 } 167 168 /* 169 * Link the symbol table into the debugger. 170 */ 171 db_symtab.start = (char *)symtab_start; 172 db_symtab.end = (char *)symtab_end; 173 db_symtab.name = name; 174 db_symtab.private = (char *)symtab; 175 176 db_printf("[ using %lu bytes of %s ELF symbol table ]\n", 177 (u_long)roundup(((char *)esymtab - (char *)symtab), sizeof(u_long)), 178 name); 179 180 return (1); 181 182 badheader: 183 db_printf("[ %s ELF symbol table not valid: %s ]\n", name, errstr); 184 return (0); 185 } 186 187 /* 188 * Internal helper function - return a pointer to the string table 189 * for the current symbol table. 190 */ 191 char * 192 db_elf_find_strtab(db_symtab_t *stab) 193 { 194 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 195 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 196 char *shstrtab; 197 int i; 198 199 shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset; 200 for (i = 0; i < elf->e_shnum; i++) { 201 if (shp[i].sh_type == SHT_SYMTAB) 202 return ((char *)elf + shp[shp[i].sh_link].sh_offset); 203 if (strcmp(".strtab", shstrtab+shp[i].sh_name) == 0) 204 return ((char *)elf + shp[i].sh_offset); 205 } 206 207 return (NULL); 208 } 209 210 /* 211 * Internal helper function - return a pointer to the line table 212 * for the current symbol table. 213 */ 214 static char * 215 db_elf_find_linetab(db_symtab_t *stab, size_t *size) 216 { 217 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 218 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 219 char *shstrtab; 220 int i; 221 222 shstrtab = (char *)elf + shp[elf->e_shstrndx].sh_offset; 223 for (i = 0; i < elf->e_shnum; i++) { 224 if ((shp[i].sh_flags & SHF_ALLOC) != 0 && 225 strcmp(".debug_line", shstrtab+shp[i].sh_name) == 0) { 226 *size = shp[i].sh_size; 227 return ((char *)elf + shp[i].sh_offset); 228 } 229 } 230 231 return (NULL); 232 } 233 234 /* 235 * Lookup the symbol with the given name. 236 */ 237 Elf_Sym * 238 db_elf_sym_lookup(char *symstr) 239 { 240 db_symtab_t *stab = &db_symtab; 241 Elf_Sym *symp, *symtab_start, *symtab_end; 242 char *strtab; 243 244 if (stab->private == NULL) 245 return (NULL); 246 247 symtab_start = STAB_TO_SYMSTART(stab); 248 symtab_end = STAB_TO_SYMEND(stab); 249 250 strtab = db_elf_find_strtab(stab); 251 if (strtab == NULL) 252 return (NULL); 253 254 for (symp = symtab_start; symp < symtab_end; symp++) { 255 if (symp->st_name != 0 && 256 db_eqname(strtab + symp->st_name, symstr, 0)) 257 return (symp); 258 } 259 260 return (NULL); 261 } 262 263 /* 264 * Search for the symbol with the given address (matching within the 265 * provided threshold). 266 */ 267 db_sym_t 268 db_elf_sym_search(db_addr_t off, db_strategy_t strategy, 269 db_expr_t *diffp) 270 { 271 db_symtab_t *stab = &db_symtab; 272 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 273 db_expr_t diff = *diffp; 274 275 if (stab->private == NULL) 276 return (NULL); 277 278 symtab_start = STAB_TO_SYMSTART(stab); 279 symtab_end = STAB_TO_SYMEND(stab); 280 281 rsymp = NULL; 282 283 for (symp = symtab_start; symp < symtab_end; symp++) { 284 if (symp->st_name == 0) 285 continue; 286 #if 0 287 /* This prevents me from seeing anythin in locore.s -- eeh */ 288 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && 289 ELF_SYM_TYPE(symp->st_info) != Elf_estt_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 void 335 db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep) 336 { 337 db_symtab_t *stab = &db_symtab; 338 Elf_Sym *symp = (Elf_Sym *)sym; 339 char *strtab; 340 341 if (sym == NULL) { 342 *namep = NULL; 343 return; 344 } 345 346 if (stab->private == NULL) 347 return; 348 349 if (namep) { 350 strtab = db_elf_find_strtab(stab); 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 int 366 db_elf_line_at_pc(db_sym_t cursym, char **filename, 367 int *linenum, db_expr_t off) 368 { 369 db_symtab_t *stab = &db_symtab; 370 static char path[PATH_MAX]; 371 const char *linetab, *dirname, *basename; 372 size_t linetab_size; 373 374 if (stab->private == NULL) 375 return (0); 376 377 linetab = db_elf_find_linetab(stab, &linetab_size); 378 if (linetab == NULL) 379 return (0); 380 381 if (!db_dwarf_line_at_pc(linetab, linetab_size, off, 382 &dirname, &basename, linenum)) 383 return (0); 384 385 if (dirname == NULL) 386 strlcpy(path, basename, sizeof(path)); 387 else 388 snprintf(path, sizeof(path), "%s/%s", dirname, basename); 389 *filename = path; 390 return (1); 391 } 392 393 void 394 db_elf_sym_forall(db_forall_func_t db_forall_func, void *arg) 395 { 396 db_symtab_t *stab = &db_symtab; 397 char *strtab; 398 static char suffix[2]; 399 Elf_Sym *symp, *symtab_start, *symtab_end; 400 401 if (stab->private == NULL) 402 return; 403 404 symtab_start = STAB_TO_SYMSTART(stab); 405 symtab_end = STAB_TO_SYMEND(stab); 406 407 strtab = db_elf_find_strtab(stab); 408 if (strtab == NULL) 409 return; 410 411 for (symp = symtab_start; symp < symtab_end; symp++) 412 if (symp->st_name != 0) { 413 suffix[1] = '\0'; 414 switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) { 415 case STT_OBJECT: 416 suffix[0] = '+'; 417 break; 418 case STT_FUNC: 419 suffix[0] = '*'; 420 break; 421 case STT_SECTION: 422 suffix[0] = '&'; 423 break; 424 case STT_FILE: 425 suffix[0] = '/'; 426 break; 427 default: 428 suffix[0] = '\0'; 429 } 430 (*db_forall_func)((db_sym_t)symp, 431 strtab + symp->st_name, suffix, 0, arg); 432 } 433 } 434 435 int 436 db_value_of_name(char *name, db_expr_t *valuep) 437 { 438 Elf_Sym *sym; 439 440 sym = db_elf_sym_lookup(name); 441 if (sym == NULL) 442 return (0); 443 db_symbol_values((db_sym_t)sym, &name, valuep); 444 return (1); 445 } 446