cmpmrg_text: detect some refs to rm'd funcs
[ia32rtools.git] / tools / asmproc.c
CommitLineData
ede51255 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "my_assert.h"
6
7static int my_isblank(char c)
8{
9 return c == '\t' || c == ' ' || c == '\r' || c == '\n';
10}
11
12static char *sskip(char *s)
13{
14 while (my_isblank(*s))
15 s++;
16
17 return s;
18}
19
20static char *next_word(char *w, size_t wsize, char *s)
21{
22 size_t i;
23
24 s = sskip(s);
25
26 for (i = 0; i < wsize - 1; i++) {
27 if (*s == 0 || my_isblank(s[i]))
28 break;
29 w[i] = s[i];
30 }
31 w[i] = 0;
32
33 if (*s != 0 && !my_isblank(s[i]))
34 printf("warning: '%s' truncated\n", w);
35
36 return s + i;
37}
38
39struct sl_item {
40 char *name;
368deb23 41 unsigned int callsites:1;
8022df01 42 unsigned int found:1;
ede51255 43};
44
45static int cmp_sym(const void *p1_, const void *p2_)
46{
47 const struct sl_item *p1 = p1_, *p2 = p2_;
48 const char *s1 = p1->name, *s2 = p2->name;
49 int i;
50
51 for (i = 0; ; i++) {
0c5547d1 52 if ((s1[i] | s2[i]) == 0)
53 break;
54
ede51255 55 if (s1[i] == s2[i])
56 continue;
57
0c5547d1 58 if (s1[i] == 0 && s2[i] == '@')
59 break;
60 if (s1[i] == '@' && s2[i] == 0)
ede51255 61 break;
62
63 return s1[i] - s2[i];
64 }
65
66 return 0;
67}
68
69static int cmp_sym_sort(const void *p1_, const void *p2_)
70{
71 const struct sl_item *p1 = p1_, *p2 = p2_;
72 const char *s1 = p1->name, *s2 = p2->name;
73 int ret;
74
75 ret = cmp_sym(p1_, p2_);
76 if (ret == 0) {
77 printf("%s: dupe sym: '%s' '%s'\n", __func__, s1, s2);
78 exit(1);
79 }
80 return ret;
81}
82
368deb23 83void read_list(struct sl_item **sl_in, int *cnt, int *alloc,
84 FILE *f, int callsites)
ede51255 85{
86 struct sl_item *sl = *sl_in;
87 int c = *cnt;
88 char line[256];
89 char word[256];
ede51255 90
91 while (fgets(line, sizeof(line), f) != NULL) {
0c5547d1 92 next_word(word, sizeof(word), line);
93 if (word[0] == 0 || word[0] == ';' || word[0] == '#')
ede51255 94 continue;
95
96 sl[c].name = strdup(word);
368deb23 97 sl[c].callsites = callsites;
8022df01 98 sl[c].found = 0;
ede51255 99 c++;
100
101 if (c >= *alloc) {
102 *alloc *= 2;
103 sl = realloc(sl, *alloc * sizeof(sl[0]));
104 my_assert_not(sl, NULL);
8022df01 105 memset(sl + c, 0, (*alloc - c) * sizeof(sl[0]));
ede51255 106 }
107 }
108
109 *sl_in = sl;
110 *cnt = c;
111}
112
8022df01 113const char *sym_use(const struct sl_item *sym)
114{
115 static char buf[256+3];
116 int ret;
117
0c5547d1 118 ret = snprintf(buf, sizeof(buf), "rm_%s", sym->name);
8022df01 119 if (ret >= sizeof(buf)) {
120 printf("truncation detected: '%s'\n", buf);
121 exit(1);
122 }
123
124 return buf;
125}
126
28023f83 127#define IS(w, y) !strcasecmp(w, y)
128#define IS_OR2(w, x, y) (IS(w, x) || IS(w, y))
129#define IS_OR3(w, x, y, z) (IS(w, x) || IS(w, y) || IS(w, z))
130
ede51255 131int main(int argc, char *argv[])
132{
8022df01 133 struct sl_item *symlist, *sym, ssym = { NULL, };
368deb23 134 int patch_callsites = 0;
ede51255 135 FILE *fout, *fin, *f;
136 int symlist_alloc;
137 int symlist_cnt;
138 char line[256];
139 char word[256];
140 char word2[256];
141 char word3[256];
142 char word4[256];
28023f83 143 char word5[256];
144 char word6[256];
ede51255 145 char *p;
8022df01 146 int i;
ede51255 147
368deb23 148 if (argc < 4) {
149 // -c - patch callsites
150 printf("usage:\n%s <asmf_out> <asmf_in> [[-c] <listf>]*>\n",
ede51255 151 argv[0]);
152 return 1;
153 }
154
155 symlist_alloc = 16;
156 symlist_cnt = 0;
8022df01 157 symlist = calloc(symlist_alloc, sizeof(symlist[0]));
ede51255 158 my_assert_not(symlist, NULL);
159
368deb23 160 for (i = 3; i < argc; i++) {
0c5547d1 161 if (strcmp(argv[i], "-c") == 0) {
368deb23 162 patch_callsites = 1;
163 continue;
164 }
165
166 f = fopen(argv[i], "r");
167 my_assert_not(f, NULL);
168 read_list(&symlist, &symlist_cnt, &symlist_alloc,
169 f, patch_callsites);
170 fclose(f);
ede51255 171
368deb23 172 patch_callsites = 0;
173 }
ede51255 174
175 qsort(symlist, symlist_cnt, sizeof(symlist[0]), cmp_sym_sort);
176
8022df01 177#if 0
178 printf("symlist:\n");
179 for (i = 0; i < symlist_cnt; i++)
368deb23 180 printf("%d '%s'\n", symlist[i].callsites, symlist[i].name);
8022df01 181#endif
ede51255 182
183 fin = fopen(argv[2], "r");
184 my_assert_not(fin, NULL);
185
186 fout = fopen(argv[1], "w");
187 my_assert_not(fout, NULL);
188
189 while (fgets(line, sizeof(line), fin))
190 {
191 p = sskip(line);
192 if (*p == 0 || *p == ';')
193 goto pass;
194
195 p = sskip(next_word(word, sizeof(word), p));
196 if (*p == 0 || *p == ';')
197 goto pass; // need at least 2 words
198
199 p = next_word(word2, sizeof(word2), p);
200
28023f83 201 if (IS_OR2(word2, "proc", "endp")) {
ede51255 202 ssym.name = word;
203 sym = bsearch(&ssym, symlist, symlist_cnt,
204 sizeof(symlist[0]), cmp_sym);
205 if (sym != NULL) {
8022df01 206 sym->found = 1;
ede51255 207 fprintf(fout, "rm_%s\t%s%s", word, word2, p);
208 continue;
209 }
210 }
211
28023f83 212 if (IS_OR3(word, "call", "jmp", "public")) {
ede51255 213 ssym.name = word2;
214 sym = bsearch(&ssym, symlist, symlist_cnt,
215 sizeof(symlist[0]), cmp_sym);
368deb23 216 if (sym != NULL && sym->callsites) {
8022df01 217 fprintf(fout, "\t\t%s\t%s%s", word,
218 sym_use(sym), p);
ede51255 219 continue;
220 }
221 }
222
223 p = sskip(p);
224 if (*p == 0 || *p == ';')
225 goto pass; // need at least 3 words
226
227 p = next_word(word3, sizeof(word3), p);
228
28023f83 229 // dd offset <sym>
230 // push offset <sym>
231 // jcc short <sym>
232 if ( (IS_OR2(word, "dd", "push") && IS(word2, "offset"))
233 || (word[0] == 'j' && IS(word2, "short")) ) {
ede51255 234 ssym.name = word3;
235 sym = bsearch(&ssym, symlist, symlist_cnt,
236 sizeof(symlist[0]), cmp_sym);
368deb23 237 if (sym != NULL && sym->callsites) {
28023f83 238 fprintf(fout, "\t\t%s %s %s%s",
239 word, word2, sym_use(sym), p);
ede51255 240 continue;
241 }
242 }
243
244 p = sskip(p);
245 if (*p == 0 || *p == ';')
246 goto pass; // need at least 4 words
247
248 p = next_word(word4, sizeof(word4), p);
249
28023f83 250 // <name> dd offset <sym>
251 if (IS(word2, "dd") && IS(word3, "offset")) {
ede51255 252 ssym.name = word4;
253 sym = bsearch(&ssym, symlist, symlist_cnt,
254 sizeof(symlist[0]), cmp_sym);
368deb23 255 if (sym != NULL && sym->callsites) {
8022df01 256 fprintf(fout, "%s\tdd offset %s%s", word,
257 sym_use(sym), p);
ede51255 258 continue;
259 }
260 }
261
28023f83 262 // mov <something>, offset <sym>
263 // jcc <some> ptr <sym>
264 if ( (IS(word, "mov") && IS(word3, "offset"))
265 || (word[0] == 'j' && IS(word3, "ptr")) ) {
266 ssym.name = word4;
267 sym = bsearch(&ssym, symlist, symlist_cnt,
268 sizeof(symlist[0]), cmp_sym);
269 if (sym != NULL && sym->callsites) {
270 fprintf(fout, "\t\t%s\t%s %s %s%s",
271 word, word2, word3,
272 sym_use(sym), p);
273 continue;
274 }
275 }
276
277 p = sskip(p);
278 if (*p == 0 || *p == ';')
279 goto pass; // need at least 5 words
280
281 p = next_word(word5, sizeof(word5), p);
282
283 p = sskip(p);
284 if (*p == 0 || *p == ';')
285 goto pass; // need at least 6 words
286
287 p = next_word(word6, sizeof(word6), p);
288
289 // <op> dword ptr <something>, offset <sym>
290 if ( IS(word2, "dword") && IS(word3, "ptr")
291 && IS(word5, "offset") ) {
292 ssym.name = word6;
293 sym = bsearch(&ssym, symlist, symlist_cnt,
294 sizeof(symlist[0]), cmp_sym);
295 if (sym != NULL && sym->callsites) {
296 fprintf(fout, "\t\t%s\tdword ptr %s offset %s%s",
297 word, word4, sym_use(sym), p);
298 continue;
299 }
300 }
301
ede51255 302pass:
303 fwrite(line, 1, strlen(line), fout);
304 }
305
8022df01 306 for (i = 0; i < symlist_cnt; i++) {
307 if (!symlist[i].found)
308 printf("warning: sym '%s' not found\n", symlist[i].name);
309 }
310
ede51255 311 fclose(fin);
312 fclose(fout);
313
314 return 0;
315}