source: mainline/kernel/generic/src/debug/symtab.c@ c89ae25

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c89ae25 was da13982, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 2 years ago

Read symbol table from ELF sections

Instead of the currently broken data generated using genmap.py,
read the ELF symbol table for stack traces and symbol names.
In addition to that, prepare ground for accessing DWARF debug
sections.

Because neither .symtab, nor .debug_* sections are
normally part of the program image, these have to be provided
externally. Instead of the previous way of relinking kernel
to bake in the symbol data, we now only link kernel once
and the extra debug data is loaded as part of the initrd image.

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/*
2 * Copyright (c) 2005 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_generic_debug
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Kernel symbol resolver.
36 */
37
38#include <symtab.h>
39#include <byteorder.h>
40#include <str.h>
41#include <stdio.h>
42#include <typedefs.h>
43#include <errno.h>
44#include <console/prompt.h>
45
46#include <abi/elf.h>
47#include <debug/sections.h>
48
49static inline size_t symtab_len()
50{
51 return symtab_size / sizeof(elf_symbol_t);
52}
53
54static inline const char *symtab_entry_name(int entry)
55{
56 size_t index = symtab[entry].st_name;
57
58 if (index >= strtab_size)
59 return NULL;
60
61 return strtab + index;
62}
63
64static inline size_t symtab_next(size_t i)
65{
66 for (; i < symtab_len(); i++) {
67 const char *name = symtab_entry_name(i);
68 int st_bind = elf_st_bind(symtab[i].st_info);
69 int st_type = elf_st_type(symtab[i].st_info);
70
71 if (st_bind == STB_LOCAL)
72 continue;
73
74 if (name == NULL || *name == '\0')
75 continue;
76
77 if (st_type == STT_FUNC || st_type == STT_OBJECT)
78 break;
79 }
80
81 return i;
82}
83
84const char *symtab_name_lookup(uintptr_t addr, uintptr_t *symbol_addr)
85{
86 if (symtab == NULL || strtab == NULL)
87 return NULL;
88
89 uintptr_t closest_symbol_addr = 0;
90 uintptr_t closest_symbol_name = 0;
91
92 for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
93 if (symtab[i].st_value > addr)
94 continue;
95
96 if (symtab[i].st_value + symtab[i].st_size > addr) {
97 closest_symbol_addr = symtab[i].st_value;
98 closest_symbol_name = symtab[i].st_name;
99 break;
100 }
101
102 if (symtab[i].st_value > closest_symbol_addr) {
103 closest_symbol_addr = symtab[i].st_value;
104 closest_symbol_name = symtab[i].st_name;
105 }
106 }
107
108 if (closest_symbol_addr == 0)
109 return NULL;
110
111 if (symbol_addr)
112 *symbol_addr = closest_symbol_addr;
113
114 if (closest_symbol_name >= strtab_size)
115 return NULL;
116
117 return strtab + closest_symbol_name;
118}
119
120/** Lookup symbol by address and format for display.
121 *
122 * Returns name of closest corresponding symbol,
123 * "unknown" if none exists and "N/A" if no symbol
124 * information is available.
125 *
126 * @param addr Address.
127 * @param name Place to store pointer to the symbol name.
128 *
129 * @return Pointer to a human-readable string.
130 *
131 */
132const char *symtab_fmt_name_lookup(uintptr_t addr)
133{
134 const char *name = symtab_name_lookup(addr, NULL);
135 if (name == NULL)
136 name = "<unknown>";
137 return name;
138}
139
140/** Return address that corresponds to the entry.
141 *
142 * Search symbol table, and if there is one match, return it
143 *
144 * @param name Name of the symbol
145 * @param addr Place to store symbol address
146 *
147 * @return Zero on success, ENOENT - not found
148 *
149 */
150errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
151{
152 for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
153 if (str_cmp(name, symtab_entry_name(i)) == 0) {
154 *addr = symtab[i].st_value;
155 return EOK;
156 }
157 }
158
159 return ENOENT;
160}
161
162/** Find symbols that match parameter and print them */
163void symtab_print_search(const char *name)
164{
165 if (symtab == NULL || strtab == NULL) {
166 printf("No symbol information available.\n");
167 return;
168 }
169
170 size_t namelen = str_length(name);
171
172 for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
173 const char *n = symtab_entry_name(i);
174
175 if (str_lcmp(name, n, namelen) == 0) {
176 printf("%p: %s\n", (void *) symtab[i].st_value, n);
177 }
178 }
179}
180
181/** Symtab completion enum, see kernel/generic/include/kconsole.h */
182const char *symtab_hints_enum(const char *input, const char **help, void **ctx)
183{
184 if (symtab == NULL || strtab == NULL)
185 return NULL;
186
187 if (help)
188 *help = NULL;
189
190 size_t len = str_length(input);
191 for (size_t i = symtab_next((size_t) *ctx); i < symtab_len(); i = symtab_next(i + 1)) {
192 const char *curname = symtab_entry_name(i);
193
194 if (str_lcmp(input, curname, len) == 0) {
195 *ctx = (void *) (i + 1);
196 return (curname + str_lsize(curname, len));
197 }
198 }
199
200 return NULL;
201}
202
203/** @}
204 */
Note: See TracBrowser for help on using the repository browser.