comparison objgrep/frontend.c @ 174:10c0cdc18208

objgrep-fe written, compiles
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 04 Jul 2014 08:46:32 +0000
parents
children 928ed52930aa
comparison
equal deleted inserted replaced
173:77cd647375e5 174:10c0cdc18208
1 /*
2 * This program is a front-end to objgrep. It takes an ASCII text file as
3 * input that lists the modules and sections to be grepped for, and it
4 * invokes objgrep via popen() for each listed section, all on the same
5 * unknown binary. We collect the symbol addresses printed by objgrep
6 * via our pipe, and then we sort them to produce the final report.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <unistd.h>
15
16 #define RAM_BOUNDARY 0x800000
17
18 #define SYMFLAG_AMBIG 8
19 #define SYMSRC_TEXTMATCH 4
20 #define SYMSRC_EXTRELOC 2
21 #define SYMSRC_INTRELOC 1
22
23 struct symbol {
24 char *name;
25 unsigned value;
26 int flags;
27 struct symbol *next;
28 };
29
30 struct symbol *flash_symbols, *ram_symbols;
31 unsigned num_flash_symbols, num_ram_symbols;
32 char *binfilename;
33
34 enter_symbol(name, valstr, symsrc)
35 char *name, *valstr;
36 {
37 struct symbol *newsym;
38
39 newsym = malloc(sizeof(struct symbol) + strlen(name) + 1);
40 if (!newsym) {
41 perror("malloc");
42 exit(1);
43 }
44 newsym->name = (char *)(newsym + 1);
45 strcpy(newsym->name, name);
46 newsym->value = strtoul(valstr, 0, 16);
47 newsym->flags = symsrc;
48 if (newsym->value < RAM_BOUNDARY) {
49 newsym->next = flash_symbols;
50 flash_symbols = newsym;
51 num_flash_symbols++;
52 } else {
53 newsym->next = ram_symbols;
54 ram_symbols = newsym;
55 num_ram_symbols++;
56 }
57 }
58
59 process_section(objfile, secname)
60 char *objfile, *secname;
61 {
62 char cmdline[1024], linebuf[512], *cp, *fields[3];
63 FILE *f;
64 int symsrc, i;
65 static char headline_textmatch[] = "This source section's symbols:";
66 static char headline_extreloc[] = "Externals deduced from relocs:";
67 static char headline_intreloc[] =
68 "This module's symbols deduced from section relocs:";
69
70 sprintf(cmdline, "objgrep -rs %s %s %s", objfile, secname, binfilename);
71 f = popen(cmdline, "r");
72 if (!f) {
73 perror("popen");
74 exit(1);
75 }
76 symsrc = 0;
77 while (fgets(linebuf, sizeof linebuf, f)) {
78 cp = index(linebuf, '\n');
79 if (!cp) {
80 fprintf(stderr,
81 "error: objgrep output line has no terminating newline\n");
82 exit(1);
83 }
84 *cp = '\0';
85 if (!strcmp(linebuf, headline_textmatch)) {
86 symsrc = SYMSRC_TEXTMATCH;
87 continue;
88 }
89 if (!strcmp(linebuf, headline_extreloc)) {
90 symsrc = SYMSRC_EXTRELOC;
91 continue;
92 }
93 if (!strcmp(linebuf, headline_intreloc)) {
94 symsrc = SYMSRC_INTRELOC;
95 continue;
96 }
97 cp = linebuf;
98 for (i = 0; ; i++) {
99 while (isspace(*cp))
100 cp++;
101 if (!*cp)
102 break;
103 if (i == 3) {
104 i++;
105 break;
106 }
107 for (fields[i] = cp; *cp && !isspace(*cp); cp++)
108 ;
109 if (*cp)
110 *cp++ = '\0';
111 }
112 if (i != 3)
113 continue;
114 if (fields[1][0] != '=' || fields[1][1])
115 continue;
116 if (!symsrc) {
117 fprintf(stderr,
118 "error: symbol output from objgrep w/o source indication\n");
119 exit(1);
120 }
121 enter_symbol(fields[0], fields[2], symsrc);
122 }
123 pclose(f);
124 }
125
126 process_list_file(listfilename)
127 char *listfilename;
128 {
129 FILE *f;
130 char linebuf[512], *objname, *cp, *np;
131 int lineno;
132
133 f = fopen(listfilename, "r");
134 if (!f) {
135 perror(listfilename);
136 exit(1);
137 }
138 for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) {
139 for (cp = linebuf; isspace(*cp); cp++)
140 ;
141 if (*cp == '\0' || *cp == '#')
142 continue;
143 for (objname = cp; *cp && !isspace(*cp); cp++)
144 ;
145 if (*cp)
146 *cp++ = '\0';
147 while (isspace(*cp))
148 cp++;
149 if (*cp == '\0' || *cp == '#') {
150 process_section(objname, ".text");
151 continue;
152 }
153 while (*cp && *cp != '#') {
154 for (np = cp; *cp && !isspace(*cp); cp++)
155 ;
156 if (*cp)
157 *cp++ = '\0';
158 process_section(objname, np);
159 while (isspace(*cp))
160 cp++;
161 }
162 }
163 fclose(f);
164 }
165
166 sort_by_value(sym1, sym2)
167 struct symbol **sym1, **sym2;
168 {
169 if ((*sym1)->value < (*sym2)->value)
170 return(-1);
171 if ((*sym1)->value > (*sym2)->value)
172 return(1);
173 return(0);
174 }
175
176 sort_by_name(sym1, sym2)
177 struct symbol **sym1, **sym2;
178 {
179 int i;
180
181 i = strcmp((*sym1)->name, (*sym2)->name);
182 if (i)
183 return i;
184 else
185 return sort_by_value(sym1, sym2);
186 }
187
188 fill_input_array(head, buf)
189 struct symbol *head, **buf;
190 {
191 struct symbol *sym, **p;
192
193 p = buf;
194 for (sym = head; sym; sym = sym->next)
195 *p = sym;
196 }
197
198 unsigned
199 dedup_symbols(inbuf, outbuf, total)
200 struct symbol **inbuf, **outbuf;
201 unsigned total;
202 {
203 struct symbol **ip, **op, **input_end, *nsym;
204
205 op = outbuf;
206 input_end = inbuf + total;
207 for (ip = inbuf; ip < input_end; ip++) {
208 nsym = *ip;
209 if (op == outbuf || strcmp(nsym->name, op[-1]->name)) {
210 *op++ = nsym;
211 continue;
212 }
213 if (nsym->value == op[-1]->value) {
214 op[-1]->flags |= nsym->flags;
215 continue;
216 }
217 op[-1]->flags |= SYMFLAG_AMBIG;
218 nsym->flags |= SYMFLAG_AMBIG;
219 *op++ = nsym;
220 }
221 return(op - outbuf);
222 }
223
224 emit_final_symbols(buf, total)
225 struct symbol **buf;
226 unsigned total;
227 {
228 struct symbol **p, **endbuf, *sym;
229
230 endbuf = buf + total;
231 for (p = buf; p < endbuf; p++) {
232 sym = *p;
233 printf("%08X %s (", sym->value, sym->name);
234 if (sym->flags & SYMSRC_TEXTMATCH)
235 putchar('S');
236 if (sym->flags & SYMSRC_EXTRELOC)
237 putchar('R');
238 if (sym->flags & SYMSRC_INTRELOC)
239 putchar('r');
240 if (sym->flags & SYMFLAG_AMBIG)
241 fputs(", ambiguous", stdout);
242 putchar(')');
243 putchar('\n');
244 }
245 }
246
247 sort_and_emit_symbols(head, total)
248 struct symbol *head;
249 unsigned total;
250 {
251 struct symbol **input, **output;
252 unsigned final_count;
253
254 input = malloc(sizeof(void *) * total);
255 if (!input) {
256 perror("malloc");
257 exit(1);
258 }
259 fill_input_array(head, input);
260 qsort(input, total, sizeof(void *), sort_by_name);
261 output = malloc(sizeof(void *) * total);
262 if (!output) {
263 perror("malloc");
264 exit(1);
265 }
266 final_count = dedup_symbols(input, output, total);
267 free(input);
268 qsort(output, final_count, sizeof(void *), sort_by_value);
269 emit_final_symbols(output, final_count);
270 free(output);
271 putchar('\n');
272 }
273
274 main(argc, argv)
275 char **argv;
276 {
277 if (argc != 3) {
278 fprintf(stderr, "usage: %s listfile binfile\n", argv[0]);
279 exit(1);
280 }
281 binfilename = argv[2];
282 process_list_file(argv[1]);
283 if (flash_symbols) {
284 printf("Flash symbols:\n\n");
285 sort_and_emit_symbols(flash_symbols, num_flash_symbols);
286 }
287 if (ram_symbols) {
288 printf("RAM symbols:\n\n");
289 sort_and_emit_symbols(ram_symbols, num_ram_symbols);
290 }
291 exit(0);
292 }