symbol.cc Source File

Back to the index.

symbol.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2009 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  * Address to symbol translation routines.
29  *
30  * This module is (probably) independent from the rest of the emulator.
31  * symbol_init() must be called before any other function in this file is used.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "symbol.h"
39 
40 
41 #define SYMBOLBUF_MAX 100
42 
43 
44 /*
45  * symbol_nsymbols():
46  *
47  * Return n_symbols.
48  */
50 {
51  return sc->n_symbols;
52 }
53 
54 
55 /*
56  * get_symbol_addr():
57  *
58  * Find a symbol by name. If addr is non-NULL, *addr is set to the symbol's
59  * address. Return value is 1 if the symbol is found, 0 otherwise.
60  *
61  * NOTE: This is O(n).
62  */
63 int get_symbol_addr(struct symbol_context *sc, const char *symbol, uint64_t *addr)
64 {
65  struct symbol *s;
66 
67  if (sc->sorted_array) {
68  int i;
69  for (i=0; i<sc->n_symbols; i++)
70  if (strcmp(symbol, sc->first_symbol[i].name) == 0) {
71  if (addr != NULL)
72  *addr = sc->first_symbol[i].addr;
73  return 1;
74  }
75  } else {
76  s = sc->first_symbol;
77  while (s != NULL) {
78  if (strcmp(symbol, s->name) == 0) {
79  if (addr != NULL)
80  *addr = s->addr;
81  return 1;
82  }
83  s = s->next;
84  }
85  }
86 
87  return 0;
88 }
89 
90 
91 /*
92  * get_symbol_name_and_n_args():
93  *
94  * Translate an address into a symbol name. The return value is a pointer
95  * to a static char array, containing the symbol name. (In other words,
96  * this function is not reentrant. This removes the need for memory allocation
97  * at the caller's side.)
98  *
99  * If offset is not a NULL pointer, *offset is set to the offset within
100  * the symbol. For example, if there is a symbol at address 0x1000 with
101  * length 0x100, and a caller wants to know the symbol name of address
102  * 0x1008, the symbol's name will be found in the static char array, and
103  * *offset will be set to 0x8.
104  *
105  * If n_argsp is non-NULL, *n_argsp is set to the symbol's n_args value.
106  *
107  * If no symbol was found, NULL is returned instead.
108  */
109 static char symbol_buf[SYMBOLBUF_MAX+1];
110 char *get_symbol_name_and_n_args(struct symbol_context *sc, uint64_t addr,
111  uint64_t *offset, int *n_argsp)
112 {
113  struct symbol *s;
114 
115  if (sc->n_symbols == 0)
116  return NULL;
117 
118  if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
119  addr |= 0xffffffff00000000ULL;
120 
121  symbol_buf[0] = symbol_buf[SYMBOLBUF_MAX] = '\0';
122  if (offset != NULL)
123  *offset = 0;
124 
125  if (!sc->sorted_array) {
126  /* Slow, linear O(n) search: */
127  s = sc->first_symbol;
128  while (s != NULL) {
129  /* Found a match? */
130  if (addr >= s->addr && addr < s->addr + s->len) {
131  if (addr == s->addr)
132  snprintf(symbol_buf, SYMBOLBUF_MAX,
133  "%s", s->name);
134  else
135  snprintf(symbol_buf, SYMBOLBUF_MAX,
136  "%s+0x%" PRIx64, s->name, (uint64_t)
137  (addr - s->addr));
138  if (offset != NULL)
139  *offset = addr - s->addr;
140  if (n_argsp != NULL)
141  *n_argsp = s->n_args;
142  return symbol_buf;
143  }
144  s = s->next;
145  }
146  } else {
147  /* Faster, O(log n) search: */
148  int lowest = 0, highest = sc->n_symbols - 1;
149  while (lowest <= highest) {
150  int ofs = (lowest + highest) / 2;
151  s = sc->first_symbol + ofs;
152 
153  /* Found a match? */
154  if (addr >= s->addr && addr <= s->addr + (s->len - 1)) {
155  if (addr == s->addr)
156  snprintf(symbol_buf, SYMBOLBUF_MAX,
157  "%s", s->name);
158  else
159  snprintf(symbol_buf, SYMBOLBUF_MAX,
160  "%s+0x%" PRIx64, s->name, (uint64_t)
161  (addr - s->addr));
162 
163  if (offset != NULL)
164  *offset = addr - s->addr;
165  if (n_argsp != NULL)
166  *n_argsp = s->n_args;
167 
168  return symbol_buf;
169  }
170 
171  if (addr < s->addr)
172  highest = ofs - 1;
173  else
174  lowest = ofs + 1;
175  }
176  }
177 
178  /* Not found? Then return NULL. */
179  return NULL;
180 }
181 
182 
183 /*
184  * get_symbol_name():
185  *
186  * See get_symbol_name_and_n_args().
187  */
188 char *get_symbol_name(struct symbol_context *sc, uint64_t addr, uint64_t *offs)
189 {
190  return get_symbol_name_and_n_args(sc, addr, offs, NULL);
191 }
192 
193 
194 /*
195  * add_symbol_name():
196  *
197  * Add a symbol to the symbol list.
198  */
200  uint64_t addr, uint64_t len, const char *name, int type, int n_args)
201 {
202  struct symbol *s;
203 
204  if (sc->sorted_array) {
205  fprintf(stderr, "add_symbol_name(): Internal error: the "
206  "symbol array is already sorted\n");
207  exit(1);
208  }
209 
210  if (name == NULL) {
211  fprintf(stderr, "add_symbol_name(): name = NULL\n");
212  exit(1);
213  }
214 
215  if (addr == 0 && strcmp(name, "_DYNAMIC_LINK") == 0)
216  return;
217 
218  if (name[0] == '\0')
219  return;
220 
221  /* TODO: Maybe this should be optional? */
222  if (name[0] == '.' || name[0] == '$')
223  return;
224 
225  /* Quick test-hack: */
226  if (n_args < 0) {
227  if (strcmp(name, "strlen") == 0)
228  n_args = 1;
229  if (strcmp(name, "strcmp") == 0)
230  n_args = 2;
231  if (strcmp(name, "strcpy") == 0)
232  n_args = 2;
233  if (strcmp(name, "strncpy") == 0)
234  n_args = 3;
235  if (strcmp(name, "strlcpy") == 0)
236  n_args = 3;
237  if (strcmp(name, "strlcat") == 0)
238  n_args = 3;
239  if (strcmp(name, "strncmp") == 0)
240  n_args = 3;
241  if (strcmp(name, "memset") == 0)
242  n_args = 3;
243  if (strcmp(name, "memcpy") == 0)
244  n_args = 3;
245  if (strcmp(name, "bzero") == 0)
246  n_args = 2;
247  if (strcmp(name, "bcopy") == 0)
248  n_args = 3;
249  }
250 
251  if ((addr >> 32) == 0 && (addr & 0x80000000ULL))
252  addr |= 0xffffffff00000000ULL;
253 
254  CHECK_ALLOCATION(s = (struct symbol *) malloc(sizeof(struct symbol)));
255  memset(s, 0, sizeof(struct symbol));
256 
258 
259  if (s->name == NULL)
260  CHECK_ALLOCATION(s->name = strdup(name));
261 
262  s->addr = addr;
263  s->len = len;
264  s->type = type;
265  s->n_args = n_args;
266 
267  sc->n_symbols ++;
268 
269  /* Add first in list: */
270  s->next = sc->first_symbol;
271  sc->first_symbol = s;
272 }
273 
274 
275 /*
276  * symbol_readfile():
277  *
278  * Read 'nm -S' style symbols from a file.
279  *
280  * TODO: This function is an ugly hack, and should be replaced
281  * with something that reads symbols directly from the executable
282  * images.
283  */
284 void symbol_readfile(struct symbol_context *sc, char *fname)
285 {
286  FILE *f;
287  char b1[80]; uint64_t addr;
288  char b2[80]; uint64_t len;
289  char b3[80]; int type;
290  char b4[80];
291  int cur_n_symbols = sc->n_symbols;
292 
293  f = fopen(fname, "r");
294  if (f == NULL) {
295  perror(fname);
296  exit(1);
297  }
298 
299  while (!feof(f)) {
300  memset(b1, 0, sizeof(b1));
301  memset(b2, 0, sizeof(b2));
302  memset(b3, 0, sizeof(b3));
303  memset(b4, 0, sizeof(b4));
304  if (fscanf(f, "%s %s\n", b1,b2) != 2)
305  fprintf(stderr, "warning: symbol file parse error\n");
306  if (strlen(b2) < 2 && !(b2[0]>='0' && b2[0]<='9')) {
307  strlcpy(b3, b2, sizeof(b3));
308  strlcpy(b2, "0", sizeof(b2));
309  if (fscanf(f, "%s\n", b4) != 1)
310  fprintf(stderr, "warning: symbol file parse error\n");
311  } else {
312  if (fscanf(f, "%s %s\n", b3,b4) != 2)
313  fprintf(stderr, "warning: symbol file parse error\n");
314  }
315 
316  /* printf("b1='%s' b2='%s' b3='%s' b4='%s'\n",
317  b1,b2,b3,b4); */
318  addr = strtoull(b1, NULL, 16);
319  len = strtoull(b2, NULL, 16);
320  type = b3[0];
321  /* printf("addr=%016" PRIx64" len=%016" PRIx64" type=%i\n",
322  addr, len, type); */
323 
324  if (type == 't' || type == 'r' || type == 'g')
325  continue;
326 
327  add_symbol_name(sc, addr, len, b4, type, -1);
328  }
329 
330  fclose(f);
331 
332  debug("%i symbols\n", sc->n_symbols - cur_n_symbols);
333 }
334 
335 
336 /*
337  * sym_addr_compare():
338  *
339  * Helper function for sorting symbols according to their address.
340  */
341 int sym_addr_compare(const void *a, const void *b)
342 {
343  struct symbol *p1 = (struct symbol *) a;
344  struct symbol *p2 = (struct symbol *) b;
345 
346  if (p1->addr < p2->addr)
347  return -1;
348  if (p1->addr > p2->addr)
349  return 1;
350 
351  return 0;
352 }
353 
354 
355 /*
356  * symbol_recalc_sizes():
357  *
358  * Recalculate sizes of symbols that have size = 0, by creating an array
359  * containing all symbols, qsort()-ing that array according to address, and
360  * recalculating the size fields if necessary.
361  */
363 {
364  struct symbol *tmp_array;
365  struct symbol *last_ptr;
366  struct symbol *tmp_ptr;
367  int i;
368 
369  CHECK_ALLOCATION(tmp_array = (struct symbol *) malloc(sizeof (struct symbol) *
370  sc->n_symbols));
371 
372  /* Copy first_symbol --> tmp_array, and remove the old
373  first_symbol at the same time: */
374  tmp_ptr = sc->first_symbol;
375  i = 0;
376  while (tmp_ptr != NULL) {
377  tmp_array[i] = *tmp_ptr;
378  last_ptr = tmp_ptr;
379  tmp_ptr = tmp_ptr->next;
380  free(last_ptr);
381  i++;
382  }
383 
384  qsort(tmp_array, sc->n_symbols, sizeof(struct symbol),
386  sc->sorted_array = 1;
387 
388  /* Recreate the first_symbol chain: */
389  sc->first_symbol = NULL;
390  for (i=0; i<sc->n_symbols; i++) {
391  /* Recalculate size, if 0: */
392  if (tmp_array[i].len == 0) {
393  uint64_t len;
394  if (i != sc->n_symbols-1)
395  len = tmp_array[i+1].addr
396  - tmp_array[i].addr;
397  else
398  len = 1;
399 
400  tmp_array[i].len = len;
401  }
402 
403  tmp_array[i].next = &tmp_array[i+1];
404  }
405 
406  sc->first_symbol = tmp_array;
407 }
408 
409 
410 /*
411  * symbol_init():
412  *
413  * Initialize the symbol hashtables.
414  */
415 void symbol_init(struct symbol_context *sc)
416 {
417  sc->first_symbol = NULL;
418  sc->sorted_array = 0;
419  sc->n_symbols = 0;
420 }
421 
symbol_context::first_symbol
struct symbol * first_symbol
Definition: symbol.h:50
f
void f(int s, int func, int only_name)
Definition: generate_arm_r.c:45
debug
#define debug
Definition: dev_adb.cc:57
symbol_context
Definition: symbol.h:49
symbol_context::n_symbols
int n_symbols
Definition: symbol.h:52
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
symbol_nsymbols
int symbol_nsymbols(struct symbol_context *sc)
Definition: symbol.cc:49
symbol_readfile
void symbol_readfile(struct symbol_context *sc, char *fname)
Definition: symbol.cc:284
get_symbol_name_and_n_args
char * get_symbol_name_and_n_args(struct symbol_context *sc, uint64_t addr, uint64_t *offset, int *n_argsp)
Definition: symbol.cc:110
get_symbol_name
char * get_symbol_name(struct symbol_context *sc, uint64_t addr, uint64_t *offs)
Definition: symbol.cc:188
symbol::name
char * name
Definition: symbol.h:41
symbol::type
int type
Definition: symbol.h:42
add_symbol_name
void add_symbol_name(struct symbol_context *sc, uint64_t addr, uint64_t len, const char *name, int type, int n_args)
Definition: symbol.cc:199
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2333
symbol_demangle_cplusplus
char * symbol_demangle_cplusplus(const char *name)
Definition: symbol_demangle.cc:236
symbol::addr
uint64_t addr
Definition: symbol.h:39
symbol::n_args
int n_args
Definition: symbol.h:44
sym_addr_compare
int sym_addr_compare(const void *a, const void *b)
Definition: symbol.cc:341
symbol::next
struct symbol * next
Definition: symbol.h:38
symbol.h
symbol_init
void symbol_init(struct symbol_context *sc)
Definition: symbol.cc:415
symbol_recalc_sizes
void symbol_recalc_sizes(struct symbol_context *sc)
Definition: symbol.cc:362
symbol
Definition: symbol.h:37
symbol::len
uint64_t len
Definition: symbol.h:40
SYMBOLBUF_MAX
#define SYMBOLBUF_MAX
Definition: symbol.cc:41
get_symbol_addr
int get_symbol_addr(struct symbol_context *sc, const char *symbol, uint64_t *addr)
Definition: symbol.cc:63
symbol_context::sorted_array
int sorted_array
Definition: symbol.h:51
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17