HelenOS sources
This source file includes following definitions.
- symtab_entry_name
- symtab_next
- symtab_name_lookup
- symtab_fmt_name_lookup
- symtab_addr_lookup
- symtab_print_search
- symtab_hints_enum
#include <abi/elf.h>
#include <byteorder.h>
#include <console/prompt.h>
#include <debug/sections.h>
#include <errno.h>
#include <proc/task.h>
#include <stdio.h>
#include <str.h>
#include <symtab.h>
#include <typedefs.h>
static inline const char *symtab_entry_name(debug_sections_t *scs, int entry)
{
size_t index = scs->symtab[entry].st_name;
if (index >= scs->strtab_size)
return NULL;
return scs->strtab + index;
}
static inline size_t symtab_next(debug_sections_t *scs, size_t i)
{
size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
for (; i < symtab_len; i++) {
const char *name = symtab_entry_name(scs, i);
int st_bind = elf_st_bind(scs->symtab[i].st_info);
int st_type = elf_st_type(scs->symtab[i].st_info);
if (st_bind == STB_LOCAL)
continue;
if (name == NULL || *name == '\0')
continue;
if (st_type == STT_FUNC || st_type == STT_OBJECT)
break;
}
return i;
}
const char *symtab_name_lookup(uintptr_t addr, uintptr_t *symbol_addr, debug_sections_t *scs)
{
const elf_symbol_t *symtab = scs->symtab;
size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
const char *strtab = scs->strtab;
size_t strtab_size = scs->strtab_size;
if (symtab == NULL || strtab == NULL)
return NULL;
uintptr_t closest_symbol_addr = 0;
uintptr_t closest_symbol_name = 0;
for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
if (symtab[i].st_value > addr)
continue;
if (symtab[i].st_value + symtab[i].st_size > addr) {
closest_symbol_addr = symtab[i].st_value;
closest_symbol_name = symtab[i].st_name;
break;
}
if (symtab[i].st_value > closest_symbol_addr) {
closest_symbol_addr = symtab[i].st_value;
closest_symbol_name = symtab[i].st_name;
}
}
if (closest_symbol_addr == 0)
return NULL;
if (symbol_addr)
*symbol_addr = closest_symbol_addr;
if (closest_symbol_name >= strtab_size)
return NULL;
return strtab + closest_symbol_name;
}
const char *symtab_fmt_name_lookup(uintptr_t addr)
{
const char *name = symtab_name_lookup(addr, NULL, &kernel_sections);
if (name == NULL)
name = "<unknown>";
return name;
}
errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
{
debug_sections_t *scs = &kernel_sections;
size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
if (str_cmp(name, symtab_entry_name(scs, i)) == 0) {
*addr = scs->symtab[i].st_value;
return EOK;
}
}
return ENOENT;
}
void symtab_print_search(const char *name)
{
debug_sections_t *scs = &kernel_sections;
size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
if (scs->symtab == NULL || scs->strtab == NULL) {
printf("No symbol information available.\n");
return;
}
size_t namelen = str_length(name);
for (size_t i = symtab_next(scs, 0); i < symtab_len; i = symtab_next(scs, i + 1)) {
const char *n = symtab_entry_name(scs, i);
if (str_lcmp(name, n, namelen) == 0) {
printf("%p: %s\n", (void *) scs->symtab[i].st_value, n);
}
}
}
const char *symtab_hints_enum(const char *input, const char **help, void **ctx)
{
debug_sections_t *scs = &kernel_sections;
size_t symtab_len = scs->symtab_size / sizeof(elf_symbol_t);
if (scs->symtab == NULL || scs->strtab == NULL)
return NULL;
if (help)
*help = NULL;
size_t len = str_length(input);
for (size_t i = symtab_next(scs, (size_t) *ctx); i < symtab_len; i = symtab_next(scs, i + 1)) {
const char *curname = symtab_entry_name(scs, i);
if (str_lcmp(input, curname, len) == 0) {
*ctx = (void *) (i + 1);
return (curname + str_lsize(curname, len));
}
}
return NULL;
}
HelenOS homepage, sources at GitHub