/[gxemul]/trunk/src/symbol/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 /trunk/src/symbol/symbol.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 10183 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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.1 2007/06/20 14:25:14 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=%016"PRIx64" len=%016"PRIx64" 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