1 /* $NetBSD: db_elf.c,v 1.10 1999/10/25 13:55:06 kleink 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/types.h> 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/proc.h> 44 45 #include <machine/db_machdep.h> 46 47 #include <ddb/db_sym.h> 48 #include <ddb/db_output.h> 49 #include <ddb/db_extern.h> 50 51 #ifdef DB_ELF_SYMBOLS 52 53 #ifndef DB_ELFSIZE 54 #error Must define DB_ELFSIZE! 55 #endif 56 57 #define ELFSIZE DB_ELFSIZE 58 59 #include <sys/exec_elf.h> 60 61 static char *db_elf_find_strtab __P((db_symtab_t *)); 62 63 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) 64 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) 65 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) 66 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) 67 68 boolean_t db_elf_sym_init __P((int, void *, void *, const char *)); 69 db_sym_t db_elf_lookup __P((db_symtab_t *, char *)); 70 db_sym_t db_elf_search_symbol __P((db_symtab_t *, db_addr_t, 71 db_strategy_t, db_expr_t *)); 72 void db_elf_symbol_values __P((db_symtab_t *, db_sym_t, 73 char **, db_expr_t *)); 74 boolean_t db_elf_line_at_pc __P((db_symtab_t *, db_sym_t, 75 char **, int *, db_expr_t)); 76 boolean_t db_elf_sym_numargs __P((db_symtab_t *, db_sym_t, int *, 77 char **)); 78 79 db_symformat_t db_symformat_elf = { 80 "ELF", 81 db_elf_sym_init, 82 db_elf_lookup, 83 db_elf_search_symbol, 84 db_elf_symbol_values, 85 db_elf_line_at_pc, 86 db_elf_sym_numargs, 87 }; 88 89 /* 90 * Find the symbol table and strings; tell ddb about them. 91 */ 92 boolean_t 93 db_elf_sym_init(symsize, symtab, esymtab, name) 94 int symsize; /* size of symbol table */ 95 void *symtab; /* pointer to start of symbol table */ 96 void *esymtab; /* pointer to end of string table, 97 for checking - rounded up to integer 98 boundary */ 99 const char *name; 100 { 101 Elf_Ehdr *elf; 102 Elf_Shdr *shp; 103 Elf_Sym *symp, *symtab_start, *symtab_end; 104 char *strtab_start, *strtab_end; 105 int i; 106 107 if (ALIGNED_POINTER(symtab, long) == 0) { 108 printf("[ %s symbol table has bad start address %p ]\n", 109 name, symtab); 110 return (FALSE); 111 } 112 113 symtab_start = symtab_end = NULL; 114 strtab_start = strtab_end = NULL; 115 116 /* 117 * The format of the symbols loaded by the boot program is: 118 * 119 * Elf exec header 120 * first section header 121 * . . . 122 * . . . 123 * last section header 124 * first symbol or string table section 125 * . . . 126 * . . . 127 * last symbol or string table section 128 */ 129 130 /* 131 * Validate the Elf header. 132 */ 133 elf = (Elf_Ehdr *)symtab; 134 if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 || 135 elf->e_ident[EI_CLASS] != ELFCLASS) 136 goto badheader; 137 138 switch (elf->e_machine) { 139 140 ELFDEFNNAME(MACHDEP_ID_CASES) 141 142 default: 143 goto badheader; 144 } 145 146 /* 147 * We need to avoid the section header string table (small string 148 * table which names the sections). We do this by assuming that 149 * the following two conditions will be true: 150 * 151 * (1) .shstrtab will be smaller than one page. 152 * (2) .strtab will be larger than one page. 153 * 154 * When we encounter what we think is the .shstrtab, we change 155 * its section type Elf_sht_null so that it will be ignored 156 * later. 157 */ 158 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); 159 for (i = 0; i < elf->e_shnum; i++) { 160 switch (shp[i].sh_type) { 161 case SHT_STRTAB: 162 if (shp[i].sh_size < NBPG) { 163 shp[i].sh_type = SHT_NULL; 164 continue; 165 } 166 if (strtab_start != NULL) 167 goto multiple_strtab; 168 strtab_start = (char *)symtab + shp[i].sh_offset; 169 strtab_end = (char *)symtab + shp[i].sh_offset + 170 shp[i].sh_size; 171 break; 172 173 case SHT_SYMTAB: 174 if (symtab_start != NULL) 175 goto multiple_symtab; 176 symtab_start = (Elf_Sym *)((char *)symtab + 177 shp[i].sh_offset); 178 symtab_end = (Elf_Sym *)((char *)symtab + 179 shp[i].sh_offset + shp[i].sh_size); 180 break; 181 182 default: 183 /* Ignore all other sections. */ 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 printf("[ preserving %lu bytes of %s ELF symbol table ]\n", 205 (u_long)roundup(((char *)esymtab - (char *)symtab), 206 sizeof(u_long)), name); 207 return (TRUE); 208 } 209 210 return (FALSE); 211 212 badheader: 213 printf("[ %s ELF symbol table not valid ]\n", name); 214 return (FALSE); 215 216 multiple_strtab: 217 printf("[ %s has multiple ELF string tables ]\n", name); 218 return (FALSE); 219 220 multiple_symtab: 221 printf("[ %s has multiple ELF symbol tables ]\n", name); 222 return (FALSE); 223 } 224 225 /* 226 * Internal helper function - return a pointer to the string table 227 * for the current symbol table. 228 */ 229 static char * 230 db_elf_find_strtab(stab) 231 db_symtab_t *stab; 232 { 233 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 234 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 235 int i; 236 237 for (i = 0; i < elf->e_shnum; i++) { 238 if (shp[i].sh_type == SHT_STRTAB) 239 return (stab->private + shp[i].sh_offset); 240 } 241 242 return (NULL); 243 } 244 245 /* 246 * Lookup the symbol with the given name. 247 */ 248 db_sym_t 249 db_elf_lookup(stab, symstr) 250 db_symtab_t *stab; 251 char *symstr; 252 { 253 Elf_Sym *symp, *symtab_start, *symtab_end; 254 char *strtab; 255 256 symtab_start = STAB_TO_SYMSTART(stab); 257 symtab_end = STAB_TO_SYMEND(stab); 258 259 strtab = db_elf_find_strtab(stab); 260 if (strtab == NULL) 261 return ((db_sym_t)0); 262 263 for (symp = symtab_start; symp < symtab_end; symp++) { 264 if (symp->st_name != 0 && 265 db_eqname(strtab + symp->st_name, symstr, 0)) 266 return ((db_sym_t)symp); 267 } 268 269 return ((db_sym_t)0); 270 } 271 272 /* 273 * Search for the symbol with the given address (matching within the 274 * provided threshold). 275 */ 276 db_sym_t 277 db_elf_search_symbol(symtab, off, strategy, diffp) 278 db_symtab_t *symtab; 279 db_addr_t off; 280 db_strategy_t strategy; 281 db_expr_t *diffp; /* in/out */ 282 { 283 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 284 db_expr_t diff = *diffp; 285 286 symtab_start = STAB_TO_SYMSTART(symtab); 287 symtab_end = STAB_TO_SYMEND(symtab); 288 289 rsymp = NULL; 290 291 for (symp = symtab_start; symp < symtab_end; symp++) { 292 if (symp->st_name == 0) 293 continue; 294 #if 0 295 /* This prevents me from seeing anythin in locore.s -- eeh */ 296 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && 297 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func) 298 continue; 299 #endif 300 301 if (off >= symp->st_value) { 302 if ((off - symp->st_value) < diff) { 303 diff = off - symp->st_value; 304 rsymp = symp; 305 if (diff == 0) { 306 if (strategy == DB_STGY_PROC && 307 ELFDEFNNAME(ST_TYPE)(symp->st_info) 308 == STT_FUNC && 309 ELFDEFNNAME(ST_BIND)(symp->st_info) 310 != STB_LOCAL) 311 break; 312 if (strategy == DB_STGY_ANY && 313 ELFDEFNNAME(ST_BIND)(symp->st_info) 314 != STB_LOCAL) 315 break; 316 } 317 } else if ((off - symp->st_value) == diff) { 318 if (rsymp == NULL) 319 rsymp = symp; 320 else if (ELFDEFNNAME(ST_BIND)(rsymp->st_info) 321 == STB_LOCAL && 322 ELFDEFNNAME(ST_BIND)(symp->st_info) 323 != STB_LOCAL) { 324 /* pick the external symbol */ 325 rsymp = symp; 326 } 327 } 328 } 329 } 330 331 if (rsymp == NULL) 332 *diffp = off; 333 else 334 *diffp = diff; 335 336 return ((db_sym_t)rsymp); 337 } 338 339 /* 340 * Return the name and value for a symbol. 341 */ 342 void 343 db_elf_symbol_values(symtab, sym, namep, valuep) 344 db_symtab_t *symtab; 345 db_sym_t sym; 346 char **namep; 347 db_expr_t *valuep; 348 { 349 Elf_Sym *symp = (Elf_Sym *)sym; 350 char *strtab; 351 352 if (namep) { 353 strtab = db_elf_find_strtab(symtab); 354 if (strtab == NULL) 355 *namep = NULL; 356 else 357 *namep = strtab + symp->st_name; 358 } 359 360 if (valuep) 361 *valuep = symp->st_value; 362 } 363 364 /* 365 * Return the file and line number of the current program counter 366 * if we can find the appropriate debugging symbol. 367 */ 368 boolean_t 369 db_elf_line_at_pc(symtab, cursym, filename, linenum, off) 370 db_symtab_t *symtab; 371 db_sym_t cursym; 372 char **filename; 373 int *linenum; 374 db_expr_t off; 375 { 376 377 /* 378 * XXX We don't support this (yet). 379 */ 380 return (FALSE); 381 } 382 383 /* 384 * Returns the number of arguments to a function and their 385 * names if we can find the appropriate debugging symbol. 386 */ 387 boolean_t 388 db_elf_sym_numargs(symtab, cursym, nargp, argnamep) 389 db_symtab_t *symtab; 390 db_sym_t cursym; 391 int *nargp; 392 char **argnamep; 393 { 394 395 /* 396 * XXX We don't support this (yet). 397 */ 398 return (FALSE); 399 } 400 #endif /* DB_ELF_SYMBOLS */ 401