Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/debug/symtab.c

    rbab75df6 r40eab9f  
    3636 */
    3737
     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>
    3846#include <symtab.h>
    39 #include <byteorder.h>
    40 #include <str.h>
    41 #include <stdio.h>
    4247#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
     49static 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
     59static 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)
    6375                        break;
    6476        }
    6577
    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
     81const 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;
    81120}
    82121
     
    95134const char *symtab_fmt_name_lookup(uintptr_t addr)
    96135{
    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}
    146141
    147142/** Return address that corresponds to the entry.
     
    152147 * @param addr Place to store symbol address
    153148 *
    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
    156150 *
    157151 */
    158152errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
    159153{
    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;
    184165}
    185166
     
    187168void symtab_print_search(const char *name)
    188169{
    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        }
    201187}
    202188
    203189/** 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
     190const 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
    208201        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);
    224204
    225205                if (str_lcmp(input, curname, len) == 0) {
    226                         (*entry)++;
    227                         if (help)
    228                                 *help = NULL;
     206                        *ctx = (void *) (i + 1);
    229207                        return (curname + str_lsize(curname, len));
    230208                }
     
    232210
    233211        return NULL;
    234 
    235 #else
    236         return NULL;
    237 #endif
    238212}
    239213
Note: See TracChangeset for help on using the changeset viewer.