2 * elf2flt.c: Convert ELF (or any BFD format) to FLAT binary format
4 * (c) 1999-2002, Greg Ungerer <gerg@snapgear.com>
5 * Created elf2flt from coff2flt (see copyrights below). Added all the
6 * ELF format file handling. Extended relocation support for all of
9 * (c) 2003, H8 support <davidm@snapgear.com>
10 * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
11 * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
12 * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
13 * (c) 2001, zflat support <davidm@snapgear.com>
14 * (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
15 * David McCullough <davidm@snapgear.com>
17 * Now supports PIC with GOT tables. This works by taking a '.elf' file
18 * and a fully linked elf executable (at address 0) and produces a flat
19 * file that can be loaded with some fixups. It still supports the old
20 * style fully relocatable elf format files.
22 * Originally obj-res.c
24 * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
25 * (c) 1998, D. Jeff Dionne
26 * (c) 1998, The Silver Hammer Group Ltd.
27 * (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
29 * This is Free Software, under the GNU Public Licence v2 or greater.
31 * Relocation added March 1997, Kresten Krab Thorup
32 * krab@california.daimi.aau.dk
35 #include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
36 #include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */
37 #include <stdarg.h> /* Allows va_list to exist in the these namespaces */
38 #include <string.h> /* Userland prototypes of the string handling funcs */
40 #include <unistd.h> /* Userland prototypes of the Unix std system calls */
41 #include <fcntl.h> /* Flag value for file handling functions */
44 #include <netinet/in.h> /* Consts and structs defined by the internet system */
46 /* from $(INSTALLDIR)/include */
47 #include <bfd.h> /* Main header file for the BFD library */
49 #if defined(TARGET_h8300)
50 #include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
52 #include <elf.h> /* TARGET_* ELF support for the BFD library */
55 /* from uClinux-x.x.x/include/linux */
56 #include "flat.h" /* Binary flat header description */
63 #if defined(TARGET_m68k)
64 #define ARCH "m68k/coldfire"
65 #elif defined(TARGET_arm)
67 #elif defined(TARGET_sparc)
69 #elif defined(TARGET_v850)
71 #elif defined(TARGET_sh)
73 #elif defined(TARGET_h8300)
75 #elif defined(TARGET_microblaze)
76 #define ARCH "microblaze"
78 #error "Don't know how to support your CPU architecture??"
82 * Define a maximum number of bytes allowed in the offset table.
83 * We'll fail if the table is larger than this.
85 * This limit may be different for platforms other than m68k, but
86 * 8000 entries is a lot, trust me :-) (davidm)
88 #define GOT_LIMIT 32767
95 int verbose = 0; /* extra output when running */
96 int pic_with_got = 0; /* do elf/got processing with PIC code */
97 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
98 int compress = 0; /* 1 = compress everything, 2 = compress data only */
99 int use_resolved = 0; /* If true, get the value of symbol references from */
100 /* the program contents, not from the relocation table. */
101 /* In this case, the input ELF file must be already */
102 /* fully resolved (using the `-q' flag with recent */
103 /* versions of GNU ld will give you a fully resolved */
104 /* output file with relocation entries). */
106 const char *progname, *filename;
112 static char where[200];
115 /* Use exactly one of these: */
116 E_NOFILE = 0, /* "progname: " */
117 E_FILE = 1, /* "filename: " */
118 E_FILELINE = 2, /* "filename:lineno: " */
119 E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */
121 /* Add in any of these with |': */
126 void ewhere (const char *format, ...);
127 void einfo (int type, const char *format, ...);
131 ewhere (const char *format, ...) {
133 va_start (args, format);
134 vsprintf (where, format, args);
140 einfo (int type, const char *format, ...) {
143 switch (type & 0x0f) {
145 fprintf (stderr, "%s: ", progname);
148 fprintf (stderr, "%s: ", filename);
151 ewhere ("%d", lineno);
154 fprintf (stderr, "%s:%s: ", filename, where);
158 if (type & E_WARNING) {
159 fprintf (stderr, "warning: ");
165 va_start (args, format);
166 vfprintf (stderr, format, args);
172 fprintf (stderr, "\n");
177 get_symbols (bfd *abfd, long *num)
180 asymbol **symbol_table;
181 long number_of_symbols;
183 storage_needed = bfd_get_symtab_upper_bound (abfd);
185 if (storage_needed < 0)
188 if (storage_needed == 0)
191 symbol_table = (asymbol **) malloc (storage_needed);
193 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
195 if (number_of_symbols < 0)
198 *num = number_of_symbols;
205 dump_symbols(asymbol **symbol_table, long number_of_symbols)
208 printf("SYMBOL TABLE:\n");
209 for (i=0; i<number_of_symbols; i++) {
210 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
211 symbol_table[i]->value);
220 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
223 for (i=0; i<number_of_symbols; i++) {
224 if (symbol_table[i]->section == sec) {
225 if (!strcmp(symbol_table[i]->name, name)) {
226 return symbol_table[i]->value;
236 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
242 for (i=0; i<number_of_symbols; i++) {
243 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
244 offset = bss_len + comsize;
245 comsize += symbol_table[i]->value;
246 symbol_table[i]->value = offset;
258 int number_of_symbols,
259 unsigned long *n_relocs,
260 unsigned char *text, int text_len, unsigned char *data, int data_len,
263 unsigned long *flat_relocs;
264 asection *a, *sym_section, *r;
265 arelent **relpp, **p, *q;
266 const char *sym_name, *section_name;
267 unsigned char *sectionp;
268 unsigned long pflags;
270 long sym_addr, sym_vma, section_vma;
271 int relsize, relcount;
272 int flat_reloc_count;
273 int sym_reloc_size, rc;
280 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=%x,number_of_symbols=%d"
281 "n_relocs=%x,text=%x,text_len=%d,data=%x,data_len=%d)\n",
282 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
283 text, text_len, data, data_len);
287 dump_symbols(symbols, number_of_symbols);
292 flat_reloc_count = 0;
296 /* Determine how big our offset table is in bytes.
297 * This isn't too difficult as we've terminated the table with -1.
298 * Also note that both the relocatable and absolute versions have this
299 * terminator even though the relocatable one doesn't have the GOT!
302 unsigned long *lp = (unsigned long *)data;
303 /* Should call ntohl(*lp) here but is isn't going to matter */
304 while (*lp != 0xffffffff) lp++;
305 got_size = ((unsigned char *)lp) - data;
307 printf("GOT table contains %d entries (%d bytes)\n",
308 got_size/sizeof(unsigned long), got_size);
310 if (got_size > GOT_LIMIT) {
311 fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
312 got_size, GOT_LIMIT);
318 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
319 section_vma = bfd_section_vma(abs_bfd, a);
322 printf("SECTION: %s [%x]: flags=%x vma=%x\n", a->name, a,
323 a->flags, section_vma);
325 // if (bfd_is_abs_section(a))
327 if (bfd_is_und_section(a))
329 if (bfd_is_com_section(a))
331 // if ((a->flags & SEC_RELOC) == 0)
335 * Only relocate things in the data sections if we are PIC/GOT.
336 * otherwise do text as well
338 if (!pic_with_got && strcmp(".text", a->name) == 0)
340 else if (strcmp(".data", a->name) == 0)
345 /* Now search for the equivalent section in the relocation binary
346 * and use that relocation information to build reloc entries
349 for (r=rel_bfd->sections; r != NULL; r=r->next)
350 if (strcmp(a->name, r->name) == 0)
355 printf(" RELOCS: %s [%x]: flags=%x vma=%x\n", r->name, r,
356 r->flags, bfd_section_vma(abs_bfd, r));
357 if ((r->flags & SEC_RELOC) == 0)
359 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
362 printf("%s(%d): no relocation entries section=%x\n",
363 __FILE__, __LINE__, r->name);
367 symb = get_symbols(rel_bfd, &nsymb);
368 relpp = (arelent **) xmalloc(relsize);
369 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
372 printf("%s(%d): no relocation entries section=%s\n",
373 __FILE__, __LINE__, r->name);
376 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
377 int relocation_needed = 0;
379 #ifdef TARGET_microblaze
380 /* The MICROBLAZE_XX_NONE relocs can be skipped.
381 They represent PC relative branches that the
382 linker has already resolved */
384 switch ((*p)->howto->type)
386 case R_MICROBLAZE_NONE:
387 case R_MICROBLAZE_64_NONE:
390 #endif /* TARGET_microblaze */
393 /* Skip this relocation entirely if possible (we
394 do this early, before doing any other
395 processing on it). */
396 switch ((*p)->howto->type) {
397 #ifdef R_V850_9_PCREL
400 #ifdef R_V850_22_PCREL
401 case R_V850_22_PCREL:
403 #ifdef R_V850_SDA_16_16_OFFSET
404 case R_V850_SDA_16_16_OFFSET:
406 #ifdef R_V850_SDA_15_16_OFFSET
407 case R_V850_SDA_15_16_OFFSET:
409 #ifdef R_V850_ZDA_15_16_OFFSET
410 case R_V850_ZDA_15_16_OFFSET:
412 #ifdef R_V850_TDA_6_8_OFFSET
413 case R_V850_TDA_6_8_OFFSET:
415 #ifdef R_V850_TDA_7_8_OFFSET
416 case R_V850_TDA_7_8_OFFSET:
418 #ifdef R_V850_TDA_7_7_OFFSET
419 case R_V850_TDA_7_7_OFFSET:
421 #ifdef R_V850_TDA_16_16_OFFSET
422 case R_V850_TDA_16_16_OFFSET:
424 #ifdef R_V850_TDA_4_5_OFFSET
425 case R_V850_TDA_4_5_OFFSET:
427 #ifdef R_V850_TDA_4_4_OFFSET
428 case R_V850_TDA_4_4_OFFSET:
430 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
431 case R_V850_SDA_16_16_SPLIT_OFFSET:
433 #ifdef R_V850_CALLT_6_7_OFFSET
434 case R_V850_CALLT_6_7_OFFSET:
436 #ifdef R_V850_CALLT_16_16_OFFSET
437 case R_V850_CALLT_16_16_OFFSET:
439 /* These are relative relocations, which
440 have already been fixed up by the
441 linker at this point, so just ignore
445 #endif /* USE_V850_RELOCS */
448 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
449 sym_name = (*(q->sym_ptr_ptr))->name;
450 sym_section = (*(q->sym_ptr_ptr))->section;
451 section_name=(*(q->sym_ptr_ptr))->section->name;
453 printf("ERROR: undefined relocation entry\n");
457 /* Adjust the address to account for the GOT table which wasn't
458 * present in the relative file link.
461 q->address += got_size;
464 * Fixup offset in the actual section.
467 if ((sym_addr = get_symbol_offset((char *) sym_name,
468 sym_section, symbols, number_of_symbols)) == -1) {
473 /* Use the address of the symbol already in
474 the program text. The alignment of the
475 build host might be stricter, and the
476 endian-ness different, than that of the
477 target, so we have to be careful. */
478 unsigned char *p = sectionp + q->address;
479 if (bfd_big_endian (abs_bfd))
481 (p[0] << 24) + (p[1] << 16)
482 + (p[2] << 8) + p[3];
486 + (p[2] << 16) + (p[3] << 24);
487 relocation_needed = 1;
489 /* Calculate the sym address ourselves. */
490 sym_reloc_size = bfd_get_reloc_size(q->howto);
493 if (sym_reloc_size != 4) {
494 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
495 (*p)->howto->type, sym_reloc_size, sym_name);
502 switch ((*p)->howto->type) {
504 #if defined(TARGET_m68k)
506 relocation_needed = 1;
507 sym_vma = bfd_section_vma(abs_bfd, sym_section);
508 sym_addr += sym_vma + q->addend;
512 sym_addr += sym_vma + q->addend;
513 sym_addr -= q->address;
517 #if defined(TARGET_arm)
519 relocation_needed = 1;
522 "%s vma=0x%x, value=0x%x, address=0x%x "
523 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
525 sym_vma, (*(q->sym_ptr_ptr))->value,
526 q->address, sym_addr,
527 (*p)->howto->rightshift,
528 *((unsigned long *) (sectionp + q->address)));
529 sym_vma = bfd_section_vma(abs_bfd, sym_section);
530 sym_addr += sym_vma + q->addend;
534 /* Should be fine as is */
539 "%s vma=0x%x, value=0x%x, address=0x%x "
540 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
542 sym_vma, (*(q->sym_ptr_ptr))->value,
543 q->address, sym_addr,
544 (*p)->howto->rightshift,
545 *((unsigned long *) (sectionp + q->address)));
548 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
554 relocation_needed = 1;
555 sym_vma = bfd_section_vma(abs_bfd, sym_section);
556 sym_addr += sym_vma + q->addend;
558 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
559 #ifdef R_V850_ZDA_16_16_OFFSET
560 case R_V850_ZDA_16_16_OFFSET:
562 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
563 case R_V850_ZDA_16_16_SPLIT_OFFSET:
565 /* Can't support zero-relocations. */
566 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
567 sym_name, q->addend);
569 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
570 #endif /* TARGET_v850 */
574 if (sym_reloc_size != 4) {
575 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
579 relocation_needed = 1;
580 sym_addr = (*(q->sym_ptr_ptr))->value;
582 sym_vma = bfd_section_vma(abs_bfd, sym_section);
583 sym_addr += sym_vma + q->addend;
584 sym_addr |= (*((unsigned char *)(sectionp+q->address))<<24);
587 if (sym_reloc_size != 4) {
588 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
592 relocation_needed = 1;
593 sym_addr = (*(q->sym_ptr_ptr))->value;
594 sym_vma = bfd_section_vma(abs_bfd, sym_section);
595 sym_addr += sym_vma + q->addend;
598 case R_H8_DIR32A16: /* currently 32, could be made 16 */
599 if (sym_reloc_size != 4) {
600 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
604 relocation_needed = 1;
605 sym_addr = (*(q->sym_ptr_ptr))->value;
606 sym_vma = bfd_section_vma(abs_bfd, sym_section);
607 sym_addr += sym_vma + q->addend;
611 sym_addr = (*(q->sym_ptr_ptr))->value;
612 sym_addr += sym_vma + q->addend;
613 sym_addr -= (q->address + 2);
614 if (bfd_big_endian(abs_bfd))
615 * ((unsigned short *) (sectionp + q->address)) =
616 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
620 sym_addr = (*(q->sym_ptr_ptr))->value;
621 sym_addr += sym_vma + q->addend;
622 sym_addr -= (q->address + 1);
623 * ((unsigned char *) (sectionp + q->address)) = sym_addr;
627 #ifdef TARGET_microblaze
628 case R_MICROBLAZE_64:
629 /* The symbol is split over two consecutive instructions.
630 Flag this to the flat loader by setting the high bit of
631 the relocation symbol. */
633 unsigned char *p = sectionp + q->address;
634 unsigned long offset;
637 /* work out the relocation */
638 sym_vma = bfd_section_vma(abs_bfd, sym_section);
639 /* grab any offset from the text */
640 offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
641 /* Update the address */
642 sym_addr += offset + sym_vma + q->addend;
643 /* Write relocated pointer back */
644 p[2] = (sym_addr >> 24) & 0xff;
645 p[3] = (sym_addr >> 16) & 0xff;
646 p[6] = (sym_addr >> 8) & 0xff;
647 p[7] = sym_addr & 0xff;
649 /* create a new reloc entry */
650 flat_relocs = realloc(flat_relocs,
651 (flat_reloc_count + 1) * sizeof(unsigned long));
652 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
654 relocation_needed = 0;
656 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
657 bfd_section_vma(abs_bfd, sym_section));
659 printf(" RELOC[%d]: offset=%x symbol=%s%s "
660 "section=%s size=%d "
661 "fixup=%x (reloc=0x%x)\n", flat_reloc_count,
662 q->address, sym_name, addstr,
663 section_name, sym_reloc_size,
664 sym_addr, section_vma + q->address);
666 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
667 section_vma + q->address);
671 case R_MICROBLAZE_32:
672 relocation_needed = 1;
673 //sym_addr = (*(q->sym_ptr_ptr))->value;
674 sym_vma = bfd_section_vma(abs_bfd, sym_section);
675 sym_addr += sym_vma + q->addend;
678 case R_MICROBLAZE_64_PCREL:
680 //sym_addr = (*(q->sym_ptr_ptr))->value;
681 sym_addr += sym_vma + q->addend;
682 sym_addr -= (q->address + 4);
683 sym_addr = htonl(sym_addr);
685 * ((unsigned short *) (sectionp + q->address+2)) |= (sym_addr) & 0xFFFF;
687 * ((unsigned short *) (sectionp + q->address+6)) |= (sym_addr >> 16) & 0xFFFF;
688 /* We've done all the work, so continue
689 to next reloc instead of break */
692 #endif /* TARGET_microblaze */
697 relocation_needed = 1;
698 sym_vma = bfd_section_vma(abs_bfd, sym_section);
699 sym_addr += sym_vma + q->addend;
703 sym_addr += sym_vma + q->addend;
704 sym_addr -= q->address;
706 case R_SPARC_WDISP30:
707 sym_addr = (((*(q->sym_ptr_ptr))->value-
708 q->address) >> 2) & 0x3fffffff;
710 ntohl(*((unsigned long *) (sectionp + q->address))) &
715 relocation_needed = 1;
717 sym_vma = bfd_section_vma(abs_bfd, sym_section);
718 sym_addr += sym_vma + q->addend;
720 htonl(* ((unsigned long *) (sectionp + q->address))) &
725 relocation_needed = 1;
727 sym_vma = bfd_section_vma(abs_bfd, sym_section);
728 sym_addr += sym_vma + q->addend;
729 sym_addr &= 0x000003ff;
731 htonl(* ((unsigned long *) (sectionp + q->address))) &
735 #endif /* TARGET_sparc */
739 relocation_needed = 1;
740 sym_vma = bfd_section_vma(abs_bfd, sym_section);
741 sym_addr += sym_vma + q->addend;
745 sym_addr += sym_vma + q->addend;
746 sym_addr -= q->address;
748 #endif /* TARGET_sh */
751 /* missing support for other types of relocs */
752 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
758 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
759 bfd_section_vma(abs_bfd, sym_section));
763 * for full elf relocation we have to write back the
764 * start_code relative value to use.
767 #if defined(TARGET_arm)
776 * horrible nasty hack to support different endianess
778 if (!bfd_big_endian(abs_bfd)) {
790 tmp.l = *((unsigned long *) (sectionp + q->address));
791 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
792 if (((*p)->howto->type != R_ARM_PC24) &&
793 ((*p)->howto->type != R_ARM_PLT32))
794 hl |= (tmp.c[i3] << 24);
795 else if (tmp.c[i2] & 0x80)
796 hl |= 0xff000000; /* sign extend */
798 tmp.c[i0] = hl & 0xff;
799 tmp.c[i1] = (hl >> 8) & 0xff;
800 tmp.c[i2] = (hl >> 16) & 0xff;
801 if (((*p)->howto->type != R_ARM_PC24) &&
802 ((*p)->howto->type != R_ARM_PLT32))
803 tmp.c[i3] = (hl >> 24) & 0xff;
804 if ((*p)->howto->type == R_ARM_ABS32)
805 *((unsigned long *) (sectionp + q->address)) = htonl(hl);
807 *((unsigned long *) (sectionp + q->address)) = tmp.l;
808 #else /* ! TARGET_arm */
809 /* The alignment of the build host might be
810 stricter than that of the target, so be
811 careful. We store in network byte order. */
812 unsigned char *p = sectionp + q->address;
813 p[0] = (sym_addr >> 24) & 0xff;
814 p[1] = (sym_addr >> 16) & 0xff;
815 p[2] = (sym_addr >> 8) & 0xff;
816 p[3] = sym_addr & 0xff;
821 printf(" RELOC[%d]: offset=%x symbol=%s%s "
822 "section=%s size=%d "
823 "fixup=%x (reloc=0x%x)\n", flat_reloc_count,
824 q->address, sym_name, addstr,
825 section_name, sym_reloc_size,
826 sym_addr, section_vma + q->address);
829 * Create relocation entry (PC relative doesn't need this).
831 if (relocation_needed) {
832 flat_relocs = realloc(flat_relocs,
833 (flat_reloc_count + 1) * sizeof(unsigned long));
834 flat_relocs[flat_reloc_count] = pflags |
835 (section_vma + q->address);
838 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
839 section_vma + q->address);
841 relocation_needed = 0;
846 printf("%s(%d): symbol name=%s address=%x section=%s -> RELOC=%x\n",
847 __FILE__, __LINE__, sym_name, q->address, section_name,
848 flat_relocs[flat_reloc_count]);
855 printf("%d bad relocs\n", bad_relocs);
862 *n_relocs = flat_reloc_count;
869 /* shared lib symbols stuff */
872 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
875 for (i=0; i<number_of_symbols; i++) {
876 if (symbol_table[i]->section == sec) {
877 if (!strcmp(symbol_table[i]->name, name)) {
878 return symbol_table[i]->value;
886 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
897 signed short *tab = malloc(32768); /* we don't know how many yet*/
899 asection *text_section = bfd_get_section_by_name (abfd, ".text");
901 if (!(ef = fopen(ename, "r"))) {
902 fprintf (stderr,"Can't open %s\n",ename);
906 fgets(libname, 80, ef);
908 if (number_of_symbols < 0) {
909 fprintf (stderr,"Corrupt symbol table!\n");
913 if ((etext_addr = get_symbol("etext",
916 number_of_symbols)) == -1) {
917 fprintf (stderr,"Can't find the symbol etext\n");
923 buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
925 if ((sym_addr = get_symbol(buf,
928 number_of_symbols)) == -1) {
929 fprintf (stderr,"Can't find the symbol %s\n",buf);
932 tab[++count] = htons(sym_addr - etext_addr);
940 fprintf (stderr,"*** %d symbols not found\n",foobar);
944 strcpy((char *)&tab[++count],libname);
945 tab[0] = htons(count * 2);
946 write(fd, tab, count * 2 + strlen(libname) + 2);
952 static char * program;
954 static void usage(void)
956 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
957 "[-o <output-file>] <elf-file>\n\n"
958 " -v : verbose operation\n"
959 " -r : force load to RAM\n"
960 " -z : compress code/data/relocs\n"
961 " -d : compress data/relocs\n"
962 " -a : use existing symbol references\n"
963 " instead of recalculating from\n"
965 " -p abs-pic-file : GOT/PIC processing with files\n"
966 " -s stacksize : set application stack size\n"
967 " -o output-file : output file name\n\n",
969 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
975 int main(int argc, char *argv[])
978 bfd *rel_bfd, *abs_bfd;
980 char *ofile=NULL, *pfile=NULL;
989 asymbol **symbol_table;
990 long number_of_symbols;
992 unsigned long data_len;
993 unsigned long bss_len;
994 unsigned long text_len;
995 unsigned long reloc_len;
997 unsigned long data_vma;
998 unsigned long bss_vma;
999 unsigned long text_vma;
1003 unsigned long *reloc;
1005 struct flat_hdr hdr;
1016 while ((opt = getopt(argc, argv, "avzdrp:s:o:")) != -1) {
1040 stack = atoi(optarg);
1043 fprintf(stderr, "%s Unknown option\n", argv[0]);
1050 * if neither the -r or -p options was given, default to
1051 * a RAM load as that is the only option that makes sense.
1053 if (!load_to_ram && !pfile)
1056 filename = fname = argv[argc-1];
1058 if (!(rel_bfd = bfd_openr(fname, 0))) {
1059 fprintf(stderr, "Can't open %s\n", fname);
1063 if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1064 fprintf(stderr, "File is not an object file\n");
1071 if (!(abs_bfd = bfd_openr(pfile, 0))) {
1072 fprintf(stderr, "Can't open %s\n", pfile);
1076 if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1077 fprintf(stderr, "File is not an object file\n");
1081 abs_bfd = rel_bfd; /* one file does all */
1084 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1085 fprintf (stderr, "%s: Input file contains no relocation info\n", fname);
1089 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1090 /* `Absolute' file is not absolute, so neither are address
1091 contained therein. */
1093 "%s: `-a' option specified with non-fully-resolved input file\n",
1094 bfd_get_filename (abs_bfd));
1098 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1100 s = bfd_get_section_by_name (abs_bfd, ".text");
1102 text_len = s->_raw_size;
1103 text = malloc(text_len);
1106 printf("TEXT -> vma=%x len=%x\n", text_vma, text_len);
1107 printf(" lma=%x clen=%x oo=%x ap=%x fp=%x\n",
1108 s->lma, s->_cooked_size, s->output_offset,
1109 s->alignment_power, s->filepos);
1112 if (bfd_get_section_contents(abs_bfd,
1116 s->_raw_size) == false) {
1117 fprintf(stderr, "read error section %s\n", s->name);
1121 s = bfd_get_section_by_name (abs_bfd, ".data");
1123 data_len = s->_raw_size;
1124 data = malloc(data_len);
1127 printf("DATA -> vma=%x len=%x\n", data_vma, data_len);
1128 printf(" lma=%x clen=%x oo=%x ap=%x fp=%x\n",
1129 s->lma, s->_cooked_size, s->output_offset,
1130 s->alignment_power, s->filepos);
1132 if ((text_vma + text_len) != data_vma) {
1133 if ((text_vma + text_len) > data_vma) {
1134 printf("ERROR: text=%x overlaps data=%x ?\n", text_len, data_vma);
1138 printf("WARNING: data=%x does not directly follow text=%x\n",
1139 data_vma, text_len);
1140 text_len = data_vma - text_vma;
1143 if (bfd_get_section_contents(abs_bfd,
1147 s->_raw_size) == false) {
1148 fprintf(stderr, "read error section %s\n", s->name);
1152 s = bfd_get_section_by_name (abs_bfd, ".bss");
1153 bss_len = s->_raw_size;
1155 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1158 printf("BSS -> vma=%x len=%x\n", bss_vma, bss_len);
1159 printf(" lma=%x clen=%x oo=%x ap=%x fp=%x\n",
1160 s->lma, s->_cooked_size, s->output_offset,
1161 s->alignment_power, s->filepos);
1164 if ((text_vma + text_len + data_len) != bss_vma) {
1165 if ((text_vma + text_len + data_len) > bss_vma) {
1166 printf("ERROR: text=%x + data=%x overlaps bss=%x ?\n", text_len,
1171 printf("WARNING: bss=%x does not directly follow text=%x + data=%x(%x)\n",
1172 bss_vma, text_len, data_len, text_len + data_len);
1173 data_len = bss_vma - data_vma;
1176 reloc = (unsigned long *) output_relocs (abs_bfd, symbol_table,
1177 number_of_symbols, &reloc_len, text, text_len, data, data_len, rel_bfd);
1180 printf("No relocations in code!\n");
1182 /* Fill in the binflt_flat header */
1183 memcpy(hdr.magic,"bFLT",4);
1184 hdr.rev = htonl(FLAT_VERSION);
1185 hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1186 hdr.data_start = htonl(16 * 4 + text_len);
1187 hdr.data_end = htonl(16 * 4 + text_len + data_len);
1188 hdr.bss_end = htonl(16 * 4 + text_len + data_len + bss_len);
1189 hdr.stack_size = htonl(stack); /* FIXME */
1190 hdr.reloc_start = htonl(16 * 4 + text_len + data_len);
1191 hdr.reloc_count = htonl(reloc_len);
1193 | (load_to_ram ? FLAT_FLAG_RAM : 0)
1194 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1195 | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1197 hdr.build_date = htonl((unsigned long)time(NULL));
1198 bzero(hdr.filler, sizeof(hdr.filler));
1200 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1203 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1204 text_len, data_len, bss_len);
1206 printf(", relocs=0x%04x", reloc_len);
1211 ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1212 strcpy(ofile, fname);
1213 strcat(ofile, ".bflt");
1216 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1217 fprintf (stderr, "Can't open output file %s\n", ofile);
1221 write(fd, &hdr, sizeof(hdr));
1225 * get the compression command ready
1227 sprintf(cmd, "gzip -f -9 >> %s", ofile);
1229 #define START_COMPRESSOR do { \
1230 if (gf) fclose(gf); \
1231 if (!(gf = popen(cmd, "w"))) { \
1232 fprintf(stderr, "Can't run cmd %s\n", cmd); \
1237 gf = fopen(ofile, "a");
1239 fprintf(stderr, "Can't opne file %s for writing\n", ofile); \
1246 fwrite(text, text_len, 1, gf);
1251 fwrite(data, data_len, 1, gf);
1253 fwrite(reloc, reloc_len*4, 1, gf);