1 /* $OpenBSD: db_sym.c,v 1.53 2017/05/30 15:39:05 mpi Exp $ */ 2 /* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */ 3 4 /* 5 * Mach Operating System 6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie Mellon 27 * the rights to redistribute these changes. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 33 #include <machine/db_machdep.h> 34 35 #include <ddb/db_lex.h> 36 #include <ddb/db_sym.h> 37 #include <ddb/db_output.h> 38 #include <ddb/db_command.h> 39 40 extern char end[]; 41 42 /* 43 * Initialize the kernel debugger by initializing the master symbol 44 * table. Note that if initializing the master symbol table fails, 45 * no other symbol tables can be loaded. 46 */ 47 void 48 ddb_init(void) 49 { 50 const char *name = "bsd"; 51 extern char *esym; 52 #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \ 53 defined(__i386__) 54 extern char *ssym; 55 #endif 56 char *xssym, *xesym; 57 58 xesym = esym; 59 #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \ 60 defined(__i386__) 61 xssym = ssym; 62 #else 63 xssym = (char *)&end; 64 #endif 65 /* 66 * Do this check now for the master symbol table to avoid printing 67 * the message N times. 68 */ 69 if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) { 70 printf("[ %s symbol table has bad start address %p ]\n", 71 name, xssym); 72 return; 73 } 74 75 if (xesym != NULL && xesym != xssym) { 76 if (db_elf_sym_init((vaddr_t)xesym - (vaddr_t)xssym, xssym, 77 xesym, name) == 1) 78 return; 79 } 80 81 printf("[ no symbol table formats found ]\n"); 82 } 83 84 int 85 db_eqname(char *src, char *dst, int c) 86 { 87 if (!strcmp(src, dst)) 88 return (1); 89 if (src[0] == c) 90 return (!strcmp(src+1,dst)); 91 return (0); 92 } 93 94 /* 95 * Find the closest symbol to val, and return its name 96 * and the difference between val and the symbol found. 97 */ 98 Elf_Sym * 99 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp) 100 { 101 unsigned int diff; 102 db_expr_t newdiff; 103 Elf_Sym *ret = NULL, *sym; 104 105 newdiff = diff = ~0; 106 sym = db_elf_sym_search(val, strategy, &newdiff); 107 if (newdiff < diff) { 108 diff = newdiff; 109 ret = sym; 110 } 111 *offp = diff; 112 return ret; 113 } 114 115 /* 116 * Print a the closest symbol to value 117 * 118 * After matching the symbol according to the given strategy 119 * we print it in the name+offset format, provided the symbol's 120 * value is close enough (eg smaller than db_maxoff). 121 * We also attempt to print [filename:linenum] when applicable 122 * (eg for procedure names). 123 * 124 * If we could not find a reasonable name+offset representation, 125 * then we just print the value in hex. Small values might get 126 * bogus symbol associations, e.g. 3 might get some absolute 127 * value like _INCLUDE_VERSION or something, therefore we do 128 * not accept symbols whose value is zero (and use plain hex). 129 * Also, avoid printing as "end+0x????" which is useless. 130 * The variable db_lastsym is used instead of "end" in case we 131 * add support for symbols in loadable driver modules. 132 */ 133 unsigned long db_lastsym = (unsigned long)end; 134 unsigned int db_maxoff = 0x10000000; 135 136 137 void 138 db_printsym(db_expr_t off, db_strategy_t strategy, 139 int (*pr)(const char *, ...)) 140 { 141 db_expr_t d; 142 char *filename; 143 char *name; 144 db_expr_t value; 145 int linenum; 146 Elf_Sym *cursym; 147 char buf[DB_FORMAT_BUF_SIZE]; 148 149 if (off <= db_lastsym) { 150 cursym = db_search_symbol(off, strategy, &d); 151 db_symbol_values(cursym, &name, &value); 152 if (name && (d < db_maxoff) && value) { 153 (*pr)("%s", name); 154 if (d) { 155 (*pr)("+%s", db_format(buf, sizeof(buf), 156 d, DB_FORMAT_R, 1, 0)); 157 } 158 if (strategy == DB_STGY_PROC) { 159 if (db_elf_line_at_pc(cursym, &filename, 160 &linenum, off)) 161 (*pr)(" [%s:%d]", filename, linenum); 162 } 163 return; 164 } 165 } 166 167 (*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0)); 168 return; 169 } 170