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, ktrace <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 */
51 #elif defined(__CYGWIN__)
52 #include "cygwin-elf.h" /* Cygwin uses a local copy */
54 #include <elf.h> /* TARGET_* ELF support for the BFD library */
57 /* from uClinux-x.x.x/include/linux */
58 #include "flat.h" /* Binary flat header description */
65 #if defined(TARGET_m68k)
66 #define ARCH "m68k/coldfire"
67 #elif defined(TARGET_arm)
69 #elif defined(TARGET_sparc)
71 #elif defined(TARGET_v850)
73 #elif defined(TARGET_sh)
75 #elif defined(TARGET_h8300)
77 #elif defined(TARGET_microblaze)
78 #define ARCH "microblaze"
80 #error "Don't know how to support your CPU architecture??"
85 * Define a maximum number of bytes allowed in the offset table.
86 * We'll fail if the table is larger than this.
88 * This limit may be different for platforms other than m68k, but
89 * 8000 entries is a lot, trust me :-) (davidm)
91 #define GOT_LIMIT 32767
93 * we have to mask out the shared library id here and there, this gives
94 * us the real address bits when needed
96 #define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
98 #define real_address_bits(x) (x)
106 int verbose = 0; /* extra output when running */
107 int pic_with_got = 0; /* do elf/got processing with PIC code */
108 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
109 int ktrace = 0; /* instruct loader output kernel trace on load */
110 int compress = 0; /* 1 = compress everything, 2 = compress data only */
111 int use_resolved = 0; /* If true, get the value of symbol references from */
112 /* the program contents, not from the relocation table. */
113 /* In this case, the input ELF file must be already */
114 /* fully resolved (using the `-q' flag with recent */
115 /* versions of GNU ld will give you a fully resolved */
116 /* output file with relocation entries). */
118 const char *progname, *filename;
124 static char where[200];
127 /* Use exactly one of these: */
128 E_NOFILE = 0, /* "progname: " */
129 E_FILE = 1, /* "filename: " */
130 E_FILELINE = 2, /* "filename:lineno: " */
131 E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */
133 /* Add in any of these with |': */
138 void ewhere (const char *format, ...);
139 void einfo (int type, const char *format, ...);
143 ewhere (const char *format, ...) {
145 va_start (args, format);
146 vsprintf (where, format, args);
152 einfo (int type, const char *format, ...) {
155 switch (type & 0x0f) {
157 fprintf (stderr, "%s: ", progname);
160 fprintf (stderr, "%s: ", filename);
163 ewhere ("%d", lineno);
166 fprintf (stderr, "%s:%s: ", filename, where);
170 if (type & E_WARNING) {
171 fprintf (stderr, "warning: ");
177 va_start (args, format);
178 vfprintf (stderr, format, args);
184 fprintf (stderr, "\n");
189 get_symbols (bfd *abfd, long *num)
192 asymbol **symbol_table;
193 long number_of_symbols;
195 storage_needed = bfd_get_symtab_upper_bound (abfd);
197 if (storage_needed < 0)
200 if (storage_needed == 0)
203 symbol_table = (asymbol **) malloc (storage_needed);
205 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
207 if (number_of_symbols < 0)
210 *num = number_of_symbols;
217 dump_symbols(asymbol **symbol_table, long number_of_symbols)
220 printf("SYMBOL TABLE:\n");
221 for (i=0; i<number_of_symbols; i++) {
222 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
223 symbol_table[i]->value);
232 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
235 for (i=0; i<number_of_symbols; i++) {
236 if (symbol_table[i]->section == sec) {
237 if (!strcmp(symbol_table[i]->name, name)) {
238 return symbol_table[i]->value;
248 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
254 for (i=0; i<number_of_symbols; i++) {
255 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
256 offset = bss_len + comsize;
257 comsize += symbol_table[i]->value;
258 symbol_table[i]->value = offset;
270 int number_of_symbols,
271 unsigned long *n_relocs,
272 unsigned char *text, int text_len, unsigned long text_vma,
273 unsigned char *data, int data_len, unsigned long data_vma,
276 unsigned long *flat_relocs;
277 asection *a, *sym_section, *r;
278 arelent **relpp, **p, *q;
279 const char *sym_name, *section_name;
280 unsigned char *sectionp;
281 unsigned long pflags;
283 long sym_addr, sym_vma, section_vma;
284 int relsize, relcount;
285 int flat_reloc_count;
286 int sym_reloc_size, rc;
293 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
294 "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
295 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
296 text, text_len, data, data_len);
300 dump_symbols(symbols, number_of_symbols);
305 flat_reloc_count = 0;
309 /* Determine how big our offset table is in bytes.
310 * This isn't too difficult as we've terminated the table with -1.
311 * Also note that both the relocatable and absolute versions have this
312 * terminator even though the relocatable one doesn't have the GOT!
315 unsigned long *lp = (unsigned long *)data;
316 /* Should call ntohl(*lp) here but is isn't going to matter */
317 while (*lp != 0xffffffff) lp++;
318 got_size = ((unsigned char *)lp) - data;
320 printf("GOT table contains %d entries (%d bytes)\n",
321 got_size/sizeof(unsigned long), got_size);
323 if (got_size > GOT_LIMIT) {
324 fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
325 got_size, GOT_LIMIT);
331 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
332 section_vma = bfd_section_vma(abs_bfd, a);
335 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
336 a->flags, section_vma);
338 // if (bfd_is_abs_section(a))
340 if (bfd_is_und_section(a))
342 if (bfd_is_com_section(a))
344 // if ((a->flags & SEC_RELOC) == 0)
348 * Only relocate things in the data sections if we are PIC/GOT.
349 * otherwise do text as well
351 if (!pic_with_got && (a->flags & SEC_CODE))
352 sectionp = text + (a->vma - text_vma);
353 else if (a->flags & SEC_DATA)
354 sectionp = data + (a->vma - data_vma);
358 /* Now search for the equivalent section in the relocation binary
359 * and use that relocation information to build reloc entries
362 for (r=rel_bfd->sections; r != NULL; r=r->next)
363 if (strcmp(a->name, r->name) == 0)
368 printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
369 r->flags, bfd_section_vma(abs_bfd, r));
370 if ((r->flags & SEC_RELOC) == 0)
372 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
375 printf("%s(%d): no relocation entries section=0x%x\n",
376 __FILE__, __LINE__, r->name);
380 symb = get_symbols(rel_bfd, &nsymb);
381 relpp = (arelent **) xmalloc(relsize);
382 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
385 printf("%s(%d): no relocation entries section=%s\n",
386 __FILE__, __LINE__, r->name);
389 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
390 unsigned char *r_mem;
391 int relocation_needed = 0;
393 #ifdef TARGET_microblaze
394 /* The MICROBLAZE_XX_NONE relocs can be skipped.
395 They represent PC relative branches that the
396 linker has already resolved */
398 switch ((*p)->howto->type)
400 case R_MICROBLAZE_NONE:
401 case R_MICROBLAZE_64_NONE:
404 #endif /* TARGET_microblaze */
407 /* Skip this relocation entirely if possible (we
408 do this early, before doing any other
409 processing on it). */
410 switch ((*p)->howto->type) {
411 #ifdef R_V850_9_PCREL
414 #ifdef R_V850_22_PCREL
415 case R_V850_22_PCREL:
417 #ifdef R_V850_SDA_16_16_OFFSET
418 case R_V850_SDA_16_16_OFFSET:
420 #ifdef R_V850_SDA_15_16_OFFSET
421 case R_V850_SDA_15_16_OFFSET:
423 #ifdef R_V850_ZDA_15_16_OFFSET
424 case R_V850_ZDA_15_16_OFFSET:
426 #ifdef R_V850_TDA_6_8_OFFSET
427 case R_V850_TDA_6_8_OFFSET:
429 #ifdef R_V850_TDA_7_8_OFFSET
430 case R_V850_TDA_7_8_OFFSET:
432 #ifdef R_V850_TDA_7_7_OFFSET
433 case R_V850_TDA_7_7_OFFSET:
435 #ifdef R_V850_TDA_16_16_OFFSET
436 case R_V850_TDA_16_16_OFFSET:
438 #ifdef R_V850_TDA_4_5_OFFSET
439 case R_V850_TDA_4_5_OFFSET:
441 #ifdef R_V850_TDA_4_4_OFFSET
442 case R_V850_TDA_4_4_OFFSET:
444 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
445 case R_V850_SDA_16_16_SPLIT_OFFSET:
447 #ifdef R_V850_CALLT_6_7_OFFSET
448 case R_V850_CALLT_6_7_OFFSET:
450 #ifdef R_V850_CALLT_16_16_OFFSET
451 case R_V850_CALLT_16_16_OFFSET:
453 /* These are relative relocations, which
454 have already been fixed up by the
455 linker at this point, so just ignore
459 #endif /* USE_V850_RELOCS */
462 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
463 sym_name = (*(q->sym_ptr_ptr))->name;
464 sym_section = (*(q->sym_ptr_ptr))->section;
465 section_name=(*(q->sym_ptr_ptr))->section->name;
467 printf("ERROR: undefined relocation entry\n");
471 /* Adjust the address to account for the GOT table which wasn't
472 * present in the relative file link.
475 q->address += got_size;
477 /* A pointer to what's being relocated, used often
479 r_mem = sectionp + q->address;
482 * Fixup offset in the actual section.
485 if ((sym_addr = get_symbol_offset((char *) sym_name,
486 sym_section, symbols, number_of_symbols)) == -1) {
491 /* Use the address of the symbol already in
492 the program text. How this is handled may
493 still depend on the particular relocation
495 switch (q->howto->type) {
499 /* We specially handle adjacent
500 HI16_S/ZDA_15_16_OFFSET and
501 HI16_S/LO16 pairs that reference the
502 same address (these are usually
503 movhi/ld and movhi/movea pairs,
506 r2_type = R_V850_NONE;
508 r2_type = p[1]->howto->type;
509 if ((r2_type == R_V850_ZDA_15_16_OFFSET
510 || r2_type == R_V850_LO16)
511 && (p[0]->sym_ptr_ptr
512 == p[1]->sym_ptr_ptr)
513 && (p[0]->addend == p[1]->addend))
515 relocation_needed = 1;
518 case R_V850_ZDA_15_16_OFFSET:
526 /* We don't really need the
527 actual value -- the bits
528 produced by the linker are
529 what we want in the final
530 flat file -- but get it
534 unsigned char *r2_mem =
542 /* Sign extend LO. */
546 /* Maybe ignore the LSB
550 if (r2_type != R_V850_LO16)
558 goto bad_v850_reloc_err;
562 /* See if this is actually the
563 2nd half of a pair. */
565 && (p[-1]->howto->type
567 && (p[-1]->sym_ptr_ptr
568 == p[0]->sym_ptr_ptr)
569 && (p[-1]->addend == p[0]->addend))
570 break; /* not an error */
572 goto bad_v850_reloc_err;
576 printf("ERROR: reloc type %s unsupported in this context\n",
580 #endif /* TARGET_V850 */
583 /* The default is to assume that the
584 relocation is relative and has
585 already been fixed up by the
586 linker (perhaps we ought to make
587 give an error by default, and
588 require `safe' relocations to be
589 enumberated explicitly?). */
590 if (bfd_big_endian (abs_bfd))
602 relocation_needed = 1;
605 /* Calculate the sym address ourselves. */
606 sym_reloc_size = bfd_get_reloc_size(q->howto);
609 if (sym_reloc_size != 4) {
610 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
611 (*p)->howto->type, sym_reloc_size, sym_name);
618 switch ((*p)->howto->type) {
620 #if defined(TARGET_m68k)
622 relocation_needed = 1;
623 sym_vma = bfd_section_vma(abs_bfd, sym_section);
624 sym_addr += sym_vma + q->addend;
628 sym_addr += sym_vma + q->addend;
629 sym_addr -= q->address;
633 #if defined(TARGET_arm)
635 relocation_needed = 1;
638 "%s vma=0x%x, value=0x%x, address=0x%x "
639 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
641 sym_vma, (*(q->sym_ptr_ptr))->value,
642 q->address, sym_addr,
643 (*p)->howto->rightshift,
644 *(unsigned long *)r_mem);
645 sym_vma = bfd_section_vma(abs_bfd, sym_section);
646 sym_addr += sym_vma + q->addend;
650 /* Should be fine as is */
655 "%s vma=0x%x, value=0x%x, address=0x%x "
656 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
658 sym_vma, (*(q->sym_ptr_ptr))->value,
659 q->address, sym_addr,
660 (*p)->howto->rightshift,
661 *(unsigned long *)r_mem);
664 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
670 relocation_needed = 1;
671 sym_vma = bfd_section_vma(abs_bfd, sym_section);
672 sym_addr += sym_vma + q->addend;
674 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
675 #ifdef R_V850_ZDA_16_16_OFFSET
676 case R_V850_ZDA_16_16_OFFSET:
678 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
679 case R_V850_ZDA_16_16_SPLIT_OFFSET:
681 /* Can't support zero-relocations. */
682 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
683 sym_name, q->addend);
685 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
686 #endif /* TARGET_v850 */
690 if (sym_reloc_size != 4) {
691 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
695 relocation_needed = 1;
696 sym_addr = (*(q->sym_ptr_ptr))->value;
698 r_mem -= 1; /* tracks q->address */
699 sym_vma = bfd_section_vma(abs_bfd, sym_section);
700 sym_addr += sym_vma + q->addend;
701 sym_addr |= (*(unsigned char *)r_mem<<24);
704 if (sym_reloc_size != 4) {
705 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
709 relocation_needed = 1;
710 sym_addr = (*(q->sym_ptr_ptr))->value;
711 sym_vma = bfd_section_vma(abs_bfd, sym_section);
712 sym_addr += sym_vma + q->addend;
715 case R_H8_DIR32A16: /* currently 32, could be made 16 */
716 if (sym_reloc_size != 4) {
717 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
721 relocation_needed = 1;
722 sym_addr = (*(q->sym_ptr_ptr))->value;
723 sym_vma = bfd_section_vma(abs_bfd, sym_section);
724 sym_addr += sym_vma + q->addend;
728 sym_addr = (*(q->sym_ptr_ptr))->value;
729 sym_addr += sym_vma + q->addend;
730 sym_addr -= (q->address + 2);
731 if (bfd_big_endian(abs_bfd))
732 *(unsigned short *)r_mem =
733 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
737 sym_addr = (*(q->sym_ptr_ptr))->value;
738 sym_addr += sym_vma + q->addend;
739 sym_addr -= (q->address + 1);
740 *(unsigned char *)r_mem = sym_addr;
744 #ifdef TARGET_microblaze
745 case R_MICROBLAZE_64:
746 /* The symbol is split over two consecutive instructions.
747 Flag this to the flat loader by setting the high bit of
748 the relocation symbol. */
750 unsigned char *p = r_mem;
751 unsigned long offset;
754 /* work out the relocation */
755 sym_vma = bfd_section_vma(abs_bfd, sym_section);
756 /* grab any offset from the text */
757 offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
758 /* Update the address */
759 sym_addr += offset + sym_vma + q->addend;
760 /* Write relocated pointer back */
761 p[2] = (sym_addr >> 24) & 0xff;
762 p[3] = (sym_addr >> 16) & 0xff;
763 p[6] = (sym_addr >> 8) & 0xff;
764 p[7] = sym_addr & 0xff;
766 /* create a new reloc entry */
767 flat_relocs = realloc(flat_relocs,
768 (flat_reloc_count + 1) * sizeof(unsigned long));
769 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
771 relocation_needed = 0;
773 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
774 bfd_section_vma(abs_bfd, sym_section));
776 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
777 "section=%s size=%d "
778 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
779 q->address, sym_name, addstr,
780 section_name, sym_reloc_size,
781 sym_addr, section_vma + q->address);
783 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
784 section_vma + q->address);
788 case R_MICROBLAZE_32:
790 unsigned char *p = r_mem;
791 unsigned long offset;
793 /* grab any offset from the text */
794 offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
795 //sym_addr = (*(q->sym_ptr_ptr))->value;
796 sym_vma = bfd_section_vma(abs_bfd, sym_section);
797 sym_addr += offset + sym_vma + q->addend;
799 relocation_needed = 1;
802 case R_MICROBLAZE_64_PCREL:
804 //sym_addr = (*(q->sym_ptr_ptr))->value;
805 sym_addr += sym_vma + q->addend;
806 sym_addr -= (q->address + 4);
807 sym_addr = htonl(sym_addr);
809 * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
811 * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
812 /* We've done all the work, so continue
813 to next reloc instead of break */
816 #endif /* TARGET_microblaze */
821 relocation_needed = 1;
822 sym_vma = bfd_section_vma(abs_bfd, sym_section);
823 sym_addr += sym_vma + q->addend;
827 sym_addr += sym_vma + q->addend;
828 sym_addr -= q->address;
830 case R_SPARC_WDISP30:
831 sym_addr = (((*(q->sym_ptr_ptr))->value-
832 q->address) >> 2) & 0x3fffffff;
834 ntohl(*(unsigned long *)r_mem)
839 relocation_needed = 1;
841 sym_vma = bfd_section_vma(abs_bfd, sym_section);
842 sym_addr += sym_vma + q->addend;
844 htonl(*(unsigned long *)r_mem)
849 relocation_needed = 1;
851 sym_vma = bfd_section_vma(abs_bfd, sym_section);
852 sym_addr += sym_vma + q->addend;
853 sym_addr &= 0x000003ff;
855 htonl(*(unsigned long *)r_mem)
859 #endif /* TARGET_sparc */
863 relocation_needed = 1;
864 sym_vma = bfd_section_vma(abs_bfd, sym_section);
865 sym_addr += sym_vma + q->addend;
869 sym_addr += sym_vma + q->addend;
870 sym_addr -= q->address;
872 #endif /* TARGET_sh */
875 /* missing support for other types of relocs */
876 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
882 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
883 bfd_section_vma(abs_bfd, sym_section));
887 * for full elf relocation we have to write back the
888 * start_code relative value to use.
891 #if defined(TARGET_arm)
900 * horrible nasty hack to support different endianess
902 if (!bfd_big_endian(abs_bfd)) {
914 tmp.l = *(unsigned long *)r_mem;
915 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
916 if (((*p)->howto->type != R_ARM_PC24) &&
917 ((*p)->howto->type != R_ARM_PLT32))
918 hl |= (tmp.c[i3] << 24);
919 else if (tmp.c[i2] & 0x80)
920 hl |= 0xff000000; /* sign extend */
922 tmp.c[i0] = hl & 0xff;
923 tmp.c[i1] = (hl >> 8) & 0xff;
924 tmp.c[i2] = (hl >> 16) & 0xff;
925 if (((*p)->howto->type != R_ARM_PC24) &&
926 ((*p)->howto->type != R_ARM_PLT32))
927 tmp.c[i3] = (hl >> 24) & 0xff;
928 if ((*p)->howto->type == R_ARM_ABS32)
929 *(unsigned long *)r_mem = htonl(hl);
931 *(unsigned long *)r_mem = tmp.l;
933 #else /* ! TARGET_arm */
935 switch (q->howto->type) {
940 /* Do nothing -- for cases we handle,
941 the bits produced by the linker are
942 what we want in the final flat file
943 (and other cases are errors). Note
944 that unlike most relocated values,
945 it is stored in little-endian order,
946 but this is necessary to avoid
947 trashing the low-bit, and the float
948 loaders knows about it. */
950 #endif /* TARGET_V850 */
952 /* The alignment of the build host
953 might be stricter than that of the
954 target, so be careful. We store in
955 network byte order. */
956 r_mem[0] = (sym_addr >> 24) & 0xff;
957 r_mem[1] = (sym_addr >> 16) & 0xff;
958 r_mem[2] = (sym_addr >> 8) & 0xff;
959 r_mem[3] = sym_addr & 0xff;
961 #endif /* !TARGET_arm */
965 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
966 "section=%s size=%d "
967 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
968 q->address, sym_name, addstr,
969 section_name, sym_reloc_size,
970 sym_addr, section_vma + q->address);
973 * Create relocation entry (PC relative doesn't need this).
975 if (relocation_needed) {
976 flat_relocs = realloc(flat_relocs,
977 (flat_reloc_count + 1) * sizeof(unsigned long));
978 flat_relocs[flat_reloc_count] = pflags |
979 (section_vma + q->address);
982 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
983 section_vma + q->address);
985 relocation_needed = 0;
990 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
991 __FILE__, __LINE__, sym_name, q->address, section_name,
992 flat_relocs[flat_reloc_count]);
999 printf("%d bad relocs\n", bad_relocs);
1006 *n_relocs = flat_reloc_count;
1013 /* shared lib symbols stuff */
1016 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
1019 for (i=0; i<number_of_symbols; i++) {
1020 if (symbol_table[i]->section == sec) {
1021 if (!strcmp(symbol_table[i]->name, name)) {
1022 return symbol_table[i]->value;
1030 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
1041 signed short *tab = malloc(32768); /* we don't know how many yet*/
1043 asection *text_section = bfd_get_section_by_name (abfd, ".text");
1045 if (!(ef = fopen(ename, "r"))) {
1046 fprintf (stderr,"Can't open %s\n",ename);
1050 fgets(libname, 80, ef);
1052 if (number_of_symbols < 0) {
1053 fprintf (stderr,"Corrupt symbol table!\n");
1057 if ((etext_addr = get_symbol("etext",
1060 number_of_symbols)) == -1) {
1061 fprintf (stderr,"Can't find the symbol etext\n");
1067 buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
1069 if ((sym_addr = get_symbol(buf,
1072 number_of_symbols)) == -1) {
1073 fprintf (stderr,"Can't find the symbol %s\n",buf);
1076 tab[++count] = htons(sym_addr - etext_addr);
1084 fprintf (stderr,"*** %d symbols not found\n",foobar);
1088 strcpy((char *)&tab[++count],libname);
1089 tab[0] = htons(count * 2);
1090 write(fd, tab, count * 2 + strlen(libname) + 2);
1096 static char * program;
1098 static void usage(void)
1100 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1101 "[-o <output-file>] <elf-file>\n\n"
1102 " -v : verbose operation\n"
1103 " -r : force load to RAM\n"
1104 " -k : enable kernel trace on load (for debug)\n"
1105 " -z : compress code/data/relocs\n"
1106 " -d : compress data/relocs\n"
1107 " -a : use existing symbol references\n"
1108 " instead of recalculating from\n"
1109 " relocation info\n"
1110 " -R reloc-file : read relocations from a separate file\n"
1111 " -p abs-pic-file : GOT/PIC processing with files\n"
1112 " -s stacksize : set application stack size\n"
1113 " -o output-file : output file name\n\n",
1115 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1120 /* Write NUM zeroes to STREAM. */
1121 static void write_zeroes (unsigned long num, FILE *stream)
1125 /* It'd be nice if we could just use fseek, but that doesn't seem to
1126 work for stdio output files. */
1127 bzero(zeroes, 1024);
1128 while (num > sizeof(zeroes)) {
1129 fwrite(zeroes, sizeof(zeroes), 1, stream);
1130 num -= sizeof(zeroes);
1133 fwrite(zeroes, num, 1, stream);
1138 int main(int argc, char *argv[])
1141 bfd *rel_bfd, *abs_bfd;
1143 char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1152 asymbol **symbol_table;
1153 long number_of_symbols;
1155 unsigned long data_len = 0;
1156 unsigned long bss_len = 0;
1157 unsigned long text_len = 0;
1158 unsigned long reloc_len;
1160 unsigned long data_vma = ~0;
1161 unsigned long bss_vma = ~0;
1162 unsigned long text_vma = ~0;
1164 unsigned long text_offs;
1168 unsigned long *reloc;
1170 struct flat_hdr hdr;
1181 while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1208 stack = atoi(optarg);
1214 fprintf(stderr, "%s Unknown option\n", argv[0]);
1221 * if neither the -r or -p options was given, default to
1222 * a RAM load as that is the only option that makes sense.
1224 if (!load_to_ram && !pfile)
1227 filename = fname = argv[argc-1];
1238 if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1239 fprintf(stderr, "Can't open %s\n", rel_file);
1243 if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1244 fprintf(stderr, "File is not an object file\n");
1248 if (abs_file == rel_file)
1249 abs_bfd = rel_bfd; /* one file does all */
1251 if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1252 fprintf(stderr, "Can't open %s\n", abs_file);
1256 if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1257 fprintf(stderr, "File is not an object file\n");
1262 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1263 fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1267 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1268 /* `Absolute' file is not absolute, so neither are address
1269 contained therein. */
1271 "%s: `-a' option specified with non-fully-resolved input file\n",
1272 bfd_get_filename (abs_bfd));
1276 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1278 /* Group output sections into text, data, and bss, and calc their sizes. */
1279 for (s = abs_bfd->sections; s != NULL; s = s->next) {
1280 unsigned long *vma, *len;
1282 if (s->flags & SEC_CODE) {
1285 } else if (s->flags & SEC_DATA) {
1288 } else if (s->flags & SEC_ALLOC) {
1294 if (s->vma < *vma) {
1296 *len += s->vma - *vma;
1298 *len = s->_raw_size;
1300 } else if (s->vma + s->_raw_size > *vma + *len)
1301 *len = s->vma + s->_raw_size - *vma;
1304 if (text_len == 0) {
1305 fprintf (stderr, "%s: no .text section", abs_file);
1309 text = malloc(text_len);
1312 printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1314 /* Read in all text sections. */
1315 for (s = abs_bfd->sections; s != NULL; s = s->next)
1316 if (s->flags & SEC_CODE)
1317 if (!bfd_get_section_contents(abs_bfd, s,
1318 text + (s->vma - text_vma), 0,
1321 fprintf(stderr, "read error section %s\n", s->name);
1325 if (data_len == 0) {
1326 fprintf (stderr, "%s: no .data section", abs_file);
1329 data = malloc(data_len);
1332 printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1334 if ((text_vma + text_len) != data_vma) {
1335 if ((text_vma + text_len) > data_vma) {
1336 printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1340 printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1341 data_vma, text_len);
1342 text_len = data_vma - text_vma;
1345 /* Read in all data sections. */
1346 for (s = abs_bfd->sections; s != NULL; s = s->next)
1347 if (s->flags & SEC_DATA)
1348 if (!bfd_get_section_contents(abs_bfd, s,
1349 data + (s->vma - data_vma), 0,
1352 fprintf(stderr, "read error section %s\n", s->name);
1356 /* Put common symbols in bss. */
1357 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1360 printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1362 if ((data_vma + data_len) != bss_vma) {
1363 if ((data_vma + data_len) > bss_vma) {
1364 printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1369 printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1370 bss_vma, text_len, data_len, text_len + data_len);
1371 data_len = bss_vma - data_vma;
1374 reloc = (unsigned long *)
1375 output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1376 text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1379 printf("No relocations in code!\n");
1381 text_offs = real_address_bits(text_vma);
1383 /* Fill in the binflt_flat header */
1384 memcpy(hdr.magic,"bFLT",4);
1385 hdr.rev = htonl(FLAT_VERSION);
1386 hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1387 hdr.data_start = htonl(16 * 4 + text_offs + text_len);
1388 hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len);
1389 hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1390 hdr.stack_size = htonl(stack); /* FIXME */
1391 hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1392 hdr.reloc_count = htonl(reloc_len);
1394 | (load_to_ram ? FLAT_FLAG_RAM : 0)
1395 | (ktrace ? FLAT_FLAG_KTRACE : 0)
1396 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1397 | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1399 hdr.build_date = htonl((unsigned long)time(NULL));
1400 bzero(hdr.filler, sizeof(hdr.filler));
1402 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1405 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1406 text_len, data_len, bss_len);
1408 printf(", relocs=0x%04x", reloc_len);
1413 ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1414 strcpy(ofile, fname);
1415 strcat(ofile, ".bflt");
1418 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1419 fprintf (stderr, "Can't open output file %s\n", ofile);
1423 write(fd, &hdr, sizeof(hdr));
1427 * get the compression command ready
1429 sprintf(cmd, "gzip -f -9 >> %s", ofile);
1431 #define START_COMPRESSOR do { \
1432 if (gf) fclose(gf); \
1433 if (!(gf = popen(cmd, "w"))) { \
1434 fprintf(stderr, "Can't run cmd %s\n", cmd); \
1439 gf = fopen(ofile, "a");
1441 fprintf(stderr, "Can't opne file %s for writing\n", ofile); \
1448 /* Fill in any hole at the beginning of the text segment. */
1450 printf("ZERO before text len=0x%x\n", text_offs);
1451 write_zeroes(text_offs, gf);
1453 /* Write the text segment. */
1454 fwrite(text, text_len, 1, gf);
1459 /* Write the data segment. */
1460 fwrite(data, data_len, 1, gf);
1463 fwrite(reloc, reloc_len * 4, 1, gf);