Ignore:
File:
1 edited

Legend:

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

    r40eab9f rbab75df6  
    3636 */
    3737
    38 #include <abi/elf.h>
     38#include <symtab.h>
    3939#include <byteorder.h>
     40#include <str.h>
     41#include <stdio.h>
     42#include <typedefs.h>
     43#include <errno.h>
    4044#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>
    46 #include <symtab.h>
    47 #include <typedefs.h>
    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)
     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 */
     56errno_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))
    7563                        break;
    7664        }
    7765
    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;
     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
    12081}
    12182
     
    13495const char *symtab_fmt_name_lookup(uintptr_t addr)
    13596{
    136         const char *name = symtab_name_lookup(addr, NULL, &kernel_sections);
    137         if (name == NULL)
    138                 name = "<unknown>";
    139         return name;
    140 }
     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 */
     120static 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
    141146
    142147/** Return address that corresponds to the entry.
     
    147152 * @param addr Place to store symbol address
    148153 *
    149  * @return Zero on success, ENOENT - not found
     154 * @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate
     155 *         symbol, ENOTSUP - no symbol information available.
    150156 *
    151157 */
    152158errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
    153159{
    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;
     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++;
    161169                }
    162         }
    163 
    164         return ENOENT;
     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
    165184}
    166185
     
    168187void symtab_print_search(const char *name)
    169188{
    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         }
     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
    187201}
    188202
    189203/** Symtab completion enum, see kernel/generic/include/kconsole.h */
    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 
     204const char *symtab_hints_enum(const char *input, const char **help,
     205    void **ctx)
     206{
     207#ifdef CONFIG_SYMTAB
    201208        size_t len = str_length(input);
    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);
     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;
    204224
    205225                if (str_lcmp(input, curname, len) == 0) {
    206                         *ctx = (void *) (i + 1);
     226                        (*entry)++;
     227                        if (help)
     228                                *help = NULL;
    207229                        return (curname + str_lsize(curname, len));
    208230                }
     
    210232
    211233        return NULL;
     234
     235#else
     236        return NULL;
     237#endif
    212238}
    213239
Note: See TracChangeset for help on using the changeset viewer.