1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include "ticks.h"
6
7 static symbol *symbols[65536] = {0};
8 static symbol *symbols_byname = NULL;
9
10
11
demangle_filename(const char * input,char * buf,size_t buflen,int * lineno)12 static void demangle_filename(const char *input, char *buf, size_t buflen, int *lineno)
13 {
14 char *start = buf;
15 char *ptr;
16
17 *lineno = -1;
18 ptr = strrchr(input, ':');
19
20 if ( ptr != NULL ) {
21 snprintf(buf,buflen,"%.*s", (int)(ptr - input), input);
22 *lineno = atoi(ptr+1);
23 }
24 }
25
26
symbol_compare(const void * p1,const void * p2)27 static int symbol_compare(const void *p1, const void *p2)
28 {
29 const symbol *s1 = p1, *s2 = p2;
30
31 return s2->address - s1->address;
32 }
33
34
35
36
read_symbol_file(char * filename)37 void read_symbol_file(char *filename)
38 {
39 char buf[256];
40 FILE *fp = fopen(filename,"r");
41
42 if ( fp != NULL ) {
43 while ( fgets(buf, sizeof(buf), fp) != NULL ) {
44 int argc;
45 char **argv = parse_words(buf,&argc);
46
47 // Ignore
48 if ( argc < 9 ) {
49 if ( argc >= 3 ) {
50 // We've got at least 3, do something (it's an old format)
51 symbol *sym = calloc(1,sizeof(*sym));
52 sym->name = strdup(argv[0]);
53 sym->address = strtol(argv[2] + 1, NULL, 16);
54 sym->symtype = SYM_ADDRESS;
55 if ( sym->address >= 0 && sym->address <= 65535 ) {
56 LL_APPEND(symbols[sym->address], sym);
57 }
58 HASH_ADD_KEYPTR(hh, symbols_byname, sym->name, strlen(sym->name), sym);
59 }
60 free(argv);
61 continue;
62 }
63 if ( strncmp(argv[0],"__CDBINFO__",11) == 0 ) {
64 debug_add_info_encoded(argv[0] + 11);
65 } else if ( strncmp(argv[0], "__C_LINE_",9) && strncmp(argv[0], "__ASM_LINE_",11) ) {
66 symbol *sym = calloc(1,sizeof(*sym));
67
68 sym->name = strdup(argv[0]);
69 sym->file = strdup(argv[8]);
70 sym->section = strdup(argv[8]); // TODO, comma
71 sym->islocal = 0;
72 if ( strcmp(argv[5], "local,")) {
73 sym->islocal = 1;
74 }
75 sym->symtype = SYM_ADDRESS;
76 if ( strcmp(argv[4],"const,") == 0 ) {
77 sym->symtype = SYM_CONST;
78 }
79 sym->address = strtol(argv[2] + 1, NULL, 16);
80 if ( sym->address >= 0 && sym->address <= 65535 ) {
81 LL_APPEND(symbols[sym->address], sym);
82 }
83 HASH_ADD_KEYPTR(hh, symbols_byname, sym->name, strlen(sym->name), sym);
84 } else if ( argc > 9 ) {
85 /* It's a cline/asmline symbol */
86 char filename[FILENAME_MAX+1];
87 int lineno;
88 char *ptr;
89
90 demangle_filename(argv[9], filename, sizeof(filename),&lineno);
91 debug_add_cline(filename, lineno, argv[2]);
92
93 if ( ( ptr = strchr(filename,':')) != NULL ) {
94 *ptr = 0;
95 debug_add_cline(filename, lineno, argv[2]);
96 }
97
98 }
99 free(argv);
100 }
101 }
102 }
103
find_symbol_byname(const char * name)104 symbol *find_symbol_byname(const char *name)
105 {
106 symbol *sym;
107
108 HASH_FIND_STR(symbols_byname, name, sym);
109
110 return sym;
111 }
112
symbol_resolve(char * name)113 int symbol_resolve(char *name)
114 {
115 symbol *sym;
116 char *ptr;
117
118 HASH_FIND_STR(symbols_byname, name, sym);
119 if ( sym != NULL ) {
120 return sym->address;
121 }
122
123 /* Check for it being a file */
124 return debug_resolve_source(name);
125 }
126
127
128
129 // Find a symbol lower than where we were
symbol_find_lower(int addr,symboltype preferred_type,char * buf,size_t buflen)130 int symbol_find_lower(int addr, symboltype preferred_type, char *buf, size_t buflen)
131 {
132 symbol *sym;
133 int original_address = addr;
134
135 buf[0] = 0;
136
137 while ( 1 ) {
138 if ( addr < 0 ) {
139 return -1;
140 }
141
142 while ( (sym = symbols[addr % 65536]) == NULL && addr > 0 ) {
143 addr--;
144 }
145
146 while ( sym != NULL ) {
147 if ( preferred_type == SYM_ANY ) {
148 break;
149 }
150 // Skip over internal labels?
151 if ( preferred_type == sym->symtype && strncmp(sym->name,"i_",2)) {
152 break;
153 }
154 sym = sym->next;
155 }
156
157 if ( sym != NULL ) {
158 snprintf(buf,buflen,"%s+%d", sym->name, original_address-addr);
159 return 0;
160 }
161 addr--;
162 }
163 }
164
find_symbol(int addr,symboltype preferred_type)165 const char *find_symbol(int addr, symboltype preferred_type)
166 {
167 symbol *sym;
168
169 if ( addr < 0 ) {
170 return NULL;
171 }
172
173 sym = symbols[addr % 65536];
174
175 while ( sym != NULL ) {
176 if ( preferred_type == SYM_ANY ) {
177 return sym->name;
178 }
179 if ( preferred_type == sym->symtype ) {
180 return sym->name;
181 }
182 sym = sym->next;
183 }
184 return NULL;
185 }
186
parse_words(char * line,int * argc)187 char **parse_words(char *line, int *argc)
188 {
189 int i = 0, j = 0 , n = 0;
190 int len = strlen(line);
191 int in_single_quotes = 0, in_double_quotes = 0;
192 char **args;
193
194 while ( isspace(line[i] ) ) {
195 i++;
196 }
197
198 for ( ; i <= len; i++) {
199 switch (line[i]) {
200 case '"':
201 if (in_single_quotes) {
202 line[j++] = line[i];
203 break;
204 }
205 in_double_quotes = !in_double_quotes;
206 break;
207 case '\'':
208 if (in_double_quotes) {
209 line[j++] = line[i];
210 break;
211 }
212 in_single_quotes = !in_single_quotes;
213 break;
214 case ' ':
215 case '\t':
216 case '\r':
217 case '\n':
218 case 0:
219 if (!in_single_quotes && !in_double_quotes) {
220 line[j++] = 0;
221 n++;
222 i++;
223 /* Try to find the start of the next word */
224 while (i <= len && (line[i] == 0 || isspace(line[i])) ) {
225 i++;
226 }
227 i--;
228 break;
229 }
230 line[j++] = line[i];
231 break;
232 case '\\':
233 switch (line[i + 1]) {
234 case '"':
235 case '\'':
236 case '\\':
237 line[j++] = line[i + 1];
238 break;
239 case ' ':
240 if (in_single_quotes || in_double_quotes) {
241 line[j++] = line[i];
242 }
243 line[j++] = line[i + 1];
244 break;
245 default:
246 line[j++] = line[i];
247 line[j++] = line[i + 1];
248 break;
249 }
250 i++;
251 break;
252 default:
253 line[j++] = line[i];
254 break;
255 }
256 }
257
258 args = (char **)malloc(sizeof(char *) * (n + 1) );
259 n = 0;
260 args[n++] = line;
261 j--;
262
263 for (i = 0; i < j; i++) {
264 if (line[i] == 0) {
265 args[n++] = line + i + 1;
266 }
267 }
268
269 *argc = n;
270
271 return args;
272 }
273