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