32,7 → 32,7 |
|
/** |
* @file |
* @brief Kernel symbol resolver. |
* @brief Kernel symbol resolver. |
*/ |
|
#include <symtab.h> |
43,30 → 43,33 |
#include <typedefs.h> |
#include <errno.h> |
|
/** Get name of symbol that seems most likely to correspond to address. |
/** Get name of a symbol that seems most likely to correspond to address. |
* |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* |
* @return Zero on success or negative error code, ENOENT if not found, |
* ENOTSUP if symbol table not available. |
* @return Zero on success or negative error code, ENOENT if not found, |
* ENOTSUP if symbol table not available. |
* |
*/ |
int symtab_name_lookup(unative_t addr, char **name) |
{ |
#ifdef CONFIG_SYMTAB |
count_t i; |
|
for (i = 1; symbol_table[i].address_le; ++i) { |
|
for (i = 1; symbol_table[i].address_le; i++) { |
if (addr < uint64_t_le2host(symbol_table[i].address_le)) |
break; |
} |
|
if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) { |
*name = symbol_table[i - 1].symbol_name; |
return EOK; |
} |
|
|
*name = NULL; |
return ENOENT; |
|
#else |
*name = NULL; |
return ENOTSUP; |
78,21 → 81,24 |
* Returns name of closest corresponding symbol, "Not found" if none exists |
* or "N/A" if no symbol information is available. |
* |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* |
* @return Pointer to a human-readable string. |
* @return Pointer to a human-readable string. |
* |
*/ |
char *symtab_fmt_name_lookup(unative_t addr) |
{ |
int rc; |
char *name; |
|
rc = symtab_name_lookup(addr, &name); |
int rc = symtab_name_lookup(addr, &name); |
|
switch (rc) { |
case EOK: return name; |
case ENOENT: return "Not found"; |
default: return "N/A"; |
case EOK: |
return name; |
case ENOENT: |
return "Not found"; |
default: |
return "N/A"; |
} |
} |
|
100,95 → 106,90 |
|
/** Find symbols that match the parameter forward and print them. |
* |
* @param name - search string |
* @param startpos - starting position, changes to found position |
* @return Pointer to the part of string that should be completed or NULL |
* @param name Search string |
* @param startpos Starting position, changes to found position |
* |
* @return Pointer to the part of string that should be completed or NULL. |
* |
*/ |
static char * symtab_search_one(const char *name, int *startpos) |
static const char *symtab_search_one(const char *name, count_t *startpos) |
{ |
unsigned int namelen = strlen(name); |
char *curname; |
int i, j; |
int colonoffset = -1; |
|
for (i = 0; name[i]; i++) |
if (name[i] == ':') { |
colonoffset = i; |
break; |
} |
|
for (i = *startpos; symbol_table[i].address_le; ++i) { |
/* Find a ':' in name */ |
curname = symbol_table[i].symbol_name; |
for (j = 0; curname[j] && curname[j] != ':'; j++) |
; |
if (!curname[j]) |
count_t namelen = str_length(name); |
|
count_t pos; |
for (pos = *startpos; symbol_table[pos].address_le; pos++) { |
const char *curname = symbol_table[pos].symbol_name; |
|
/* Find a ':' in curname */ |
const char *colon = str_chr(curname, ':'); |
if (colon == NULL) |
continue; |
j -= colonoffset; |
curname += j; |
if (strlen(curname) < namelen) |
|
if (str_length(curname) < namelen) |
continue; |
if (strncmp(curname, name, namelen) == 0) { |
*startpos = i; |
return curname + namelen; |
|
if (str_lcmp(name, curname, namelen) == 0) { |
*startpos = pos; |
return (curname + str_lsize(curname, namelen)); |
} |
} |
|
return NULL; |
} |
|
#endif |
|
/** Return address that corresponds to the entry |
/** Return address that corresponds to the entry. |
* |
* Search symbol table, and if there is one match, return it |
* |
* @param name Name of the symbol |
* @param addr Place to store symbol address |
* @param name Name of the symbol |
* @param addr Place to store symbol address |
* |
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate |
* symbol, ENOTSUP - no symbol information available. |
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate |
* symbol, ENOTSUP - no symbol information available. |
* |
*/ |
int symtab_addr_lookup(const char *name, uintptr_t *addr) |
{ |
#ifdef CONFIG_SYMTAB |
count_t found = 0; |
char *hint; |
int i; |
|
i = 0; |
while ((hint = symtab_search_one(name, &i))) { |
if (!strlen(hint)) { |
*addr = uint64_t_le2host(symbol_table[i].address_le); |
count_t pos = 0; |
const char *hint; |
|
while ((hint = symtab_search_one(name, &pos))) { |
if (str_length(hint) == 0) { |
*addr = uint64_t_le2host(symbol_table[pos].address_le); |
found++; |
} |
i++; |
pos++; |
} |
|
if (found > 1) |
return EOVERFLOW; |
|
if (found < 1) |
return ENOENT; |
|
return EOK; |
|
#else |
return ENOTSUP; |
#endif |
} |
|
/** Find symbols that match parameter and prints them */ |
/** Find symbols that match parameter and print them */ |
void symtab_print_search(const char *name) |
{ |
#ifdef CONFIG_SYMTAB |
int i; |
uintptr_t addr; |
char *realname; |
|
|
i = 0; |
while (symtab_search_one(name, &i)) { |
addr = uint64_t_le2host(symbol_table[i].address_le); |
realname = symbol_table[i].symbol_name; |
count_t pos = 0; |
while (symtab_search_one(name, &pos)) { |
uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le); |
char *realname = symbol_table[pos].symbol_name; |
printf("%p: %s\n", addr, realname); |
i++; |
pos++; |
} |
|
#else |
printf("No symbol information available.\n"); |
#endif |
196,55 → 197,54 |
|
/** Symtab completion |
* |
* @param input - Search string, completes to symbol name |
* @returns - 0 - nothing found, 1 - success, >1 print duplicates |
* @param input Search string, completes to symbol name |
* @param size Input buffer size |
* |
* @return 0 - nothing found, 1 - success, >1 print duplicates |
* |
*/ |
int symtab_compl(char *input) |
int symtab_compl(char *input, count_t size) |
{ |
#ifdef CONFIG_SYMTAB |
char output[MAX_SYMBOL_NAME + 1]; |
int startpos = 0; |
char *foundtxt; |
int found = 0; |
int i; |
char *name = input; |
|
/* Allow completion of pointers */ |
if (name[0] == '*' || name[0] == '&') |
const char *name = input; |
|
/* Allow completion of pointers */ |
if ((name[0] == '*') || (name[0] == '&')) |
name++; |
|
/* Do not print everything */ |
if (!strlen(name)) |
|
/* Do not print all symbols */ |
if (str_length(name) == 0) |
return 0; |
|
|
output[0] = '\0'; |
|
while ((foundtxt = symtab_search_one(name, &startpos))) { |
startpos++; |
if (!found) |
strncpy(output, foundtxt, strlen(foundtxt) + 1); |
else { |
for (i = 0; output[i] && foundtxt[i] && |
output[i] == foundtxt[i]; i++) |
; |
output[i] = '\0'; |
} |
count_t found = 0; |
count_t pos = 0; |
const char *hint; |
char output[MAX_SYMBOL_NAME]; |
|
output[0] = 0; |
|
while ((hint = symtab_search_one(name, &pos))) { |
if ((found == 0) || (str_length(output) > str_length(hint))) |
str_cpy(output, MAX_SYMBOL_NAME, hint); |
|
pos++; |
found++; |
} |
if (!found) |
return 0; |
|
if (found > 1 && !strlen(output)) { |
|
if ((found > 1) && (str_length(output) != 0)) { |
printf("\n"); |
startpos = 0; |
while ((foundtxt = symtab_search_one(name, &startpos))) { |
printf("%s\n", symbol_table[startpos].symbol_name); |
startpos++; |
pos = 0; |
while ((hint = symtab_search_one(name, &pos))) { |
printf("%s\n", symbol_table[pos].symbol_name); |
pos++; |
} |
} |
strncpy(input, output, MAX_SYMBOL_NAME); |
|
if (found > 0) |
str_cpy(input, size, output); |
|
return found; |
|
#else |
return 0; |
#endif |