1 /* $NetBSD: db_elf.c,v 1.3 1997/11/30 15:49:35 drochner 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 ALIGNED_POINTER(symtab_start, long) == 0 || 171 ALIGNED_POINTER(strtab_start, long) == 0) 172 goto badheader; 173 for (symp = symtab_start; symp < symtab_end; symp++) 174 if (symp->st_name + strtab_start > strtab_end) 175 goto badheader; 176 177 /* 178 * Link the symbol table into the debugger. 179 */ 180 if (db_add_symbol_table((char *)symtab_start, 181 (char *)symtab_end, name, (char *)symtab) != -1) 182 printf("[ preserving %lu bytes of %s symbol table ]\n", 183 (u_long)roundup((esymtab - symtab), sizeof(u_long)), name); 184 return; 185 186 badheader: 187 printf("[ %s symbol table not valid ]\n", name); 188 return; 189 190 multiple_strtab: 191 printf("[ %s has multiple string tables ]\n", name); 192 return; 193 194 multiple_symtab: 195 printf("[ %s has multiple symbol tables ]\n", name); 196 return; 197 } 198 199 /* 200 * Internal helper function - return a pointer to the string table 201 * for the current symbol table. 202 */ 203 static char * 204 db_elf_find_strtab(stab) 205 db_symtab_t *stab; 206 { 207 Elf_Ehdr *elf = STAB_TO_EHDR(stab); 208 Elf_Shdr *shp = STAB_TO_SHDR(stab, elf); 209 int i; 210 211 for (i = 0; i < elf->e_shnum; i++) { 212 if (shp[i].sh_type == Elf_sht_strtab) 213 return (stab->private + shp[i].sh_offset); 214 } 215 216 return (NULL); 217 } 218 219 /* 220 * Lookup the symbol with the given name. 221 */ 222 db_sym_t 223 X_db_lookup(stab, symstr) 224 db_symtab_t *stab; 225 char *symstr; 226 { 227 Elf_Sym *symp, *symtab_start, *symtab_end; 228 char *strtab; 229 230 symtab_start = STAB_TO_SYMSTART(stab); 231 symtab_end = STAB_TO_SYMEND(stab); 232 233 strtab = db_elf_find_strtab(stab); 234 if (strtab == NULL) 235 return ((db_sym_t)0); 236 237 for (symp = symtab_start; symp < symtab_end; symp++) { 238 if (symp->st_name != 0 && 239 db_eqname(strtab + symp->st_name, symstr, 0)) 240 return ((db_sym_t)symp); 241 } 242 243 return ((db_sym_t)0); 244 } 245 246 /* 247 * Search for the symbol with the given address (matching within the 248 * provided threshold). 249 */ 250 db_sym_t 251 X_db_search_symbol(symtab, off, strategy, diffp) 252 db_symtab_t *symtab; 253 db_addr_t off; 254 db_strategy_t strategy; 255 db_expr_t *diffp; /* in/out */ 256 { 257 Elf_Sym *rsymp, *symp, *symtab_start, *symtab_end; 258 db_expr_t diff = *diffp; 259 260 symtab_start = STAB_TO_SYMSTART(symtab); 261 symtab_end = STAB_TO_SYMEND(symtab); 262 263 rsymp = NULL; 264 265 for (symp = symtab_start; symp < symtab_end; symp++) { 266 if (symp->st_name == 0) 267 continue; 268 if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object && 269 ELF_SYM_TYPE(symp->st_info) != Elf_estt_func) 270 continue; 271 272 if (off >= symp->st_value) { 273 if ((off - symp->st_value) < diff) { 274 diff = off - symp->st_value; 275 rsymp = symp; 276 if (diff == 0) { 277 if (strategy == DB_STGY_PROC && 278 ELF_SYM_TYPE(symp->st_info) == 279 Elf_estt_func && 280 ELF_SYM_BIND(symp->st_info) != 281 Elf_estb_local) 282 break; 283 if (strategy == DB_STGY_ANY && 284 ELF_SYM_BIND(symp->st_info) != 285 Elf_estb_local) 286 break; 287 } 288 } else if ((off - symp->st_value) == diff) { 289 if (rsymp == NULL) 290 rsymp = symp; 291 else if (ELF_SYM_BIND(rsymp->st_info) == 292 Elf_estb_local && 293 ELF_SYM_BIND(symp->st_info) != 294 Elf_estb_local) { 295 /* pick the external symbol */ 296 rsymp = symp; 297 } 298 } 299 } 300 } 301 302 if (rsymp == NULL) 303 *diffp = off; 304 else 305 *diffp = diff; 306 307 return ((db_sym_t)rsymp); 308 } 309 310 /* 311 * Return the name and value for a symbol. 312 */ 313 void 314 X_db_symbol_values(symtab, sym, namep, valuep) 315 db_symtab_t *symtab; 316 db_sym_t sym; 317 char **namep; 318 db_expr_t *valuep; 319 { 320 Elf_Sym *symp = (Elf_Sym *)sym; 321 char *strtab; 322 323 if (namep) { 324 strtab = db_elf_find_strtab(symtab); 325 if (strtab == NULL) 326 *namep = NULL; 327 else 328 *namep = strtab + symp->st_name; 329 } 330 331 if (valuep) 332 *valuep = symp->st_value; 333 } 334 335 /* 336 * Return the file and line number of the current program counter 337 * if we can find the appropriate debugging symbol. 338 */ 339 boolean_t 340 X_db_line_at_pc(symtab, cursym, filename, linenum, off) 341 db_symtab_t *symtab; 342 db_sym_t cursym; 343 char **filename; 344 int *linenum; 345 db_expr_t off; 346 { 347 348 /* 349 * XXX We don't support this (yet). 350 */ 351 return (FALSE); 352 } 353 354 /* 355 * Returns the number of arguments to a function and their 356 * names if we can find the appropriate debugging symbol. 357 */ 358 boolean_t 359 X_db_sym_numargs(symtab, cursym, nargp, argnamep) 360 db_symtab_t *symtab; 361 db_sym_t cursym; 362 int *nargp; 363 char **argnamep; 364 { 365 366 /* 367 * XXX We don't support this (yet). 368 */ 369 return (FALSE); 370 } 371 372 /* 373 * Initialization routine for Elf files. 374 */ 375 void 376 ddb_init(sym_start, sym_end) 377 void *sym_start, *sym_end; 378 { 379 380 if (sym_end > sym_start) 381 X_db_sym_init(sym_start, sym_end, "netbsd"); 382 } 383 384 #endif /* DB_ELF_SYMBOLS */ 385