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