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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 10523 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 /*
2 * Copyright (C) 2003-2006 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.36 2006/07/07 19:38:55 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 int stepsize, ofs;
117
118 if (sc->n_symbols == 0)
119 return NULL;
120
121 if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
122 addr |= 0xffffffff00000000ULL;
123
124 symbol_buf[0] = symbol_buf[SYMBOLBUF_MAX] = '\0';
125 if (offset != NULL)
126 *offset = 0;
127
128 if (!sc->sorted_array) {
129 /* Slow, linear O(n) search: */
130 s = sc->first_symbol;
131 while (s != NULL) {
132 /* Found a match? */
133 if (addr >= s->addr && addr < s->addr + s->len) {
134 if (addr == s->addr)
135 snprintf(symbol_buf, SYMBOLBUF_MAX,
136 "%s", s->name);
137 else
138 snprintf(symbol_buf, SYMBOLBUF_MAX,
139 "%s+0x%lx", s->name, (long)
140 (addr - s->addr));
141 if (offset != NULL)
142 *offset = addr - s->addr;
143 if (n_argsp != NULL)
144 *n_argsp = s->n_args;
145 return symbol_buf;
146 }
147 s = s->next;
148 }
149 } else {
150 /* Faster, O(log n) search: */
151 stepsize = sc->n_symbols / 2;
152 ofs = stepsize;
153 while (stepsize > 0 || (stepsize == 0 && ofs == 0)) {
154 s = sc->first_symbol + ofs;
155
156 /* Found a match? */
157 if (addr >= s->addr && addr < s->addr + s->len) {
158 if (addr == s->addr)
159 snprintf(symbol_buf, SYMBOLBUF_MAX,
160 "%s", s->name);
161 else
162 snprintf(symbol_buf, SYMBOLBUF_MAX,
163 "%s+0x%lx", s->name, (long)
164 (addr - s->addr));
165 if (offset != NULL)
166 *offset = addr - s->addr;
167 if (n_argsp != NULL)
168 *n_argsp = s->n_args;
169 return symbol_buf;
170 }
171
172 if (ofs == 0)
173 break;
174
175 stepsize >>= 1;
176
177 /* Special case for offset 0 (end of search in
178 the Left direction */
179 if (stepsize == 0)
180 ofs = 0;
181 else {
182 if (addr < s->addr)
183 ofs -= stepsize;
184 else
185 ofs += stepsize;
186 }
187 }
188 }
189
190 /* Not found? Then return NULL. */
191 return NULL;
192 }
193
194
195 /*
196 * get_symbol_name():
197 *
198 * See get_symbol_name_and_n_args().
199 */
200 char *get_symbol_name(struct symbol_context *sc, uint64_t addr, uint64_t *offs)
201 {
202 return get_symbol_name_and_n_args(sc, addr, offs, NULL);
203 }
204
205
206 /*
207 * add_symbol_name():
208 *
209 * Add a symbol to the symbol list.
210 */
211 void add_symbol_name(struct symbol_context *sc,
212 uint64_t addr, uint64_t len, char *name, int type, int n_args)
213 {
214 struct symbol *s;
215
216 if (sc->sorted_array) {
217 fprintf(stderr, "add_symbol_name(): Internal error: the "
218 "symbol array is already sorted\n");
219 exit(1);
220 }
221
222 if (name == NULL) {
223 fprintf(stderr, "add_symbol_name(): name = NULL\n");
224 exit(1);
225 }
226
227 if (addr == 0 && strcmp(name, "_DYNAMIC_LINK") == 0)
228 return;
229
230 if (name[0] == '\0')
231 return;
232
233 /* TODO: Maybe this should be optional? */
234 if (name[0] == '.' || name[0] == '$')
235 return;
236
237 /* Quick test-hack: */
238 if (n_args < 0) {
239 if (strcmp(name, "strlen") == 0)
240 n_args = 1;
241 if (strcmp(name, "strcmp") == 0)
242 n_args = 2;
243 if (strcmp(name, "strcpy") == 0)
244 n_args = 2;
245 if (strcmp(name, "strncpy") == 0)
246 n_args = 3;
247 if (strcmp(name, "strlcpy") == 0)
248 n_args = 3;
249 if (strcmp(name, "strlcat") == 0)
250 n_args = 3;
251 if (strcmp(name, "strncmp") == 0)
252 n_args = 3;
253 if (strcmp(name, "memset") == 0)
254 n_args = 3;
255 if (strcmp(name, "memcpy") == 0)
256 n_args = 3;
257 if (strcmp(name, "bzero") == 0)
258 n_args = 2;
259 if (strcmp(name, "bcopy") == 0)
260 n_args = 3;
261 }
262
263 if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
264 addr |= 0xffffffff00000000ULL;
265
266 s = malloc(sizeof(struct symbol));
267 if (s == NULL) {
268 fprintf(stderr, "out of memory\n");
269 exit(1);
270 }
271
272 memset(s, 0, sizeof(struct symbol));
273
274 s->name = symbol_demangle_cplusplus(name);
275
276 if (s->name == NULL) {
277 s->name = strdup(name);
278 if (s->name == NULL) {
279 fprintf(stderr, "out of memory\n");
280 exit(1);
281 }
282 }
283
284 s->addr = addr;
285 s->len = len;
286 s->type = type;
287 s->n_args = n_args;
288
289 sc->n_symbols ++;
290
291 /* Add first in list: */
292 s->next = sc->first_symbol;
293 sc->first_symbol = s;
294 }
295
296
297 /*
298 * symbol_readfile():
299 *
300 * Read 'nm -S' style symbols from a file.
301 *
302 * TODO: This function is an ugly hack, and should be replaced
303 * with something that reads symbols directly from the executable
304 * images.
305 */
306 void symbol_readfile(struct symbol_context *sc, char *fname)
307 {
308 FILE *f;
309 char b1[80]; uint64_t addr;
310 char b2[80]; uint64_t len;
311 char b3[80]; int type;
312 char b4[80];
313 int cur_n_symbols = sc->n_symbols;
314
315 f = fopen(fname, "r");
316 if (f == NULL) {
317 perror(fname);
318 exit(1);
319 }
320
321 while (!feof(f)) {
322 memset(b1, 0, sizeof(b1));
323 memset(b2, 0, sizeof(b2));
324 memset(b3, 0, sizeof(b3));
325 memset(b4, 0, sizeof(b4));
326 fscanf(f, "%s %s\n", b1,b2);
327 if (strlen(b2) < 2 && !(b2[0]>='0' && b2[0]<='9')) {
328 strlcpy(b3, b2, sizeof(b3));
329 strlcpy(b2, "0", sizeof(b2));
330 fscanf(f, "%s\n", b4);
331 } else {
332 fscanf(f, "%s %s\n", b3,b4);
333 }
334
335 /* printf("b1='%s' b2='%s' b3='%s' b4='%s'\n",
336 b1,b2,b3,b4); */
337 addr = strtoull(b1, NULL, 16);
338 len = strtoull(b2, NULL, 16);
339 type = b3[0];
340 /* printf("addr=%016llx len=%016llx type=%i\n",
341 addr, len, type); */
342
343 if (type == 't' || type == 'r' || type == 'g')
344 continue;
345
346 add_symbol_name(sc, addr, len, b4, type, -1);
347 }
348
349 fclose(f);
350
351 debug("%i symbols\n", sc->n_symbols - cur_n_symbols);
352 }
353
354
355 /*
356 * sym_addr_compare():
357 *
358 * Helper function for sorting symbols according to their address.
359 */
360 int sym_addr_compare(const void *a, const void *b)
361 {
362 struct symbol *p1 = (struct symbol *) a;
363 struct symbol *p2 = (struct symbol *) b;
364
365 if (p1->addr < p2->addr)
366 return -1;
367 if (p1->addr > p2->addr)
368 return 1;
369
370 return 0;
371 }
372
373
374 /*
375 * symbol_recalc_sizes():
376 *
377 * Recalculate sizes of symbols that have size = 0, by creating an array
378 * containing all symbols, qsort()-ing that array according to address, and
379 * recalculating the size fields if necessary.
380 */
381 void symbol_recalc_sizes(struct symbol_context *sc)
382 {
383 struct symbol *tmp_array;
384 struct symbol *last_ptr;
385 struct symbol *tmp_ptr;
386 int i;
387
388 tmp_array = malloc(sizeof (struct symbol) * sc->n_symbols);
389 if (tmp_array == NULL) {
390 fprintf(stderr, "out of memory\n");
391 exit(1);
392 }
393
394 /* Copy first_symbol --> tmp_array, and remove the old
395 first_symbol at the same time: */
396 tmp_ptr = sc->first_symbol;
397 i = 0;
398 while (tmp_ptr != NULL) {
399 tmp_array[i] = *tmp_ptr;
400 last_ptr = tmp_ptr;
401 tmp_ptr = tmp_ptr->next;
402 free(last_ptr);
403 i++;
404 }
405
406 qsort(tmp_array, sc->n_symbols, sizeof(struct symbol),
407 sym_addr_compare);
408 sc->sorted_array = 1;
409
410 /* Recreate the first_symbol chain: */
411 sc->first_symbol = NULL;
412 for (i=0; i<sc->n_symbols; i++) {
413 /* Recalculate size, if 0: */
414 if (tmp_array[i].len == 0) {
415 uint64_t len;
416 if (i != sc->n_symbols-1)
417 len = tmp_array[i+1].addr
418 - tmp_array[i].addr;
419 else
420 len = 1;
421 tmp_array[i].len = len;
422 }
423
424 tmp_array[i].next = &tmp_array[i+1];
425 }
426
427 sc->first_symbol = tmp_array;
428 }
429
430
431 /*
432 * symbol_init():
433 *
434 * Initialize the symbol hashtables.
435 */
436 void symbol_init(struct symbol_context *sc)
437 {
438 sc->first_symbol = NULL;
439 sc->sorted_array = 0;
440 sc->n_symbols = 0;
441 }
442

  ViewVC Help
Powered by ViewVC 1.1.26