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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4ccdcf6 was e16e0d59, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Make optionality of symbol information less intrusive per Jakub's request. Also, improve symtab function names and update their semantics.

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[ab08b42]1/*
[df4ed85]2 * Copyright (c) 2005 Ondrej Palkovsky
[ab08b42]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
[06e1e95]29/** @addtogroup genericdebug
[b45c443]30 * @{
31 */
32
[cf26ba9]33/**
[b45c443]34 * @file
[cf26ba9]35 * @brief Kernel symbol resolver.
36 */
[ab08b42]37
38#include <symtab.h>
[5d494b3]39#include <byteorder.h>
[16da5f8e]40#include <string.h>
[6e716a59]41#include <print.h>
[8ed4014]42#include <arch/types.h>
43#include <typedefs.h>
[e16e0d59]44#include <errno.h>
[ab08b42]45
[e16e0d59]46/** Get name of symbol that seems most likely to correspond to address.
[ab08b42]47 *
[e16e0d59]48 * @param addr Address.
49 * @param name Place to store pointer to the symbol name.
[a783ca4]50 *
[e16e0d59]51 * @return Zero on success or negative error code, ENOENT if not found,
52 * ENOTSUP if symbol table not available.
[ab08b42]53 */
[e16e0d59]54int symtab_name_lookup(unative_t addr, char **name)
[ab08b42]55{
[e16e0d59]56#ifdef CONFIG_SYMTAB
[ab08b42]57 count_t i;
58
[5d494b3]59 for (i = 1; symbol_table[i].address_le; ++i) {
[7f1c620]60 if (addr < uint64_t_le2host(symbol_table[i].address_le))
[ab08b42]61 break;
62 }
[e16e0d59]63 if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) {
64 *name = symbol_table[i - 1].symbol_name;
65 return EOK;
66 }
67
68 *name = NULL;
69 return ENOENT;
70#else
71 *name = NULL;
72 return ENOTSUP;
73#endif
74}
75
76/** Lookup symbol by address and format for display.
77 *
78 * Returns name of closest corresponding symbol, "Not found" if none exists
79 * or "N/A" if no symbol information is available.
80 *
81 * @param addr Address.
82 * @param name Place to store pointer to the symbol name.
83 *
84 * @return Pointer to a human-readable string.
85 */
86char *symtab_fmt_name_lookup(unative_t addr)
87{
88 int rc;
89 char *name;
90
91 rc = symtab_name_lookup(addr, &name);
92 switch (rc) {
93 case EOK: return name;
94 case ENOENT: return "Not found";
95 default: return "N/A";
96 }
[ab08b42]97}
[6e716a59]98
[e16e0d59]99#ifdef CONFIG_SYMTAB
100
[cf26ba9]101/** Find symbols that match the parameter forward and print them.
[0c8e692]102 *
103 * @param name - search string
104 * @param startpos - starting position, changes to found position
105 * @return Pointer to the part of string that should be completed or NULL
106 */
107static char * symtab_search_one(const char *name, int *startpos)
108{
[6c441cf8]109 unsigned int namelen = strlen(name);
[0c8e692]110 char *curname;
[5d494b3]111 int i, j;
[0c8e692]112 int colonoffset = -1;
113
[5d494b3]114 for (i = 0; name[i]; i++)
[0c8e692]115 if (name[i] == ':') {
116 colonoffset = i;
117 break;
118 }
119
[5d494b3]120 for (i = *startpos; symbol_table[i].address_le; ++i) {
[0c8e692]121 /* Find a ':' in name */
122 curname = symbol_table[i].symbol_name;
[5d494b3]123 for (j = 0; curname[j] && curname[j] != ':'; j++)
[0c8e692]124 ;
125 if (!curname[j])
126 continue;
127 j -= colonoffset;
128 curname += j;
129 if (strlen(curname) < namelen)
130 continue;
131 if (strncmp(curname, name, namelen) == 0) {
132 *startpos = i;
[5d494b3]133 return curname + namelen;
[0c8e692]134 }
135 }
136 return NULL;
137}
138
[e16e0d59]139#endif
140
[6e716a59]141/** Return address that corresponds to the entry
142 *
[0c8e692]143 * Search symbol table, and if there is one match, return it
[6e716a59]144 *
[e16e0d59]145 * @param name Name of the symbol
146 * @param addr Place to store symbol address
147 *
148 * @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate
149 * symbol, ENOTSUP - no symbol information available.
[6e716a59]150 */
[e16e0d59]151int symtab_addr_lookup(const char *name, uintptr_t *addr)
[6e716a59]152{
[e16e0d59]153#ifdef CONFIG_SYMTAB
[6e716a59]154 count_t found = 0;
[0c8e692]155 char *hint;
156 int i;
[6e716a59]157
[0c8e692]158 i = 0;
[5d494b3]159 while ((hint = symtab_search_one(name, &i))) {
[0c8e692]160 if (!strlen(hint)) {
[e16e0d59]161 *addr = uint64_t_le2host(symbol_table[i].address_le);
[6e716a59]162 found++;
163 }
[0c8e692]164 i++;
[6e716a59]165 }
[0c8e692]166 if (found > 1)
[e16e0d59]167 return EOVERFLOW;
168 if (found < 1)
169 return ENOENT;
170 return EOK;
171#else
172 return ENOTSUP;
173#endif
[6e716a59]174}
175
[0c8e692]176/** Find symbols that match parameter and prints them */
[6e716a59]177void symtab_print_search(const char *name)
178{
[e16e0d59]179#ifdef CONFIG_SYMTAB
[6e716a59]180 int i;
[7f1c620]181 uintptr_t addr;
[6e716a59]182 char *realname;
183
[0c8e692]184
185 i = 0;
186 while (symtab_search_one(name, &i)) {
[7f1c620]187 addr = uint64_t_le2host(symbol_table[i].address_le);
[0c8e692]188 realname = symbol_table[i].symbol_name;
[8ed4014]189 printf("%p: %s\n", addr, realname);
[0c8e692]190 i++;
191 }
[e16e0d59]192#else
193 printf("No symbol information available.\n");
194#endif
[0c8e692]195}
196
197/** Symtab completion
198 *
[9179d0a]199 * @param input - Search string, completes to symbol name
[0c8e692]200 * @returns - 0 - nothing found, 1 - success, >1 print duplicates
201 */
[91ef0d95]202int symtab_compl(char *input)
[0c8e692]203{
[e16e0d59]204#ifdef CONFIG_SYMTAB
[5d494b3]205 char output[MAX_SYMBOL_NAME + 1];
[0c8e692]206 int startpos = 0;
207 char *foundtxt;
208 int found = 0;
209 int i;
[91ef0d95]210 char *name = input;
211
212 /* Allow completion of pointers */
213 if (name[0] == '*' || name[0] == '&')
214 name++;
[0c8e692]215
216 /* Do not print everything */
217 if (!strlen(name))
218 return 0;
[91ef0d95]219
[0c8e692]220
221 output[0] = '\0';
222
223 while ((foundtxt = symtab_search_one(name, &startpos))) {
224 startpos++;
225 if (!found)
[5d494b3]226 strncpy(output, foundtxt, strlen(foundtxt) + 1);
[0c8e692]227 else {
[5d494b3]228 for (i = 0; output[i] && foundtxt[i] &&
229 output[i] == foundtxt[i]; i++)
[0c8e692]230 ;
231 output[i] = '\0';
232 }
233 found++;
234 }
235 if (!found)
236 return 0;
237
[3550c393]238 if (found > 1 && !strlen(output)) {
[0c8e692]239 printf("\n");
240 startpos = 0;
241 while ((foundtxt = symtab_search_one(name, &startpos))) {
242 printf("%s\n", symbol_table[startpos].symbol_name);
243 startpos++;
[6e716a59]244 }
245 }
[91ef0d95]246 strncpy(input, output, MAX_SYMBOL_NAME);
[0c8e692]247 return found;
[e16e0d59]248#else
249 return 0;
250#endif
[6e716a59]251}
[b45c443]252
[06e1e95]253/** @}
[b45c443]254 */
Note: See TracBrowser for help on using the repository browser.