minor makefile update
[ia32rtools.git] / tools / cmpmrg_text.c
CommitLineData
cfd23479 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <linux/coff.h>
5#include <assert.h>
6#include <stdint.h>
7
ede51255 8#include "my_assert.h"
9
cfd23479 10/* http://www.delorie.com/djgpp/doc/coff/ */
11
12typedef struct {
13 unsigned short f_magic; /* magic number */
14 unsigned short f_nscns; /* number of sections */
15 unsigned int f_timdat; /* time & date stamp */
16 unsigned int f_symptr; /* file pointer to symtab */
17 unsigned int f_nsyms; /* number of symtab entries */
18 unsigned short f_opthdr; /* sizeof(optional hdr) */
19 unsigned short f_flags; /* flags */
20} FILHDR;
21
22typedef struct {
23 unsigned short magic; /* type of file */
24 unsigned short vstamp; /* version stamp */
25 unsigned int tsize; /* text size in bytes, padded to FW bdry*/
26 unsigned int dsize; /* initialized data " " */
27 unsigned int bsize; /* uninitialized data " " */
28 unsigned int entry; /* entry pt. */
29 unsigned int text_start; /* base of text used for this file */
30 unsigned int data_start; /* base of data used for this file */
31} AOUTHDR;
32
33typedef struct {
34 char s_name[8]; /* section name */
35 unsigned int s_paddr; /* physical address, aliased s_nlib */
36 unsigned int s_vaddr; /* virtual address */
37 unsigned int s_size; /* section size */
38 unsigned int s_scnptr; /* file ptr to raw data for section */
39 unsigned int s_relptr; /* file ptr to relocation */
40 unsigned int s_lnnoptr; /* file ptr to line numbers */
41 unsigned short s_nreloc; /* number of relocation entries */
42 unsigned short s_nlnno; /* number of line number entries */
43 unsigned int s_flags; /* flags */
44} SCNHDR;
45
46typedef struct {
47 unsigned int r_vaddr; /* address of relocation */
48 unsigned int r_symndx; /* symbol we're adjusting for */
49 unsigned short r_type; /* type of relocation */
50} __attribute__((packed)) RELOC;
51
e86c9ee6 52typedef struct {
53 union {
54 char e_name[E_SYMNMLEN];
55 struct {
56 unsigned int e_zeroes;
57 unsigned int e_offset;
58 } e;
59 } e;
60 unsigned int e_value;
61 short e_scnum;
62 unsigned short e_type;
63 unsigned char e_sclass;
64 unsigned char e_numaux;
65} __attribute__((packed)) SYMENT;
66
67#define C_EXT 2
68
69struct my_symtab {
70 unsigned int addr;
a2f78da4 71 //unsigned int fpos; // for patching
72 unsigned int is_text:1;
e86c9ee6 73 char *name;
74};
75
572a6bea 76struct my_sect_info {
77 long scnhdr_fofs;
78 long sect_fofs;
79 long reloc_fofs;
80 uint8_t *data;
81 long size;
82 RELOC *relocs;
83 long reloc_cnt;
84};
85
e86c9ee6 86static int symt_cmp(const void *p1_, const void *p2_)
87{
88 const struct my_symtab *p1 = p1_, *p2 = p2_;
89 return p1->addr - p2->addr;
90}
91
cfd23479 92void parse_headers(FILE *f, unsigned int *base_out,
572a6bea 93 struct my_sect_info *sect_i,
a2f78da4 94 struct my_symtab **symtab_out, long *sym_cnt,
95 struct my_symtab **raw_symtab_out, long *raw_sym_cnt)
cfd23479 96{
a2f78da4 97 struct my_symtab *symt_txt = NULL;
98 struct my_symtab *symt_all = NULL;
e86c9ee6 99 char *stringtab = NULL;
cfd23479 100 unsigned int base = 0;
e86c9ee6 101 int text_scnum = 0;
102 long filesize;
103 char symname[9];
cfd23479 104 long opthdr_pos;
105 long reloc_size;
106 FILHDR hdr;
107 AOUTHDR opthdr;
108 SCNHDR scnhdr;
e86c9ee6 109 SYMENT syment;
110 int i, s, val;
cfd23479 111 int ret;
112
e86c9ee6 113 ret = fseek(f, 0, SEEK_END);
114 my_assert(ret, 0);
115
116 filesize = ftell(f);
117
118 ret = fseek(f, 0, SEEK_SET);
119 my_assert(ret, 0);
120
cfd23479 121 ret = fread(&hdr, 1, sizeof(hdr), f);
122 my_assert(ret, sizeof(hdr));
123
124 if (hdr.f_magic == 0x5a4d) // MZ
125 {
126 ret = fseek(f, 0x3c, SEEK_SET);
127 my_assert(ret, 0);
128 ret = fread(&val, 1, sizeof(val), f);
129 my_assert(ret, sizeof(val));
130
131 ret = fseek(f, val, SEEK_SET);
132 my_assert(ret, 0);
133 ret = fread(&val, 1, sizeof(val), f);
134 my_assert(ret, sizeof(val));
135 my_assert(val, 0x4550); // PE
136
137 // should be COFF now
138 ret = fread(&hdr, 1, sizeof(hdr), f);
139 my_assert(ret, sizeof(hdr));
140 }
141
142 my_assert(hdr.f_magic, COFF_I386MAGIC);
143
144 if (hdr.f_opthdr != 0)
145 {
146 opthdr_pos = ftell(f);
147
148 if (hdr.f_opthdr < sizeof(opthdr))
149 my_assert(1, 0);
150
151 ret = fread(&opthdr, 1, sizeof(opthdr), f);
152 my_assert(ret, sizeof(opthdr));
153 my_assert(opthdr.magic, COFF_ZMAGIC);
154
2c605b97 155 //printf("text_start: %x\n", opthdr.text_start);
cfd23479 156
157 if (hdr.f_opthdr > sizeof(opthdr)) {
158 ret = fread(&base, 1, sizeof(base), f);
159 my_assert(ret, sizeof(base));
2c605b97 160 //printf("base: %x\n", base);
cfd23479 161 }
162 ret = fseek(f, opthdr_pos + hdr.f_opthdr, SEEK_SET);
163 my_assert(ret, 0);
164 }
165
e86c9ee6 166 // note: assuming first non-empty one is .text ..
cfd23479 167 for (s = 0; s < hdr.f_nscns; s++) {
572a6bea 168 sect_i->scnhdr_fofs = ftell(f);
169
cfd23479 170 ret = fread(&scnhdr, 1, sizeof(scnhdr), f);
171 my_assert(ret, sizeof(scnhdr));
172
e86c9ee6 173 if (scnhdr.s_size != 0) {
174 text_scnum = s + 1;
cfd23479 175 break;
e86c9ee6 176 }
cfd23479 177 }
572a6bea 178 my_assert(s < hdr.f_nscns, 1);
cfd23479 179
2c605b97 180#if 0
e86c9ee6 181 printf("f_nsyms: %x\n", hdr.f_nsyms);
cfd23479 182 printf("s_name: '%s'\n", scnhdr.s_name);
183 printf("s_vaddr: %x\n", scnhdr.s_vaddr);
184 printf("s_size: %x\n", scnhdr.s_size);
e86c9ee6 185 //printf("s_scnptr: %x\n", scnhdr.s_scnptr);
cfd23479 186 printf("s_nreloc: %x\n", scnhdr.s_nreloc);
187 printf("--\n");
2c605b97 188#endif
cfd23479 189
190 ret = fseek(f, scnhdr.s_scnptr, SEEK_SET);
191 my_assert(ret, 0);
192
572a6bea 193 sect_i->data = malloc(scnhdr.s_size);
194 my_assert_not(sect_i->data, NULL);
195 ret = fread(sect_i->data, 1, scnhdr.s_size, f);
cfd23479 196 my_assert(ret, scnhdr.s_size);
197
572a6bea 198 sect_i->sect_fofs = scnhdr.s_scnptr;
199 sect_i->size = scnhdr.s_size;
cfd23479 200
e86c9ee6 201 // relocs
cfd23479 202 ret = fseek(f, scnhdr.s_relptr, SEEK_SET);
203 my_assert(ret, 0);
204
572a6bea 205 reloc_size = scnhdr.s_nreloc * sizeof(sect_i->relocs[0]);
206 sect_i->relocs = malloc(reloc_size + 1);
207 my_assert_not(sect_i->relocs, NULL);
208 ret = fread(sect_i->relocs, 1, reloc_size, f);
cfd23479 209 my_assert(ret, reloc_size);
210
572a6bea 211 sect_i->reloc_cnt = scnhdr.s_nreloc;
212 sect_i->reloc_fofs = scnhdr.s_relptr;
213
214 if (base != 0 && base_out != NULL)
215 *base_out = base + scnhdr.s_vaddr;
216
217 if (symtab_out == NULL || sym_cnt == NULL)
218 return;
cfd23479 219
e86c9ee6 220 // symtab
221 if (hdr.f_nsyms != 0) {
222 symname[8] = 0;
223
a2f78da4 224 symt_txt = malloc(hdr.f_nsyms * sizeof(symt_txt[0]) + 1);
225 my_assert_not(symt_txt, NULL);
226 symt_all = malloc(hdr.f_nsyms * sizeof(symt_all[0]) + 1);
227 my_assert_not(symt_all, NULL);
e86c9ee6 228
229 ret = fseek(f, hdr.f_symptr
230 + hdr.f_nsyms * sizeof(syment), SEEK_SET);
231 my_assert(ret, 0);
232 ret = fread(&i, 1, sizeof(i), f);
233 my_assert(ret, sizeof(i));
234 my_assert((unsigned int)i < filesize, 1);
235
236 stringtab = malloc(i);
237 my_assert_not(stringtab, NULL);
238 memset(stringtab, 0, 4);
239 ret = fread(stringtab + 4, 1, i - 4, f);
240 my_assert(ret, i - 4);
241
242 ret = fseek(f, hdr.f_symptr, SEEK_SET);
243 my_assert(ret, 0);
244 }
245
246 for (i = s = 0; i < hdr.f_nsyms; i++) {
a2f78da4 247 //long pos = ftell(f);
e86c9ee6 248
249 ret = fread(&syment, 1, sizeof(syment), f);
250 my_assert(ret, sizeof(syment));
251
252 strncpy(symname, syment.e.e_name, 8);
253 //printf("%3d %2d %08x '%s'\n", syment.e_sclass,
254 // syment.e_scnum, syment.e_value, symname);
255
a2f78da4 256 symt_all[i].addr = syment.e_value;
257 //symt_all[i].fpos = pos;
e86c9ee6 258 if (syment.e.e.e_zeroes == 0)
a2f78da4 259 symt_all[i].name = stringtab + syment.e.e.e_offset;
e86c9ee6 260 else
a2f78da4 261 symt_all[i].name = strdup(symname);
262
263 symt_all[i].is_text = (syment.e_scnum == text_scnum);
264 if (symt_all[i].is_text && syment.e_sclass == C_EXT) {
265 symt_txt[s] = symt_all[i];
266 s++;
267 }
e86c9ee6 268
269 if (syment.e_numaux) {
270 ret = fseek(f, syment.e_numaux * sizeof(syment),
271 SEEK_CUR);
272 my_assert(ret, 0);
273 i += syment.e_numaux;
274 }
275 }
276
a2f78da4 277 if (symt_txt != NULL)
278 qsort(symt_txt, s, sizeof(symt_txt[0]), symt_cmp);
e86c9ee6 279
280 *sym_cnt = s;
a2f78da4 281 *symtab_out = symt_txt;
282 *raw_sym_cnt = i;
283 *raw_symtab_out = symt_all;
cfd23479 284}
285
286static int handle_pad(uint8_t *d_obj, uint8_t *d_exe, int maxlen)
287{
288 static const uint8_t p7[7] = { 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00 };
289 static const uint8_t p6[6] = { 0x8d, 0x9b, 0x00, 0x00, 0x00, 0x00 };
3ebea2cf 290 static const uint8_t p5[5] = { 0x05, 0x00, 0x00, 0x00, 0x00 }; // add eax, 0
291 static const uint8_t p4[4] = { 0x8d, 0x64, 0x24, 0x00 }; // lea
292 static const uint8_t p3[3] = { 0x8d, 0x49, 0x00 }; // lea ecx, [ecx]
293 static const uint8_t p2[2] = { 0x8b, 0xff }; // mov edi, edi
294 static const uint8_t p1[1] = { 0x90 }; // nop
cfd23479 295 int len;
296 int i;
297
298 for (i = 0; i < maxlen; i++)
299 if (d_exe[i] != 0xcc)
300 break;
301
302 for (len = i; len > 0; )
303 {
304 i = len;
305 if (i > 7)
306 i = 7;
307
308 switch (i) {
309 #define CASE(x) \
310 case sizeof(p ## x): \
311 if (memcmp(d_obj, p ## x, sizeof(p ## x))) \
312 return 0; \
313 memset(d_obj, 0xcc, sizeof(p ## x)); \
314 break;
315 CASE(7)
316 CASE(6)
317 CASE(5)
318 CASE(4)
319 CASE(3)
320 CASE(2)
321 CASE(1)
322 default:
323 printf("%s: unhandled len: %d\n", __func__, len);
324 return 0;
325 #undef CASE
326 }
327
328 len -= i;
329 d_obj += i;
330 }
331
332 return 1;
333}
334
335struct equiv_opcode {
336 signed char len;
337 signed char ofs;
338 short cmp_rm;
339 uint8_t v_masm[8];
340 uint8_t v_masm_mask[8];
341 uint8_t v_msvc[8];
342 uint8_t v_msvc_mask[8];
343} equiv_ops[] = {
344 // cmp $0x11,%ax
345 { 4, -1, 0,
346 { 0x66,0x83,0xf8,0x03 }, { 0xff,0xff,0xff,0x00 },
347 { 0x66,0x3d,0x03,0x00 }, { 0xff,0xff,0x00,0xff }, },
348 // lea -0x1(%ebx,%eax,1),%esi // op mod/rm sib offs
349 // mov, test, imm grp 1
350 { 3, -2, 1,
351 { 0x8d,0x74,0x03 }, { 0xf0,0x07,0xc0 },
352 { 0x8d,0x74,0x18 }, { 0xf0,0x07,0xc0 }, },
353 // movzbl 0x58f24a(%eax,%ecx,1),%eax
354 { 4, -3, 1,
355 { 0x0f,0xb6,0x84,0x08 }, { 0xff,0xff,0x07,0xc0 },
356 { 0x0f,0xb6,0x84,0x01 }, { 0xff,0xff,0x07,0xc0 }, },
357 // inc/dec
358 { 3, -2, 1,
359 { 0xfe,0x4c,0x03 }, { 0xfe,0xff,0xc0 },
360 { 0xfe,0x4c,0x18 }, { 0xfe,0xff,0xc0 }, },
361 // cmp
362 { 3, -2, 1,
363 { 0x38,0x0c,0x0c }, { 0xff,0xff,0xc0 },
364 { 0x38,0x0c,0x30 }, { 0xff,0xff,0xc0 }, },
365 // test %dl,%bl
366 { 2, -1, 1,
367 { 0x84,0xd3 }, { 0xfe,0xc0 },
368 { 0x84,0xda }, { 0xfe,0xc0 }, },
369 // cmp r,r/m vs rm/r
370 { 2, 0, 1,
371 { 0x3a,0xca }, { 0xff,0xc0 },
372 { 0x38,0xd1 }, { 0xff,0xc0 }, },
373 // rep + 66 prefix
374 { 2, 0, 0,
375 { 0xf3,0x66 }, { 0xfe,0xff },
376 { 0x66,0xf3 }, { 0xff,0xfe }, },
377 // fadd st, st(0) vs st(0), st
378 { 2, 0, 0,
379 { 0xd8,0xc0 }, { 0xff,0xf7 },
380 { 0xdc,0xc0 }, { 0xff,0xf7 }, },
381
382 // broad filters (may take too much..)
383 // testb $0x4,0x1d(%esi,%eax,1)
384 // movb, push, ..
385 { 3, -2, 1,
386 { 0xf6,0x44,0x06 }, { 0x00,0x07,0xc0 },
387 { 0xf6,0x44,0x30 }, { 0x00,0x07,0xc0 }, },
388};
389
390static int cmp_mask(uint8_t *d, uint8_t *expect, uint8_t *mask, int len)
391{
392 int i;
393
394 for (i = 0; i < len; i++)
395 if ((d[i] & mask[i]) != (expect[i] & mask[i]))
396 return 1;
397
398 return 0;
399}
400
401static int check_equiv(uint8_t *d_obj, uint8_t *d_exe, int maxlen)
402{
403 uint8_t vo, ve, vo2, ve2;
404 int i, jo, je;
405 int len, ofs;
406
407 for (i = 0; i < sizeof(equiv_ops) / sizeof(equiv_ops[0]); i++)
408 {
409 struct equiv_opcode *op = &equiv_ops[i];
410
411 len = op->len;
412 if (maxlen < len)
413 continue;
414
415 ofs = op->ofs;
416 if (cmp_mask(d_obj + ofs, op->v_masm,
417 op->v_masm_mask, len))
418 continue;
419 if (cmp_mask(d_exe + ofs, op->v_msvc,
420 op->v_msvc_mask, len))
421 continue;
422
423 jo = je = 0;
424 d_obj += ofs;
425 d_exe += ofs;
426 while (1)
427 {
428 for (; jo < len; jo++)
429 if (op->v_masm_mask[jo] != 0xff)
430 break;
431 for (; je < len; je++)
432 if (op->v_msvc_mask[je] != 0xff)
433 break;
434
435 if ((jo == len && je != len) || (jo != len && je == len)) {
436 printf("invalid equiv_ops\n");
437 return -1;
438 }
439 if (jo == len)
440 return len + ofs - 1; // matched
441
442 // var byte
443 vo = d_obj[jo] & ~op->v_masm_mask[jo];
444 ve = d_exe[je] & ~op->v_msvc_mask[je];
445 if (op->cmp_rm && op->v_masm_mask[jo] == 0xc0) {
446 vo2 = vo >> 3;
447 vo &= 7;
448 ve2 = ve & 7;
449 ve >>= 3;
450 if (vo != ve || vo2 != ve2)
451 return -1;
452 }
453 else {
454 if (vo != ve)
455 return -1;
456 }
457
458 jo++;
459 je++;
460 }
461 }
462
463 return -1;
464}
465
572a6bea 466static void fill_int3(unsigned char *d, int len)
467{
468 while (len-- > 0) {
a2f78da4 469 if (d[0] == 0xcc && d[1] == 0xcc)
572a6bea 470 break;
471 *d++ = 0xcc;
472 }
473}
474
cfd23479 475int main(int argc, char *argv[])
476{
de50b98b 477 unsigned int base = 0, addr, end, sym, *t;
572a6bea 478 struct my_sect_info s_text_obj, s_text_exe;
a2f78da4 479 struct my_symtab *raw_syms_obj = NULL;
572a6bea 480 struct my_symtab *syms_obj = NULL;
a2f78da4 481 long sym_cnt_obj, raw_sym_cnt_obj;
cfd23479 482 FILE *f_obj, *f_exe;
572a6bea 483 SCNHDR tmphdr;
484 long sztext_cmn;
c0d9cac6 485 int do_cmp = 1;
cfd23479 486 int retval = 1;
487 int left;
c0d9cac6 488 int arg;
cfd23479 489 int ret;
490 int i;
491
c0d9cac6 492 for (arg = 1; arg < argc; arg++) {
493 if (!strcmp(argv[arg], "-n"))
494 do_cmp = 0;
495 else
496 break;
497 }
498
499 if (argc != arg + 2) {
500 printf("usage:\n%s [-n] <a_obj> <exe>\n", argv[0]);
cfd23479 501 return 1;
502 }
503
c0d9cac6 504 f_obj = fopen(argv[arg++], "r+b");
cfd23479 505 if (f_obj == NULL) {
3ebea2cf 506 fprintf(stderr, "%s: ", argv[1]);
cfd23479 507 perror("");
508 return 1;
509 }
510
c0d9cac6 511 f_exe = fopen(argv[arg++], "r");
cfd23479 512 if (f_exe == NULL) {
3ebea2cf 513 fprintf(stderr, "%s: ", argv[2]);
cfd23479 514 perror("");
515 return 1;
516 }
517
a2f78da4 518 parse_headers(f_obj, NULL, &s_text_obj, &syms_obj, &sym_cnt_obj,
519 &raw_syms_obj, &raw_sym_cnt_obj);
520 parse_headers(f_exe, &base, &s_text_exe, NULL, NULL, NULL, NULL);
cfd23479 521
572a6bea 522 sztext_cmn = s_text_obj.size;
523 if (sztext_cmn > s_text_exe.size)
524 sztext_cmn = s_text_exe.size;
cfd23479 525
526 if (sztext_cmn == 0) {
527 printf("bad .text size(s): %ld, %ld\n",
572a6bea 528 s_text_obj.size, s_text_exe.size);
cfd23479 529 return 1;
530 }
531
572a6bea 532 for (i = 0; i < s_text_obj.reloc_cnt; i++)
cfd23479 533 {
572a6bea 534 unsigned int a = s_text_obj.relocs[i].r_vaddr;
535 //printf("%04x %08x\n", s_text_obj.relocs[i].r_type, a);
cfd23479 536
572a6bea 537 switch (s_text_obj.relocs[i].r_type) {
2c605b97 538 case 0x06: // RELOC_ADDR32
539 case 0x14: // RELOC_REL32
540 // must preserve stored val,
572a6bea 541 // so trash exe so that cmp passes
542 memcpy(s_text_exe.data + a, s_text_obj.data + a, 4);
cfd23479 543 break;
544 default:
2c605b97 545 printf("unknown reloc %x @%08x/%08x\n",
572a6bea 546 s_text_obj.relocs[i].r_type, a, base + a);
cfd23479 547 return 1;
548 }
549 }
550
c0d9cac6 551 if (do_cmp)
cfd23479 552 for (i = 0; i < sztext_cmn; i++)
553 {
572a6bea 554 if (s_text_obj.data[i] == s_text_exe.data[i])
cfd23479 555 continue;
556
557 left = sztext_cmn - i;
558
572a6bea 559 if (s_text_exe.data[i] == 0xcc) { // padding
560 if (handle_pad(s_text_obj.data + i,
561 s_text_exe.data + i, left))
cfd23479 562 continue;
563 }
564
572a6bea 565 ret = check_equiv(s_text_obj.data + i, s_text_exe.data + i, left);
cfd23479 566 if (ret >= 0) {
567 i += ret;
568 continue;
569 }
570
572a6bea 571 printf("%x: %02x vs %02x\n", base + i,
572 s_text_obj.data[i], s_text_exe.data[i]);
cfd23479 573 goto out;
574 }
575
572a6bea 576 // fill removed funcs with 'int3'
2c605b97 577 for (i = 0; i < sym_cnt_obj; i++) {
578 if (strncmp(syms_obj[i].name, "rm_", 3))
579 continue;
580
581 addr = syms_obj[i].addr;
582 end = (i < sym_cnt_obj - 1)
572a6bea 583 ? syms_obj[i + 1].addr : s_text_obj.size;
584 if (addr >= s_text_obj.size || end > s_text_obj.size) {
2c605b97 585 printf("addr OOR: %x-%x '%s'\n", addr, end,
586 syms_obj[i].name);
587 goto out;
588 }
572a6bea 589 fill_int3(s_text_obj.data + addr, end - addr);
590 }
591
592 // remove relocs
593 for (i = 0; i < s_text_obj.reloc_cnt; i++) {
594 addr = s_text_obj.relocs[i].r_vaddr;
a2f78da4 595 sym = s_text_obj.relocs[i].r_symndx;
572a6bea 596 if (addr > s_text_obj.size - 4) {
597 printf("reloc addr OOR: %x\n", addr);
598 goto out;
599 }
a2f78da4 600 if (sym >= raw_sym_cnt_obj) {
601 printf("reloc sym OOR: %d/%ld\n",
602 sym, raw_sym_cnt_obj);
603 goto out;
604 }
605#if 0
606 printf("r %08x -> %08x %s\n", base + addr,
607 raw_syms_obj[sym].addr,
608 raw_syms_obj[sym].name);
609#endif
610 t = (unsigned int *)(s_text_obj.data + addr);
611 if (t[0] == 0xcccccccc
612 || t[-1] == 0xcccccccc) { // jumptab of a func?
613 t[0] = 0xcccccccc;
572a6bea 614 memmove(&s_text_obj.relocs[i],
615 &s_text_obj.relocs[i + 1],
616 (s_text_obj.reloc_cnt - i - 1)
617 * sizeof(s_text_obj.relocs[0]));
618 i--;
619 s_text_obj.reloc_cnt--;
620 }
de50b98b 621#if 0
a2f78da4 622 // note: branches/calls already linked,
623 // so only useful for dd refs
de50b98b 624 // XXX: rm'd because of switch tables
a2f78da4 625 else if (raw_syms_obj[sym].is_text) {
de50b98b 626 unsigned int addr2 = raw_syms_obj[sym].addr;
a2f78da4 627 if (s_text_obj.data[addr2] == 0xcc) {
628 printf("warning: reloc %08x -> %08x "
629 "points to rm'd target '%s'\n",
630 base + addr, base + addr2,
631 raw_syms_obj[sym].name);
632 }
633 }
de50b98b 634#endif
2c605b97 635 }
636
572a6bea 637 // patch .text
638 ret = fseek(f_obj, s_text_obj.sect_fofs, SEEK_SET);
639 my_assert(ret, 0);
640 ret = fwrite(s_text_obj.data, 1, s_text_obj.size, f_obj);
641 my_assert(ret, s_text_obj.size);
642
643 // patch relocs
644 ret = fseek(f_obj, s_text_obj.reloc_fofs, SEEK_SET);
645 my_assert(ret, 0);
646 ret = fwrite(s_text_obj.relocs, sizeof(s_text_obj.relocs[0]),
647 s_text_obj.reloc_cnt, f_obj);
648 my_assert(ret, s_text_obj.reloc_cnt);
649
650 ret = fseek(f_obj, s_text_obj.scnhdr_fofs, SEEK_SET);
651 my_assert(ret, 0);
652 ret = fread(&tmphdr, 1, sizeof(tmphdr), f_obj);
653 my_assert(ret, sizeof(tmphdr));
654
655 tmphdr.s_nreloc = s_text_obj.reloc_cnt;
656
657 ret = fseek(f_obj, s_text_obj.scnhdr_fofs, SEEK_SET);
658 my_assert(ret, 0);
659 ret = fwrite(&tmphdr, 1, sizeof(tmphdr), f_obj);
660 my_assert(ret, sizeof(tmphdr));
2c605b97 661
662 fclose(f_obj);
663 fclose(f_exe);
664
665 retval = 0;
cfd23479 666out:
667 return retval;
668}