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