Changes in kernel/generic/src/debug/symtab.c [bab75df6:40eab9f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/debug/symtab.c
rbab75df6 r40eab9f 36 36 */ 37 37 38 #include <abi/elf.h> 39 #include <byteorder.h> 40 #include <console/prompt.h> 41 #include <debug/sections.h> 42 #include <errno.h> 43 #include <proc/task.h> 44 #include <stdio.h> 45 #include <str.h> 38 46 #include <symtab.h> 39 #include <byteorder.h>40 #include <str.h>41 #include <stdio.h>42 47 #include <typedefs.h> 43 #include <errno.h> 44 #include <console/prompt.h> 45 46 /** Get name of a symbol that seems most likely to correspond to address. 47 * 48 * @param addr Address. 49 * @param name Place to store pointer to the symbol name. 50 * @param offset Place to store offset from the symbol address. 51 * 52 * @return Zero on success or an error code, ENOENT if not found, 53 * ENOTSUP if symbol table not available. 54 * 55 */ 56 errno_t symtab_name_lookup(uintptr_t addr, const char **name, uintptr_t *offset) 57 { 58 #ifdef CONFIG_SYMTAB 59 size_t i; 60 61 for (i = 1; symbol_table[i].address_le; i++) { 62 if (addr < uint64_t_le2host(symbol_table[i].address_le)) 48 49 static inline const char *symtab_entry_name(debug_sections_t *scs, int entry) 50 { 51 size_t index = scs->symtab[entry].st_name; 52 53 if (index >= scs->strtab_size) 54 return NULL; 55 56 return scs->strtab + index; 57 } 58 59 static inline size_t symtab_next(debug_sections_t *scs, size_t i) 60 { 61 size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t); 62 63 for (; i < symtab_len; i++) { 64 const char *name = symtab_entry_name(scs, i); 65 int st_bind = elf_st_bind(scs->symtab[i].st_info); 66 int st_type = elf_st_type(scs->symtab[i].st_info); 67 68 if (st_bind == STB_LOCAL) 69 continue; 70 71 if (name == NULL || *name == '\0') 72 continue; 73 74 if (st_type == STT_FUNC || st_type == STT_OBJECT) 63 75 break; 64 76 } 65 77 66 if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) { 67 *name = symbol_table[i - 1].symbol_name; 68 if (offset) 69 *offset = addr - 70 uint64_t_le2host(symbol_table[i - 1].address_le); 71 return EOK; 72 } 73 74 *name = NULL; 75 return ENOENT; 76 77 #else 78 *name = NULL; 79 return ENOTSUP; 80 #endif 78 return i; 79 } 80 81 const char *symtab_name_lookup(uintptr_t addr, uintptr_t *symbol_addr, debug_sections_t *scs) 82 { 83 const elf_symbol_t *symtab = scs->symtab; 84 size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t); 85 const char *strtab = scs->strtab; 86 size_t strtab_size = scs->strtab_size; 87 88 if (symtab == NULL || strtab == NULL) 89 return NULL; 90 91 uintptr_t closest_symbol_addr = 0; 92 uintptr_t closest_symbol_name = 0; 93 94 for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) { 95 if (symtab[i].st_value > addr) 96 continue; 97 98 if (symtab[i].st_value + symtab[i].st_size > addr) { 99 closest_symbol_addr = symtab[i].st_value; 100 closest_symbol_name = symtab[i].st_name; 101 break; 102 } 103 104 if (symtab[i].st_value > closest_symbol_addr) { 105 closest_symbol_addr = symtab[i].st_value; 106 closest_symbol_name = symtab[i].st_name; 107 } 108 } 109 110 if (closest_symbol_addr == 0) 111 return NULL; 112 113 if (symbol_addr) 114 *symbol_addr = closest_symbol_addr; 115 116 if (closest_symbol_name >= strtab_size) 117 return NULL; 118 119 return strtab + closest_symbol_name; 81 120 } 82 121 … … 95 134 const char *symtab_fmt_name_lookup(uintptr_t addr) 96 135 { 97 const char *name; 98 errno_t rc = symtab_name_lookup(addr, &name, NULL); 99 100 switch (rc) { 101 case EOK: 102 return name; 103 case ENOENT: 104 return "unknown"; 105 default: 106 return "N/A"; 107 } 108 } 109 110 #ifdef CONFIG_SYMTAB 111 112 /** Find symbols that match the parameter forward and print them. 113 * 114 * @param name Search string 115 * @param startpos Starting position, changes to found position 116 * 117 * @return Pointer to the part of string that should be completed or NULL. 118 * 119 */ 120 static const char *symtab_search_one(const char *name, size_t *startpos) 121 { 122 size_t namelen = str_length(name); 123 124 size_t pos; 125 for (pos = *startpos; symbol_table[pos].address_le; pos++) { 126 const char *curname = symbol_table[pos].symbol_name; 127 128 /* Find a ':' in curname */ 129 const char *colon = str_chr(curname, ':'); 130 if (colon == NULL) 131 continue; 132 133 if (str_length(curname) < namelen) 134 continue; 135 136 if (str_lcmp(name, curname, namelen) == 0) { 137 *startpos = pos; 138 return (curname + str_lsize(curname, namelen)); 139 } 140 } 141 142 return NULL; 143 } 144 145 #endif 136 const char *name = symtab_name_lookup(addr, NULL, &kernel_sections); 137 if (name == NULL) 138 name = "<unknown>"; 139 return name; 140 } 146 141 147 142 /** Return address that corresponds to the entry. … … 152 147 * @param addr Place to store symbol address 153 148 * 154 * @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate 155 * symbol, ENOTSUP - no symbol information available. 149 * @return Zero on success, ENOENT - not found 156 150 * 157 151 */ 158 152 errno_t symtab_addr_lookup(const char *name, uintptr_t *addr) 159 153 { 160 #ifdef CONFIG_SYMTAB 161 size_t found = 0; 162 size_t pos = 0; 163 const char *hint; 164 165 while ((hint = symtab_search_one(name, &pos))) { 166 if (str_length(hint) == 0) { 167 *addr = uint64_t_le2host(symbol_table[pos].address_le); 168 found++; 169 } 170 pos++; 171 } 172 173 if (found > 1) 174 return EOVERFLOW; 175 176 if (found < 1) 177 return ENOENT; 178 179 return EOK; 180 181 #else 182 return ENOTSUP; 183 #endif 154 debug_sections_t *scs = &kernel_sections; 155 size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t); 156 157 for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) { 158 if (str_cmp(name, symtab_entry_name(scs, i)) == 0) { 159 *addr = scs->symtab[i].st_value; 160 return EOK; 161 } 162 } 163 164 return ENOENT; 184 165 } 185 166 … … 187 168 void symtab_print_search(const char *name) 188 169 { 189 #ifdef CONFIG_SYMTAB 190 size_t pos = 0; 191 while (symtab_search_one(name, &pos)) { 192 uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le); 193 char *realname = symbol_table[pos].symbol_name; 194 printf("%p: %s\n", (void *) addr, realname); 195 pos++; 196 } 197 198 #else 199 printf("No symbol information available.\n"); 200 #endif 170 debug_sections_t *scs = &kernel_sections; 171 size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t); 172 173 if (scs->symtab == NULL || scs->strtab == NULL) { 174 printf("No symbol information available.\n"); 175 return; 176 } 177 178 size_t namelen = str_length(name); 179 180 for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) { 181 const char *n = symtab_entry_name(scs, i); 182 183 if (str_lcmp(name, n, namelen) == 0) { 184 printf("%p: %s\n", (void *) scs->symtab[i].st_value, n); 185 } 186 } 201 187 } 202 188 203 189 /** Symtab completion enum, see kernel/generic/include/kconsole.h */ 204 const char *symtab_hints_enum(const char *input, const char **help, 205 void **ctx) 206 { 207 #ifdef CONFIG_SYMTAB 190 const char *symtab_hints_enum(const char *input, const char **help, void **ctx) 191 { 192 debug_sections_t *scs = &kernel_sections; 193 size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t); 194 195 if (scs->symtab == NULL || scs->strtab == NULL) 196 return NULL; 197 198 if (help) 199 *help = NULL; 200 208 201 size_t len = str_length(input); 209 struct symtab_entry **entry = (struct symtab_entry **)ctx; 210 211 if (*entry == NULL) 212 *entry = symbol_table; 213 214 for (; (*entry)->address_le; (*entry)++) { 215 const char *curname = (*entry)->symbol_name; 216 217 /* Find a ':' in curname */ 218 const char *colon = str_chr(curname, ':'); 219 if (colon == NULL) 220 continue; 221 222 if (str_length(curname) < len) 223 continue; 202 for (size_t i = symtab_next(scs, (size_t) *ctx); i < symtab_len; i = symtab_next(scs, i + 1)) { 203 const char *curname = symtab_entry_name(scs, i); 224 204 225 205 if (str_lcmp(input, curname, len) == 0) { 226 (*entry)++; 227 if (help) 228 *help = NULL; 206 *ctx = (void *) (i + 1); 229 207 return (curname + str_lsize(curname, len)); 230 208 } … … 232 210 233 211 return NULL; 234 235 #else236 return NULL;237 #endif238 212 } 239 213
Note:
See TracChangeset
for help on using the changeset viewer.