/[gxemul]/upstream/0.4.6/src/symbol.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.6/src/symbol.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 10174 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: symbol.c,v 1.39 2007/06/15 17:02:38 debug Exp $
29 *
30 * Address to symbol translation routines.
31 *
32 * This module is (probably) independent from the rest of the emulator.
33 * symbol_init() must be called before any other function in this file is used.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "symbol.h"
41
42
43 #define SYMBOLBUF_MAX 100
44
45
46 /*
47 * symbol_nsymbols():
48 *
49 * Return n_symbols.
50 */
51 int symbol_nsymbols(struct symbol_context *sc)
52 {
53 return sc->n_symbols;
54 }
55
56
57 /*
58 * get_symbol_addr():
59 *
60 * Find a symbol by name. If addr is non-NULL, *addr is set to the symbol's
61 * address. Return value is 1 if the symbol is found, 0 otherwise.
62 *
63 * NOTE: This is O(n).
64 */
65 int get_symbol_addr(struct symbol_context *sc, char *symbol, uint64_t *addr)
66 {
67 struct symbol *s;
68
69 if (sc->sorted_array) {
70 int i;
71 for (i=0; i<sc->n_symbols; i++)
72 if (strcmp(symbol, sc->first_symbol[i].name) == 0) {
73 if (addr != NULL)
74 *addr = sc->first_symbol[i].addr;
75 return 1;
76 }
77 } else {
78 s = sc->first_symbol;
79 while (s != NULL) {
80 if (strcmp(symbol, s->name) == 0) {
81 if (addr != NULL)
82 *addr = s->addr;
83 return 1;
84 }
85 s = s->next;
86 }
87 }
88
89 return 0;
90 }
91
92
93 /*
94 * get_symbol_name_and_n_args():
95 *
96 * Translate an address into a symbol name. The return value is a pointer
97 * to a static char array, containing the symbol name. (In other words,
98 * this function is not reentrant. This removes the need for memory allocation
99 * at the caller's side.)
100 *
101 * If offset is not a NULL pointer, *offset is set to the offset within
102 * the symbol. For example, if there is a symbol at address 0x1000 with
103 * length 0x100, and a caller wants to know the symbol name of address
104 * 0x1008, the symbol's name will be found in the static char array, and
105 * *offset will be set to 0x8.
106 *
107 * If n_argsp is non-NULL, *n_argsp is set to the symbol's n_args value.
108 *
109 * If no symbol was found, NULL is returned instead.
110 */
111 static char symbol_buf[SYMBOLBUF_MAX+1];
112 char *get_symbol_name_and_n_args(struct symbol_context *sc, uint64_t addr,
113 uint64_t *offset, int *n_argsp)
114 {
115 struct symbol *s;
116
117 if (sc->n_symbols == 0)
118 return NULL;
119
120 if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
121 addr |= 0xffffffff00000000ULL;
122
123 symbol_buf[0] = symbol_buf[SYMBOLBUF_MAX] = '\0';
124 if (offset != NULL)
125 *offset = 0;
126
127 if (!sc->sorted_array) {
128 /* Slow, linear O(n) search: */
129 s = sc->first_symbol;
130 while (s != NULL) {
131 /* Found a match? */
132 if (addr >= s->addr && addr < s->addr + s->len) {
133 if (addr == s->addr)
134 snprintf(symbol_buf, SYMBOLBUF_MAX,
135 "%s", s->name);
136 else
137 snprintf(symbol_buf, SYMBOLBUF_MAX,
138 "%s+0x%"PRIx64, s->name, (uint64_t)
139 (addr - s->addr));
140 if (offset != NULL)
141 *offset = addr - s->addr;
142 if (n_argsp != NULL)
143 *n_argsp = s->n_args;
144 return symbol_buf;
145 }
146 s = s->next;
147 }
148 } else {
149 /* Faster, O(log n) search: */
150 int lowest = 0, highest = sc->n_symbols - 1;
151 while (lowest <= highest) {
152 int ofs = (lowest + highest) / 2;
153 s = sc->first_symbol + ofs;
154
155 /* Found a match? */
156 if (addr >= s->addr && addr < s->addr + s->len) {
157 if (addr == s->addr)
158 snprintf(symbol_buf, SYMBOLBUF_MAX,
159 "%s", s->name);
160 else
161 snprintf(symbol_buf, SYMBOLBUF_MAX,
162 "%s+0x%"PRIx64, s->name, (uint64_t)
163 (addr - s->addr));
164
165 if (offset != NULL)
166 *offset = addr - s->addr;
167 if (n_argsp != NULL)
168 *n_argsp = s->n_args;
169
170 return symbol_buf;
171 }
172
173 if (addr < s->addr)
174 highest = ofs - 1;
175 else
176 lowest = ofs + 1;
177 }
178 }
179
180 /* Not found? Then return NULL. */
181 return NULL;
182 }
183
184
185 /*
186 * get_symbol_name():
187 *
188 * See get_symbol_name_and_n_args().
189 */
190 char *get_symbol_name(struct symbol_context *sc, uint64_t addr, uint64_t *offs)
191 {
192 return get_symbol_name_and_n_args(sc, addr, offs, NULL);
193 }
194
195
196 /*
197 * add_symbol_name():
198 *
199 * Add a symbol to the symbol list.
200 */
201 void add_symbol_name(struct symbol_context *sc,
202 uint64_t addr, uint64_t len, char *name, int type, int n_args)
203 {
204 struct symbol *s;
205
206 if (sc->sorted_array) {
207 fprintf(stderr, "add_symbol_name(): Internal error: the "
208 "symbol array is already sorted\n");
209 exit(1);
210 }
211
212 if (name == NULL) {
213 fprintf(stderr, "add_symbol_name(): name = NULL\n");
214 exit(1);
215 }
216
217 if (addr == 0 && strcmp(name, "_DYNAMIC_LINK") == 0)
218 return;
219
220 if (name[0] == '\0')
221 return;
222
223 /* TODO: Maybe this should be optional? */
224 if (name[0] == '.' || name[0] == '$')
225 return;
226
227 /* Quick test-hack: */
228 if (n_args < 0) {
229 if (strcmp(name, "strlen") == 0)
230 n_args = 1;
231 if (strcmp(name, "strcmp") == 0)
232 n_args = 2;
233 if (strcmp(name, "strcpy") == 0)
234 n_args = 2;
235 if (strcmp(name, "strncpy") == 0)
236 n_args = 3;
237 if (strcmp(name, "strlcpy") == 0)
238 n_args = 3;
239 if (strcmp(name, "strlcat") == 0)
240 n_args = 3;
241 if (strcmp(name, "strncmp") == 0)
242 n_args = 3;
243 if (strcmp(name, "memset") == 0)
244 n_args = 3;
245 if (strcmp(name, "memcpy") == 0)
246 n_args = 3;
247 if (strcmp(name, "bzero") == 0)
248 n_args = 2;
249 if (strcmp(name, "bcopy") == 0)
250 n_args = 3;
251 }
252
253 if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
254 addr |= 0xffffffff00000000ULL;
255
256 CHECK_ALLOCATION(s = malloc(sizeof(struct symbol)));
257 memset(s, 0, sizeof(struct symbol));
258
259 s->name = symbol_demangle_cplusplus(name);
260
261 if (s->name == NULL)
262 CHECK_ALLOCATION(s->name = strdup(name));
263
264 s->addr = addr;
265 s->len = len;
266 s->type = type;
267 s->n_args = n_args;
268
269 sc->n_symbols ++;
270
271 /* Add first in list: */
272 s->next = sc->first_symbol;
273 sc->first_symbol = s;
274 }
275
276
277 /*
278 * symbol_readfile():
279 *
280 * Read 'nm -S' style symbols from a file.
281 *
282 * TODO: This function is an ugly hack, and should be replaced
283 * with something that reads symbols directly from the executable
284 * images.
285 */
286 void symbol_readfile(struct symbol_context *sc, char *fname)
287 {
288 FILE *f;
289 char b1[80]; uint64_t addr;
290 char b2[80]; uint64_t len;
291 char b3[80]; int type;
292 char b4[80];
293 int cur_n_symbols = sc->n_symbols;
294
295 f = fopen(fname, "r");
296 if (f == NULL) {
297 perror(fname);
298 exit(1);
299 }
300
301 while (!feof(f)) {
302 memset(b1, 0, sizeof(b1));
303 memset(b2, 0, sizeof(b2));
304 memset(b3, 0, sizeof(b3));
305 memset(b4, 0, sizeof(b4));
306 fscanf(f, "%s %s\n", b1,b2);
307 if (strlen(b2) < 2 && !(b2[0]>='0' && b2[0]<='9')) {
308 strlcpy(b3, b2, sizeof(b3));
309 strlcpy(b2, "0", sizeof(b2));
310 fscanf(f, "%s\n", b4);
311 } else {
312 fscanf(f, "%s %s\n", b3,b4);
313 }
314
315 /* printf("b1='%s' b2='%s' b3='%s' b4='%s'\n",
316 b1,b2,b3,b4); */
317 addr = strtoull(b1, NULL, 16);
318 len = strtoull(b2, NULL, 16);
319 type = b3[0];
320 /* printf("addr=%016llx len=%016llx type=%i\n",
321 addr, len, type); */
322
323 if (type == 't' || type == 'r' || type == 'g')
324 continue;
325
326 add_symbol_name(sc, addr, len, b4, type, -1);
327 }
328
329 fclose(f);
330
331 debug("%i symbols\n", sc->n_symbols - cur_n_symbols);
332 }
333
334
335 /*
336 * sym_addr_compare():
337 *
338 * Helper function for sorting symbols according to their address.
339 */
340 int sym_addr_compare(const void *a, const void *b)
341 {
342 struct symbol *p1 = (struct symbol *) a;
343 struct symbol *p2 = (struct symbol *) b;
344
345 if (p1->addr < p2->addr)
346 return -1;
347 if (p1->addr > p2->addr)
348 return 1;
349
350 return 0;
351 }
352
353
354 /*
355 * symbol_recalc_sizes():
356 *
357 * Recalculate sizes of symbols that have size = 0, by creating an array
358 * containing all symbols, qsort()-ing that array according to address, and
359 * recalculating the size fields if necessary.
360 */
361 void symbol_recalc_sizes(struct symbol_context *sc)
362 {
363 struct symbol *tmp_array;
364 struct symbol *last_ptr;
365 struct symbol *tmp_ptr;
366 int i;
367
368 CHECK_ALLOCATION(tmp_array = malloc(sizeof (struct symbol) *
369 sc->n_symbols));
370
371 /* Copy first_symbol --> tmp_array, and remove the old
372 first_symbol at the same time: */
373 tmp_ptr = sc->first_symbol;
374 i = 0;
375 while (tmp_ptr != NULL) {
376 tmp_array[i] = *tmp_ptr;
377 last_ptr = tmp_ptr;
378 tmp_ptr = tmp_ptr->next;
379 free(last_ptr);
380 i++;
381 }
382
383 qsort(tmp_array, sc->n_symbols, sizeof(struct symbol),
384 sym_addr_compare);
385 sc->sorted_array = 1;
386
387 /* Recreate the first_symbol chain: */
388 sc->first_symbol = NULL;
389 for (i=0; i<sc->n_symbols; i++) {
390 /* Recalculate size, if 0: */
391 if (tmp_array[i].len == 0) {
392 uint64_t len;
393 if (i != sc->n_symbols-1)
394 len = tmp_array[i+1].addr
395 - tmp_array[i].addr;
396 else
397 len = 1;
398
399 tmp_array[i].len = len;
400 }
401
402 tmp_array[i].next = &tmp_array[i+1];
403 }
404
405 sc->first_symbol = tmp_array;
406 }
407
408
409 /*
410 * symbol_init():
411 *
412 * Initialize the symbol hashtables.
413 */
414 void symbol_init(struct symbol_context *sc)
415 {
416 sc->first_symbol = NULL;
417 sc->sorted_array = 0;
418 sc->n_symbols = 0;
419 }
420

  ViewVC Help
Powered by ViewVC 1.1.26