32,171 → 32,222 |
|
/** |
* @file |
* @brief Kernel symbol resolver. |
* @brief Kernel symbol resolver. |
*/ |
|
#include <symtab.h> |
#include <byteorder.h> |
#include <func.h> |
#include <string.h> |
#include <print.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <errno.h> |
|
/** Return entry that seems most likely to correspond to argument. |
/** Get name of a symbol that seems most likely to correspond to address. |
* |
* Return entry that seems most likely to correspond |
* to address passed in the argument. |
* |
* @param addr Address. |
* @param name Place to store pointer to the symbol name. |
* |
* @return Pointer to respective symbol string on success, NULL otherwise. |
* @return Zero on success or negative error code, ENOENT if not found, |
* ENOTSUP if symbol table not available. |
* |
*/ |
char * get_symtab_entry(unative_t addr) |
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)) |
return symbol_table[i - 1].symbol_name; |
return NULL; |
|
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; |
#endif |
} |
|
/** Find symbols that match the parameter forward and print them. |
/** Lookup symbol by address and format for display. |
* |
* @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 |
* 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. |
* |
* @return Pointer to a human-readable string. |
* |
*/ |
static char * symtab_search_one(const char *name, int *startpos) |
char *symtab_fmt_name_lookup(unative_t addr) |
{ |
unsigned int namelen = strlen(name); |
char *curname; |
int i, j; |
int colonoffset = -1; |
char *name; |
int rc = symtab_name_lookup(addr, &name); |
|
switch (rc) { |
case EOK: |
return name; |
case ENOENT: |
return "Not found"; |
default: |
return "N/A"; |
} |
} |
|
for (i = 0; name[i]; i++) |
if (name[i] == ':') { |
colonoffset = i; |
break; |
} |
#ifdef CONFIG_SYMTAB |
|
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]) |
/** 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. |
* |
*/ |
static const char *symtab_search_one(const char *name, count_t *startpos) |
{ |
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; |
} |
|
/** Return address that corresponds to the entry |
#endif |
|
/** Return address that corresponds to the entry. |
* |
* Search symbol table, and if there is one match, return it |
* |
* @param name Name of the symbol |
* @return 0 - Not found, -1 - Duplicate symbol, other - address of symbol |
* @param addr Place to store symbol address |
* |
* @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate |
* symbol, ENOTSUP - no symbol information available. |
* |
*/ |
uintptr_t get_symbol_addr(const char *name) |
int symtab_addr_lookup(const char *name, uintptr_t *addr) |
{ |
#ifdef CONFIG_SYMTAB |
count_t found = 0; |
uintptr_t addr = NULL; |
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 ((uintptr_t) -1); |
return addr; |
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) |
{ |
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; |
#ifdef CONFIG_SYMTAB |
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 |
} |
|
/** 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) |
{ |
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] == '&') |
#ifdef CONFIG_SYMTAB |
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 |
} |
|
/** @} |