1 /* $NetBSD: db_elf.c,v 1.8 1999/01/08 18:10:35 augustss 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 #define CONCAT(x,y) __CONCAT(x,y) 62 #define ELFDEFNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) 63 64 static char *db_elf_find_strtab __P((db_symtab_t *)); 65 66 #define STAB_TO_SYMSTART(stab) ((Elf_Sym *)((stab)->start)) 67 #define STAB_TO_SYMEND(stab) ((Elf_Sym *)((stab)->end)) 68 #define STAB_TO_EHDR(stab) ((Elf_Ehdr *)((stab)->private)) 69 #define STAB_TO_SHDR(stab, e) ((Elf_Shdr *)((stab)->private + (e)->e_shoff)) 70 71 boolean_t db_elf_sym_init __P((int, void *, void *, const char *)); 72 db_sym_t db_elf_lookup __P((db_symtab_t *, char *)); 73 db_sym_t db_elf_search_symbol __P((db_symtab_t *, db_addr_t, 74 db_strategy_t, db_expr_t *)); 75 void db_elf_symbol_values __P((db_symtab_t *, db_sym_t, 76 char **, db_expr_t *)); 77 boolean_t db_elf_line_at_pc __P((db_symtab_t *, db_sym_t, 78 char **, int *, db_expr_t)); 79 boolean_t db_elf_sym_numargs __P((db_symtab_t *, db_sym_t, int *, 80 char **)); 81 82 db_symformat_t db_symformat_elf = { 83 "ELF", 84 db_elf_sym_init, 85 db_elf_lookup, 86 db_elf_search_symbol, 87 db_elf_symbol_values, 88 db_elf_line_at_pc, 89 db_elf_sym_numargs, 90 }; 91 92 /* 93 * Find the symbol table and strings; tell ddb about them. 94 */ 95 boolean_t 96 db_elf_sym_init(symsize, symtab, esymtab, name) 97 int symsize; /* size of symbol table */ 98 void *symtab; /* pointer to start of symbol table */ 99 void *esymtab; /* pointer to end of string table, 100 for checking - rounded up to integer 101 boundary */ 102 const char *name; 103 { 104 Elf_Ehdr *elf; 105 Elf_Shdr *shp; 106 Elf_Sym *symp, *symtab_start, *symtab_end; 107 char *strtab_start, *strtab_end; 108 int i; 109 110 if (ALIGNED_POINTER(symtab, long) == 0) { 111 printf("[ %s symbol table has bad start address %p ]\n", 112 name, symtab); 113 return (FALSE); 114 } 115 116 symtab_start = symtab_end = NULL; 117 strtab_start = strtab_end = NULL; 118 119 /* 120 * The format of the symbols loaded by the boot program is: 121 * 122 * Elf exec header 123 * first section header 124 * . . . 125 * . . . 126 * last section header 127 * first symbol or string table section 128 * . . . 129 * . . . 130 * last symbol or string table section 131 */ 132 133 /* 134 * Validate the Elf header. 135 */ 136 elf = (Elf_Ehdr *)symtab; 137 if (memcmp(elf->e_ident, Elf_e_ident, Elf_e_siz) != 0) 138 goto badheader; 139 140 switch (elf->e_machine) { 141 142 ELFDEFNAME(MACHDEP_ID_CASES) 143 144 default: 145 goto badheader; 146 } 147 148 /* 149 * We need to avoid the section header string table (small string 150 * table which names the sections). We do this by assuming that 151 * the following two conditions will be true: 152 * 153 * (1) .shstrtab will be smaller than one page. 154 * (2) .strtab will be larger than one page. 155 * 156 * When we encounter what we think is the .shstrtab, we change 157 * its section type Elf_sht_null so that it will be ignored 158 * later. 159 */ 160 shp = (Elf_Shdr *)((char *)symtab + elf->e_shoff); 161 for (i = 0; i < elf->e_shnum; i++) { 162 switch (shp[i].sh_type) { 163 case Elf_sht_strtab: 164 if (shp[i].sh_size < NBPG) { 165 shp[i].sh_type = Elf_sht_null; 166 continue; 167 } 168 if (strtab_start != NULL) 169 goto multiple_strtab; 170 strtab_start = (char *)symtab + shp[i].sh_offset; 171 strtab_end = (char *)symtab + shp[i].sh_offset + 172 shp[i].sh_size; 173 break; 174 175 case Elf_sht_symtab: 176 if (symtab_start != NULL) 177 goto multiple_symtab; 178 symtab_start = (Elf_Sym *)((char *)symtab + 179 shp[i].sh_offset); 180 symtab_end = (Elf_Sym *)((char *)symtab + 181 shp[i].sh_offset + shp[i].sh_size); 182 break; 183 184 default: 185 /* Ignore all other sections. */ 186 break; 187 } 188 } 189 190 /* 191 * Now, sanity check the symbols against the string table. 192 */ 193 if (symtab_start == NULL || strtab_start == NULL || 194 ALIGNED_POINTER(symtab_start, long) == 0 || 195 ALIGNED_POINTER(strtab_start, long) == 0) 196 goto badheader; 197 for (symp = symtab_start; symp < symtab_end; symp++) 198 if (symp->st_name + strtab_start > strtab_end) 199 goto badheader; 200 201 /* 202 * Link the symbol table into the debugger. 203 */ 204 if (db_add_symbol_table((char *)symtab_start, 205 (char *)symtab_end, name, (char *)symtab) != -1) { 206 printf("[ preserving %lu bytes of %s ELF symbol table ]\n", 207 (u_long)roundup(((char *)esymtab - (char *)symtab), 208 sizeof(u_long)), name); 209 return (TRUE); 210 } 211 212 return (FALSE); 213 214 badheader: 215 printf("[ %s ELF symbol table not valid ]\n", name); 216 return (FALSE); 217 218 multiple_strtab: 219 printf("[ %s has multiple ELF string tables ]\n", name); 220 return (FALSE); 221 222 multiple_symtab: 223 printf("[ %s has multiple ELF symbol tables ]\n", name); 224 return (FALSE); 225 } 226 227 /* 228 * Internal helper function - return a pointer to the string table 229 * for the current symbol table. 230 */ 231 static char * 232 db_elf_find_strtab(stab) 233 db_symtab_t *stab; 234 { 235 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 236 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 237 int i; 238 239 for (i = 0; i < elf->e_shnum; i++) { 240 if (shp[i].sh_type == Elf_sht_strtab) 241 return (stab->private + shp[i].sh_offset); 242 } 243 244 return (NULL); 245 } 246 247 /* 248 * Lookup the symbol with the given name. 249 */ 250 db_sym_t 251 db_elf_lookup(stab, symstr) 252 db_symtab_t *stab; 253 char *symstr; 254 { 255 Elf_Sym *symp, *symtab_start, *symtab_end; 256 char *strtab; 257 258 symtab_start = STAB_TO_SYMSTART(stab); 259 symtab_end = STAB_TO_SYMEND(stab); 260 261 strtab = db_elf_find_strtab(stab); 262 if (strtab == NULL) 263 return ((db_sym_t)0); 264 265 for (symp = symtab_start; symp < symtab_end; symp++) { 266 if (symp->st_name != 0 && 267 db_eqname(strtab + symp->st_name, symstr, 0)) 268 return ((db_sym_t)symp); 269 } 270 271 return ((db_sym_t)0); 272 } 273 274 /* 275 * Search for the symbol with the given address (matching within the 276 * provided threshold). 277 */ 278 db_sym_t 279 db_elf_search_symbol(symtab, off, strategy, diffp) 280 db_symtab_t *symtab; 281 db_addr_t off; 282 db_strategy_t strategy; 283 db_expr_t *diffp; /* in/out */ 284 { 285 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 286 db_expr_t diff = *diffp; 287 288 symtab_start = STAB_TO_SYMSTART(symtab); 289 symtab_end = STAB_TO_SYMEND(symtab); 290 291 rsymp = NULL; 292 293 for (symp = symtab_start; symp < symtab_end; symp++) { 294 if (symp->st_name == 0) 295 continue; 296 #if 0 297 /* This prevents me from seeing anythin in locore.s -- eeh */ 298 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && 299 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func) 300 continue; 301 #endif 302 303 if (off >= symp->st_value) { 304 if ((off - symp->st_value) < diff) { 305 diff = off - symp->st_value; 306 rsymp = symp; 307 if (diff == 0) { 308 if (strategy == DB_STGY_PROC && 309 ELF_SYM_TYPE(symp->st_info) == 310 Elf_estt_func && 311 ELF_SYM_BIND(symp->st_info) != 312 Elf_estb_local) 313 break; 314 if (strategy == DB_STGY_ANY && 315 ELF_SYM_BIND(symp->st_info) != 316 Elf_estb_local) 317 break; 318 } 319 } else if ((off - symp->st_value) == diff) { 320 if (rsymp == NULL) 321 rsymp = symp; 322 else if (ELF_SYM_BIND(rsymp->st_info) == 323 Elf_estb_local && 324 ELF_SYM_BIND(symp->st_info) != 325 Elf_estb_local) { 326 /* pick the external symbol */ 327 rsymp = symp; 328 } 329 } 330 } 331 } 332 333 if (rsymp == NULL) 334 *diffp = off; 335 else 336 *diffp = diff; 337 338 return ((db_sym_t)rsymp); 339 } 340 341 /* 342 * Return the name and value for a symbol. 343 */ 344 void 345 db_elf_symbol_values(symtab, sym, namep, valuep) 346 db_symtab_t *symtab; 347 db_sym_t sym; 348 char **namep; 349 db_expr_t *valuep; 350 { 351 Elf_Sym *symp = (Elf_Sym *)sym; 352 char *strtab; 353 354 if (namep) { 355 strtab = db_elf_find_strtab(symtab); 356 if (strtab == NULL) 357 *namep = NULL; 358 else 359 *namep = strtab + symp->st_name; 360 } 361 362 if (valuep) 363 *valuep = symp->st_value; 364 } 365 366 /* 367 * Return the file and line number of the current program counter 368 * if we can find the appropriate debugging symbol. 369 */ 370 boolean_t 371 db_elf_line_at_pc(symtab, cursym, filename, linenum, off) 372 db_symtab_t *symtab; 373 db_sym_t cursym; 374 char **filename; 375 int *linenum; 376 db_expr_t off; 377 { 378 379 /* 380 * XXX We don't support this (yet). 381 */ 382 return (FALSE); 383 } 384 385 /* 386 * Returns the number of arguments to a function and their 387 * names if we can find the appropriate debugging symbol. 388 */ 389 boolean_t 390 db_elf_sym_numargs(symtab, cursym, nargp, argnamep) 391 db_symtab_t *symtab; 392 db_sym_t cursym; 393 int *nargp; 394 char **argnamep; 395 { 396 397 /* 398 * XXX We don't support this (yet). 399 */ 400 return (FALSE); 401 } 402 #endif /* DB_ELF_SYMBOLS */ 403