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) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
11 * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
12 * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
13 * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
14 * (c) 2001, zflat support <davidm@snapgear.com>
15 * (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
16 * David McCullough <davidm@snapgear.com>
18 * Now supports PIC with GOT tables. This works by taking a '.elf' file
19 * and a fully linked elf executable (at address 0) and produces a flat
20 * file that can be loaded with some fixups. It still supports the old
21 * style fully relocatable elf format files.
23 * Originally obj-res.c
25 * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
26 * (c) 1998, D. Jeff Dionne
27 * (c) 1998, The Silver Hammer Group Ltd.
28 * (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
30 * This is Free Software, under the GNU Public Licence v2 or greater.
32 * Relocation added March 1997, Kresten Krab Thorup
33 * krab@california.daimi.aau.dk
36 #include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
37 #include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */
38 #include <stdarg.h> /* Allows va_list to exist in the these namespaces */
39 #include <string.h> /* Userland prototypes of the string handling funcs */
41 #include <unistd.h> /* Userland prototypes of the Unix std system calls */
42 #include <fcntl.h> /* Flag value for file handling functions */
45 #include <netinet/in.h> /* Consts and structs defined by the internet system */
50 /* from $(INSTALLDIR)/include */
51 #include <bfd.h> /* Main header file for the BFD library */
53 #if defined(TARGET_h8300)
54 #include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
55 #elif defined(__CYGWIN__)
56 #include "cygwin-elf.h" /* Cygwin uses a local copy */
57 #elif defined(TARGET_microblaze)
58 #include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
60 #include <elf.h> /* TARGET_* ELF support for the BFD library */
63 /* from uClinux-x.x.x/include/linux */
64 #include "flat.h" /* Binary flat header description */
74 #if defined(TARGET_m68k)
75 #define ARCH "m68k/coldfire"
76 #elif defined(TARGET_arm)
78 #elif defined(TARGET_sparc)
80 #elif defined(TARGET_v850)
82 #elif defined(TARGET_sh)
84 #elif defined(TARGET_h8300)
86 #elif defined(TARGET_microblaze)
87 #define ARCH "microblaze"
88 #elif defined(TARGET_e1)
89 #define ARCH "e1-coff"
90 #elif defined(TARGET_bfin)
93 #error "Don't know how to support your CPU architecture??"
96 #if defined(TARGET_m68k) || defined(TARGET_h8300) || defined(TARGET_bfin)
98 * Define a maximum number of bytes allowed in the offset table.
99 * We'll fail if the table is larger than this.
101 * This limit may be different for platforms other than m68k, but
102 * 8000 entries is a lot, trust me :-) (davidm)
104 #define GOT_LIMIT 32767
106 * we have to mask out the shared library id here and there, this gives
107 * us the real address bits when needed
109 #define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
111 #define real_address_bits(x) (x)
119 int verbose = 0; /* extra output when running */
120 int pic_with_got = 0; /* do elf/got processing with PIC code */
121 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
122 int ktrace = 0; /* instruct loader output kernel trace on load */
123 int compress = 0; /* 1 = compress everything, 2 = compress data only */
124 int use_resolved = 0; /* If true, get the value of symbol references from */
125 /* the program contents, not from the relocation table. */
126 /* In this case, the input ELF file must be already */
127 /* fully resolved (using the `-q' flag with recent */
128 /* versions of GNU ld will give you a fully resolved */
129 /* output file with relocation entries). */
131 const char *progname, *filename;
137 static char where[200];
140 /* Use exactly one of these: */
141 E_NOFILE = 0, /* "progname: " */
142 E_FILE = 1, /* "filename: " */
143 E_FILELINE = 2, /* "filename:lineno: " */
144 E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */
146 /* Add in any of these with |': */
151 void ewhere (const char *format, ...);
152 void einfo (int type, const char *format, ...);
156 ewhere (const char *format, ...) {
158 va_start (args, format);
159 vsprintf (where, format, args);
165 einfo (int type, const char *format, ...) {
168 switch (type & 0x0f) {
170 fprintf (stderr, "%s: ", progname);
173 fprintf (stderr, "%s: ", filename);
176 ewhere ("%d", lineno);
179 fprintf (stderr, "%s:%s: ", filename, where);
183 if (type & E_WARNING) {
184 fprintf (stderr, "warning: ");
190 va_start (args, format);
191 vfprintf (stderr, format, args);
197 fprintf (stderr, "\n");
202 get_symbols (bfd *abfd, long *num)
205 asymbol **symbol_table;
206 long number_of_symbols;
208 storage_needed = bfd_get_symtab_upper_bound (abfd);
210 if (storage_needed < 0)
213 if (storage_needed == 0)
216 symbol_table = (asymbol **) malloc (storage_needed);
218 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
220 if (number_of_symbols < 0)
223 *num = number_of_symbols;
230 dump_symbols(asymbol **symbol_table, long number_of_symbols)
233 printf("SYMBOL TABLE:\n");
234 for (i=0; i<number_of_symbols; i++) {
235 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
236 symbol_table[i]->value);
245 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
248 for (i=0; i<number_of_symbols; i++) {
249 if (symbol_table[i]->section == sec) {
250 if (!strcmp(symbol_table[i]->name, name)) {
251 return symbol_table[i]->value;
261 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
267 for (i=0; i<number_of_symbols; i++) {
268 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
269 offset = bss_len + comsize;
270 comsize += symbol_table[i]->value;
271 symbol_table[i]->value = offset;
283 int number_of_symbols,
284 unsigned long *n_relocs,
285 unsigned char *text, int text_len, unsigned long text_vma,
286 unsigned char *data, int data_len, unsigned long data_vma,
289 uint32_t *flat_relocs;
290 asection *a, *sym_section, *r;
291 arelent **relpp, **p, *q;
292 const char *sym_name, *section_name;
293 unsigned char *sectionp;
294 unsigned long pflags;
296 long sym_addr, sym_vma, section_vma;
297 int relsize, relcount;
298 int flat_reloc_count;
299 int sym_reloc_size, rc;
306 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
307 "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
308 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
309 text, text_len, data, data_len);
313 dump_symbols(symbols, number_of_symbols);
318 flat_reloc_count = 0;
322 /* Determine how big our offset table is in bytes.
323 * This isn't too difficult as we've terminated the table with -1.
324 * Also note that both the relocatable and absolute versions have this
325 * terminator even though the relocatable one doesn't have the GOT!
328 unsigned long *lp = (unsigned long *)data;
329 /* Should call ntohl(*lp) here but is isn't going to matter */
330 while (*lp != 0xffffffff) lp++;
331 got_size = ((unsigned char *)lp) - data;
333 printf("GOT table contains %d entries (%d bytes)\n",
334 got_size/sizeof(unsigned long), got_size);
336 if (got_size > GOT_LIMIT) {
337 fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
338 got_size, GOT_LIMIT);
344 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
345 section_vma = bfd_section_vma(abs_bfd, a);
348 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
349 a->flags, section_vma);
351 // if (bfd_is_abs_section(a))
353 if (bfd_is_und_section(a))
355 if (bfd_is_com_section(a))
357 // if ((a->flags & SEC_RELOC) == 0)
361 * Only relocate things in the data sections if we are PIC/GOT.
362 * otherwise do text as well
364 if (!pic_with_got && (a->flags & SEC_CODE))
365 sectionp = text + (a->vma - text_vma);
366 else if (a->flags & SEC_DATA)
367 sectionp = data + (a->vma - data_vma);
371 /* Now search for the equivalent section in the relocation binary
372 * and use that relocation information to build reloc entries
375 for (r=rel_bfd->sections; r != NULL; r=r->next)
376 if (strcmp(a->name, r->name) == 0)
381 printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
382 r->flags, bfd_section_vma(abs_bfd, r));
383 if ((r->flags & SEC_RELOC) == 0)
385 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
388 printf("%s(%d): no relocation entries section=0x%x\n",
389 __FILE__, __LINE__, r->name);
393 symb = get_symbols(rel_bfd, &nsymb);
394 relpp = (arelent **) xmalloc(relsize);
395 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
398 printf("%s(%d): no relocation entries section=%s\n",
399 __FILE__, __LINE__, r->name);
402 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
403 unsigned char *r_mem;
404 int relocation_needed = 0;
406 #ifdef TARGET_microblaze
407 /* The MICROBLAZE_XX_NONE relocs can be skipped.
408 They represent PC relative branches that the
409 linker has already resolved */
411 switch ((*p)->howto->type)
413 case R_MICROBLAZE_NONE:
414 case R_MICROBLAZE_64_NONE:
417 #endif /* TARGET_microblaze */
420 /* Skip this relocation entirely if possible (we
421 do this early, before doing any other
422 processing on it). */
423 switch ((*p)->howto->type) {
424 #ifdef R_V850_9_PCREL
427 #ifdef R_V850_22_PCREL
428 case R_V850_22_PCREL:
430 #ifdef R_V850_SDA_16_16_OFFSET
431 case R_V850_SDA_16_16_OFFSET:
433 #ifdef R_V850_SDA_15_16_OFFSET
434 case R_V850_SDA_15_16_OFFSET:
436 #ifdef R_V850_ZDA_15_16_OFFSET
437 case R_V850_ZDA_15_16_OFFSET:
439 #ifdef R_V850_TDA_6_8_OFFSET
440 case R_V850_TDA_6_8_OFFSET:
442 #ifdef R_V850_TDA_7_8_OFFSET
443 case R_V850_TDA_7_8_OFFSET:
445 #ifdef R_V850_TDA_7_7_OFFSET
446 case R_V850_TDA_7_7_OFFSET:
448 #ifdef R_V850_TDA_16_16_OFFSET
449 case R_V850_TDA_16_16_OFFSET:
451 #ifdef R_V850_TDA_4_5_OFFSET
452 case R_V850_TDA_4_5_OFFSET:
454 #ifdef R_V850_TDA_4_4_OFFSET
455 case R_V850_TDA_4_4_OFFSET:
457 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
458 case R_V850_SDA_16_16_SPLIT_OFFSET:
460 #ifdef R_V850_CALLT_6_7_OFFSET
461 case R_V850_CALLT_6_7_OFFSET:
463 #ifdef R_V850_CALLT_16_16_OFFSET
464 case R_V850_CALLT_16_16_OFFSET:
466 /* These are relative relocations, which
467 have already been fixed up by the
468 linker at this point, so just ignore
472 #endif /* USE_V850_RELOCS */
475 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
476 sym_name = (*(q->sym_ptr_ptr))->name;
477 sym_section = (*(q->sym_ptr_ptr))->section;
478 section_name=(*(q->sym_ptr_ptr))->section->name;
480 printf("ERROR: undefined relocation entry\n");
484 /* Adjust the address to account for the GOT table which wasn't
485 * present in the relative file link.
488 q->address += got_size;
490 /* A pointer to what's being relocated, used often
492 r_mem = sectionp + q->address;
495 * Fixup offset in the actual section.
499 if ((sym_addr = get_symbol_offset((char *) sym_name,
500 sym_section, symbols, number_of_symbols)) == -1) {
504 sym_addr = (*(q->sym_ptr_ptr))->value;
507 /* Use the address of the symbol already in
508 the program text. How this is handled may
509 still depend on the particular relocation
511 switch (q->howto->type) {
515 /* We specially handle adjacent
516 HI16_S/ZDA_15_16_OFFSET and
517 HI16_S/LO16 pairs that reference the
518 same address (these are usually
519 movhi/ld and movhi/movea pairs,
522 r2_type = R_V850_NONE;
524 r2_type = p[1]->howto->type;
525 if ((r2_type == R_V850_ZDA_15_16_OFFSET
526 || r2_type == R_V850_LO16)
527 && (p[0]->sym_ptr_ptr
528 == p[1]->sym_ptr_ptr)
529 && (p[0]->addend == p[1]->addend))
531 relocation_needed = 1;
534 case R_V850_ZDA_15_16_OFFSET:
542 /* We don't really need the
543 actual value -- the bits
544 produced by the linker are
545 what we want in the final
546 flat file -- but get it
550 unsigned char *r2_mem =
558 /* Sign extend LO. */
562 /* Maybe ignore the LSB
566 if (r2_type != R_V850_LO16)
574 goto bad_v850_reloc_err;
578 /* See if this is actually the
579 2nd half of a pair. */
581 && (p[-1]->howto->type
583 && (p[-1]->sym_ptr_ptr
584 == p[0]->sym_ptr_ptr)
585 && (p[-1]->addend == p[0]->addend))
586 break; /* not an error */
588 goto bad_v850_reloc_err;
592 printf("ERROR: reloc type %s unsupported in this context\n",
596 #endif /* TARGET_V850 */
599 /* The default is to assume that the
600 relocation is relative and has
601 already been fixed up by the
602 linker (perhaps we ought to make
603 give an error by default, and
604 require `safe' relocations to be
605 enumberated explicitly?). */
606 if (bfd_big_endian (abs_bfd))
618 relocation_needed = 1;
621 /* Calculate the sym address ourselves. */
622 sym_reloc_size = bfd_get_reloc_size(q->howto);
624 #if !defined(TARGET_h8300) && !defined(TARGET_e1)
625 if (sym_reloc_size != 4) {
626 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
627 (*p)->howto->type, sym_reloc_size, sym_name);
634 switch ((*p)->howto->type) {
636 #if defined(TARGET_m68k)
638 relocation_needed = 1;
639 sym_vma = bfd_section_vma(abs_bfd, sym_section);
640 sym_addr += sym_vma + q->addend;
644 sym_addr += sym_vma + q->addend;
645 sym_addr -= q->address;
649 #if defined(TARGET_arm)
651 relocation_needed = 1;
654 "%s vma=0x%x, value=0x%x, address=0x%x "
655 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
657 sym_vma, (*(q->sym_ptr_ptr))->value,
658 q->address, sym_addr,
659 (*p)->howto->rightshift,
660 *(unsigned long *)r_mem);
661 sym_vma = bfd_section_vma(abs_bfd, sym_section);
662 sym_addr += sym_vma + q->addend;
666 /* Should be fine as is */
671 "%s vma=0x%x, value=0x%x, address=0x%x "
672 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
674 sym_vma, (*(q->sym_ptr_ptr))->value,
675 q->address, sym_addr,
676 (*p)->howto->rightshift,
677 *(unsigned long *)r_mem);
680 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
686 relocation_needed = 1;
687 sym_vma = bfd_section_vma(abs_bfd, sym_section);
688 sym_addr += sym_vma + q->addend;
690 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
691 #ifdef R_V850_ZDA_16_16_OFFSET
692 case R_V850_ZDA_16_16_OFFSET:
694 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
695 case R_V850_ZDA_16_16_SPLIT_OFFSET:
697 /* Can't support zero-relocations. */
698 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
699 sym_name, q->addend);
701 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
702 #endif /* TARGET_v850 */
706 if (sym_reloc_size != 4) {
707 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
711 relocation_needed = 1;
712 sym_addr = (*(q->sym_ptr_ptr))->value;
714 r_mem -= 1; /* tracks q->address */
715 sym_vma = bfd_section_vma(abs_bfd, sym_section);
716 sym_addr += sym_vma + q->addend;
717 sym_addr |= (*(unsigned char *)r_mem<<24);
720 if (sym_reloc_size != 4) {
721 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
725 /* Absolute symbol done not relocation */
726 relocation_needed = !bfd_is_abs_section(sym_section);
727 sym_addr = (*(q->sym_ptr_ptr))->value;
728 sym_vma = bfd_section_vma(abs_bfd, sym_section);
729 sym_addr += sym_vma + q->addend;
732 case R_H8_DIR32A16: /* currently 32, could be made 16 */
733 if (sym_reloc_size != 4) {
734 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
738 relocation_needed = 1;
739 sym_addr = (*(q->sym_ptr_ptr))->value;
740 sym_vma = bfd_section_vma(abs_bfd, sym_section);
741 sym_addr += sym_vma + q->addend;
745 sym_addr = (*(q->sym_ptr_ptr))->value;
746 sym_addr += sym_vma + q->addend;
747 sym_addr -= (q->address + 2);
748 if (bfd_big_endian(abs_bfd))
749 *(unsigned short *)r_mem =
750 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
754 sym_addr = (*(q->sym_ptr_ptr))->value;
755 sym_addr += sym_vma + q->addend;
756 sym_addr -= (q->address + 1);
757 *(unsigned char *)r_mem = sym_addr;
761 #ifdef TARGET_microblaze
762 case R_MICROBLAZE_64:
763 /* The symbol is split over two consecutive instructions.
764 Flag this to the flat loader by setting the high bit of
765 the relocation symbol. */
767 unsigned char *p = r_mem;
768 unsigned long offset;
771 /* work out the relocation */
772 sym_vma = bfd_section_vma(abs_bfd, sym_section);
773 /* grab any offset from the text */
774 offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
775 /* Update the address */
776 sym_addr += offset + sym_vma + q->addend;
777 /* Write relocated pointer back */
778 p[2] = (sym_addr >> 24) & 0xff;
779 p[3] = (sym_addr >> 16) & 0xff;
780 p[6] = (sym_addr >> 8) & 0xff;
781 p[7] = sym_addr & 0xff;
783 /* create a new reloc entry */
784 flat_relocs = realloc(flat_relocs,
785 (flat_reloc_count + 1) * sizeof(uint32_t));
786 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
788 relocation_needed = 0;
790 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
791 bfd_section_vma(abs_bfd, sym_section));
793 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
794 "section=%s size=%d "
795 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
796 q->address, sym_name, addstr,
797 section_name, sym_reloc_size,
798 sym_addr, section_vma + q->address);
800 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
801 section_vma + q->address);
805 case R_MICROBLAZE_32:
807 unsigned char *p = r_mem;
808 unsigned long offset;
810 /* grab any offset from the text */
811 offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
812 sym_vma = bfd_section_vma(abs_bfd, sym_section);
813 /* This is a horrible kludge. For some
814 reason, *sometimes* the offset is in
815 both addend and the code. Detect
816 it, and cancel the effect. Otherwise
817 the offset gets added twice - ouch.
818 There should be a better test
819 for this condition, based on the
820 BFD data structures */
821 if(offset==q->addend)
824 sym_addr += offset + sym_vma + q->addend;
825 relocation_needed = 1;
828 case R_MICROBLAZE_64_PCREL:
830 //sym_addr = (*(q->sym_ptr_ptr))->value;
831 sym_addr += sym_vma + q->addend;
832 sym_addr -= (q->address + 4);
833 sym_addr = htonl(sym_addr);
835 * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
837 * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
838 /* We've done all the work, so continue
839 to next reloc instead of break */
842 #endif /* TARGET_microblaze */
847 relocation_needed = 1;
848 sym_vma = bfd_section_vma(abs_bfd, sym_section);
849 sym_addr += sym_vma + q->addend;
853 sym_addr += sym_vma + q->addend;
854 sym_addr -= q->address;
856 case R_SPARC_WDISP30:
857 sym_addr = (((*(q->sym_ptr_ptr))->value-
858 q->address) >> 2) & 0x3fffffff;
860 ntohl(*(unsigned long *)r_mem)
865 relocation_needed = 1;
867 sym_vma = bfd_section_vma(abs_bfd, sym_section);
868 sym_addr += sym_vma + q->addend;
870 htonl(*(unsigned long *)r_mem)
875 relocation_needed = 1;
877 sym_vma = bfd_section_vma(abs_bfd, sym_section);
878 sym_addr += sym_vma + q->addend;
879 sym_addr &= 0x000003ff;
881 htonl(*(unsigned long *)r_mem)
885 #endif /* TARGET_sparc */
889 relocation_needed = 1;
890 sym_vma = bfd_section_vma(abs_bfd, sym_section);
891 sym_addr += sym_vma + q->addend;
895 sym_addr += sym_vma + q->addend;
896 sym_addr -= q->address;
898 #endif /* TARGET_sh */
901 #define htoe1l(x) htonl(x)
908 #define DBG_E1 printf
910 #define DBG_E1(x, ... )
913 #define _32BITS_RELOC 0x00000000
914 #define _30BITS_RELOC 0x80000000
915 #define _28BITS_RELOC 0x40000000
918 unsigned long sec_vma, exist_val, S;
920 relocation_needed = 1;
921 DBG_E1("Handling Reloc <CONST31>\n");
922 sec_vma = bfd_section_vma(abs_bfd, sym_section);
923 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
924 sec_vma, sym_addr, q->address);
925 sym_addr = sec_vma + sym_addr;
926 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
927 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
928 exist_val = htoe1l(exist_val);
929 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
930 sym_addr += exist_val;
931 pflags = _30BITS_RELOC;
933 case R_E1_CONST31_PCREL:
934 relocation_needed = 0;
935 DBG_E1("Handling Reloc <CONST31_PCREL>\n");
936 DBG_E1("DONT RELOCATE AT LOADING\n");
937 sec_vma = bfd_section_vma(abs_bfd, sym_section);
938 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
939 sec_vma, sym_addr, q->address);
940 sym_addr = sec_vma + sym_addr;
941 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
943 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
945 q->address = q->address + section_vma;
946 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
948 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
949 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
950 DBG_E1( "sym_addr := sym_addr - q->address - "
951 "sizeof(CONST31_PCREL): [0x%x]\n",
953 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
954 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
955 exist_val = htoe1l(exist_val);
956 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
957 sym_addr |= exist_val;
958 DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr );
960 case R_E1_DIS29W_PCREL:
961 relocation_needed = 0;
962 DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
963 DBG_E1("DONT RELOCATE AT LOADING\n");
964 sec_vma = bfd_section_vma(abs_bfd, sym_section);
965 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
966 sec_vma, sym_addr, q->address);
967 sym_addr = sec_vma + sym_addr;
968 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
970 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
972 q->address = q->address + section_vma;
973 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
975 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
976 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
977 DBG_E1( "sym_addr := sym_addr - q->address - "
978 "sizeof(CONST31_PCREL): [0x%x]\n",
980 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
981 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
982 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
983 exist_val = htoe1l(exist_val);
984 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
985 sym_addr += exist_val;
988 DBG_E1("Handling Reloc <DIS29W>\n");
989 goto DIS29_RELOCATION;
991 DBG_E1("Handling Reloc <DIS29H>\n");
992 goto DIS29_RELOCATION;
994 DBG_E1("Handling Reloc <DIS29B>\n");
996 relocation_needed = 1;
997 sec_vma = bfd_section_vma(abs_bfd, sym_section);
998 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
1000 sym_addr = sec_vma + sym_addr;
1001 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr);
1002 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1003 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1004 exist_val = htoe1l(exist_val);
1005 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1006 sym_addr += exist_val;
1007 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1008 pflags = _28BITS_RELOC;
1010 case R_E1_IMM32_PCREL:
1011 relocation_needed = 0;
1012 DBG_E1("Handling Reloc <IMM32_PCREL>\n");
1013 DBG_E1("DONT RELOCATE AT LOADING\n");
1014 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1015 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1017 sym_addr = sec_vma + sym_addr;
1019 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1020 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1022 q->address = q->address + section_vma;
1023 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1025 if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
1026 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1027 DBG_E1( "sym_addr := sym_addr - q->address - "
1028 "sizeof(CONST31_PCREL): [0x%x]\n",
1030 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1031 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1032 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1033 exist_val = htoe1l(exist_val);
1034 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1035 sym_addr += exist_val;
1038 relocation_needed = 1;
1039 DBG_E1("Handling Reloc <IMM32>\n");
1040 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1041 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1043 sym_addr = sec_vma + sym_addr;
1044 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1045 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1046 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1047 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1048 exist_val = htoe1l(exist_val);
1049 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1050 sym_addr += exist_val;
1051 pflags = _32BITS_RELOC;
1054 relocation_needed = 1;
1055 DBG_E1("Handling Reloc <WORD>\n");
1056 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1057 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1059 sym_addr = sec_vma + sym_addr;
1060 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1061 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
1062 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1063 exist_val = htoe1l(exist_val);
1064 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1065 sym_addr += exist_val;
1066 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1067 pflags = _32BITS_RELOC;
1070 #undef _32BITS_RELOC
1071 #undef _30BITS_RELOC
1072 #undef _28BITS_RELOC
1075 /* missing support for other types of relocs */
1076 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
1082 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
1083 bfd_section_vma(abs_bfd, sym_section));
1087 * for full elf relocation we have to write back the
1088 * start_code relative value to use.
1090 if (!pic_with_got) {
1091 #if defined(TARGET_arm)
1100 * horrible nasty hack to support different endianess
1102 if (!bfd_big_endian(abs_bfd)) {
1114 tmp.l = *(unsigned long *)r_mem;
1115 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
1116 if (((*p)->howto->type != R_ARM_PC24) &&
1117 ((*p)->howto->type != R_ARM_PLT32))
1118 hl |= (tmp.c[i3] << 24);
1119 else if (tmp.c[i2] & 0x80)
1120 hl |= 0xff000000; /* sign extend */
1122 tmp.c[i0] = hl & 0xff;
1123 tmp.c[i1] = (hl >> 8) & 0xff;
1124 tmp.c[i2] = (hl >> 16) & 0xff;
1125 if (((*p)->howto->type != R_ARM_PC24) &&
1126 ((*p)->howto->type != R_ARM_PLT32))
1127 tmp.c[i3] = (hl >> 24) & 0xff;
1128 if ((*p)->howto->type == R_ARM_ABS32)
1129 *(unsigned long *)r_mem = htonl(hl);
1131 *(unsigned long *)r_mem = tmp.l;
1133 #elif defined(TARGET_e1)
1134 #define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/
1135 switch ((*p)->howto->type) {
1137 case R_E1_CONST31_PCREL:
1138 case R_E1_DIS29W_PCREL:
1142 case R_E1_IMM32_PCREL:
1144 DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
1145 (sectionp + q->address + 2), sym_addr );
1146 *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
1150 DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
1151 (sectionp + q->address), sym_addr );
1152 *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
1155 printf("ERROR:Unhandled Relocation. Exiting...\n");
1159 #else /* ! TARGET_arm && ! TARGET_e1 */
1161 switch (q->howto->type) {
1166 /* Do nothing -- for cases we handle,
1167 the bits produced by the linker are
1168 what we want in the final flat file
1169 (and other cases are errors). Note
1170 that unlike most relocated values,
1171 it is stored in little-endian order,
1172 but this is necessary to avoid
1173 trashing the low-bit, and the float
1174 loaders knows about it. */
1176 #endif /* TARGET_V850 */
1178 /* The alignment of the build host
1179 might be stricter than that of the
1180 target, so be careful. We store in
1181 network byte order. */
1182 r_mem[0] = (sym_addr >> 24) & 0xff;
1183 r_mem[1] = (sym_addr >> 16) & 0xff;
1184 r_mem[2] = (sym_addr >> 8) & 0xff;
1185 r_mem[3] = sym_addr & 0xff;
1187 #endif /* !TARGET_arm */
1191 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
1192 "section=%s size=%d "
1193 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
1194 q->address, sym_name, addstr,
1195 section_name, sym_reloc_size,
1196 sym_addr, section_vma + q->address);
1199 * Create relocation entry (PC relative doesn't need this).
1201 if (relocation_needed) {
1202 flat_relocs = realloc(flat_relocs,
1203 (flat_reloc_count + 1) * sizeof(uint32_t));
1205 flat_relocs[flat_reloc_count] = pflags |
1206 (section_vma + q->address);
1209 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
1210 section_vma + q->address);
1212 switch ((*p)->howto->type) {
1214 case R_E1_CONST31_PCREL:
1215 case R_E1_DIS29W_PCREL:
1219 case R_E1_IMM32_PCREL:
1221 flat_relocs[flat_reloc_count] = pflags |
1222 (section_vma + q->address + OPCODE_SIZE);
1224 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1225 flat_relocs[flat_reloc_count] );
1228 flat_relocs[flat_reloc_count] = pflags |
1229 (section_vma + q->address);
1231 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1232 flat_relocs[flat_reloc_count] );
1237 relocation_needed = 0;
1242 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
1243 __FILE__, __LINE__, sym_name, q->address, section_name,
1244 flat_relocs[flat_reloc_count]);
1251 printf("%d bad relocs\n", bad_relocs);
1258 *n_relocs = flat_reloc_count;
1264 static char * program;
1266 static void usage(void)
1268 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1269 "[-o <output-file>] <elf-file>\n\n"
1270 " -v : verbose operation\n"
1271 " -r : force load to RAM\n"
1272 " -k : enable kernel trace on load (for debug)\n"
1273 " -z : compress code/data/relocs\n"
1274 " -d : compress data/relocs\n"
1275 " -a : use existing symbol references\n"
1276 " instead of recalculating from\n"
1277 " relocation info\n"
1278 " -R reloc-file : read relocations from a separate file\n"
1279 " -p abs-pic-file : GOT/PIC processing with files\n"
1280 " -s stacksize : set application stack size\n"
1281 " -o output-file : output file name\n\n",
1283 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1288 /* Write NUM zeroes to STREAM. */
1289 static void write_zeroes (unsigned long num, FILE *stream)
1293 /* It'd be nice if we could just use fseek, but that doesn't seem to
1294 work for stdio output files. */
1295 bzero(zeroes, 1024);
1296 while (num > sizeof(zeroes)) {
1297 fwrite(zeroes, sizeof(zeroes), 1, stream);
1298 num -= sizeof(zeroes);
1301 fwrite(zeroes, num, 1, stream);
1306 int main(int argc, char *argv[])
1309 bfd *rel_bfd, *abs_bfd;
1311 char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1320 asymbol **symbol_table;
1321 long number_of_symbols;
1323 unsigned long data_len = 0;
1324 unsigned long bss_len = 0;
1325 unsigned long text_len = 0;
1326 unsigned long reloc_len;
1328 unsigned long data_vma = ~0;
1329 unsigned long bss_vma = ~0;
1330 unsigned long text_vma = ~0;
1332 unsigned long text_offs;
1336 unsigned long *reloc;
1338 struct flat_hdr hdr;
1350 #else /* We need plenty of stack for both of them (Aggregate and Register) */
1354 while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1381 stack = atoi(optarg);
1387 fprintf(stderr, "%s Unknown option\n", argv[0]);
1394 * if neither the -r or -p options was given, default to
1395 * a RAM load as that is the only option that makes sense.
1397 if (!load_to_ram && !pfile)
1400 filename = fname = argv[argc-1];
1411 if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1412 fprintf(stderr, "Can't open %s\n", rel_file);
1416 if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1417 fprintf(stderr, "File is not an object file\n");
1421 if (abs_file == rel_file)
1422 abs_bfd = rel_bfd; /* one file does all */
1424 if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1425 fprintf(stderr, "Can't open %s\n", abs_file);
1429 if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1430 fprintf(stderr, "File is not an object file\n");
1435 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1436 fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1440 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1441 /* `Absolute' file is not absolute, so neither are address
1442 contained therein. */
1444 "%s: `-a' option specified with non-fully-resolved input file\n",
1445 bfd_get_filename (abs_bfd));
1449 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1451 /* Group output sections into text, data, and bss, and calc their sizes. */
1452 for (s = abs_bfd->sections; s != NULL; s = s->next) {
1453 unsigned long *vma, *len;
1454 bfd_size_type sec_size;
1457 if (s->flags & SEC_CODE) {
1460 } else if (s->flags & SEC_DATA) {
1463 } else if (s->flags & SEC_ALLOC) {
1469 sec_size = bfd_section_size(abs_bfd, s);
1470 sec_vma = bfd_section_vma(abs_bfd, s);
1472 if (sec_vma < *vma) {
1474 *len += sec_vma - *vma;
1478 } else if (sec_vma + sec_size > *vma + *len)
1479 *len = sec_vma + sec_size - *vma;
1482 if (text_len == 0) {
1483 fprintf (stderr, "%s: no .text section", abs_file);
1487 text = malloc(text_len);
1490 printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1492 /* Read in all text sections. */
1493 for (s = abs_bfd->sections; s != NULL; s = s->next)
1494 if (s->flags & SEC_CODE)
1495 if (!bfd_get_section_contents(abs_bfd, s,
1496 text + (s->vma - text_vma), 0,
1497 bfd_section_size(abs_bfd, s)))
1499 fprintf(stderr, "read error section %s\n", s->name);
1503 if (data_len == 0) {
1504 fprintf (stderr, "%s: no .data section", abs_file);
1507 data = malloc(data_len);
1510 printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1512 if ((text_vma + text_len) != data_vma) {
1513 if ((text_vma + text_len) > data_vma) {
1514 printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1518 printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1519 data_vma, text_len);
1520 text_len = data_vma - text_vma;
1523 /* Read in all data sections. */
1524 for (s = abs_bfd->sections; s != NULL; s = s->next)
1525 if (s->flags & SEC_DATA)
1526 if (!bfd_get_section_contents(abs_bfd, s,
1527 data + (s->vma - data_vma), 0,
1528 bfd_section_size(abs_bfd, s)))
1530 fprintf(stderr, "read error section %s\n", s->name);
1534 /* Put common symbols in bss. */
1535 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1538 printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1540 if ((data_vma + data_len) != bss_vma) {
1541 if ((data_vma + data_len) > bss_vma) {
1542 printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1547 printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1548 bss_vma, text_len, data_len, text_len + data_len);
1549 data_len = bss_vma - data_vma;
1552 reloc = (unsigned long *)
1553 output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1554 text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1557 printf("No relocations in code!\n");
1559 text_offs = real_address_bits(text_vma);
1561 /* Fill in the binflt_flat header */
1562 memcpy(hdr.magic,"bFLT",4);
1563 hdr.rev = htonl(FLAT_VERSION);
1564 hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1565 hdr.data_start = htonl(16 * 4 + text_offs + text_len);
1566 hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len);
1567 hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1568 hdr.stack_size = htonl(stack); /* FIXME */
1569 hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1570 hdr.reloc_count = htonl(reloc_len);
1572 | (load_to_ram ? FLAT_FLAG_RAM : 0)
1573 | (ktrace ? FLAT_FLAG_KTRACE : 0)
1574 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1575 | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1577 hdr.build_date = htonl((unsigned long)time(NULL));
1578 bzero(hdr.filler, sizeof(hdr.filler));
1580 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1583 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1584 text_len, data_len, bss_len);
1586 printf(", relocs=0x%04x", reloc_len);
1591 ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1592 strcpy(ofile, fname);
1593 strcat(ofile, ".bflt");
1596 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1597 fprintf (stderr, "Can't open output file %s\n", ofile);
1601 write(fd, &hdr, sizeof(hdr));
1605 * get the compression command ready
1607 sprintf(cmd, "gzip -f -9 >> %s", ofile);
1609 #define START_COMPRESSOR do { \
1615 if (!(gf = popen(cmd, "wb"))) { \
1616 fprintf(stderr, "Can't run cmd %s\n", cmd); \
1622 gf = fopen(ofile, "ab"); /* Add 'b' to support non-posix (ie windows) */
1624 fprintf(stderr, "Can't open file %s for writing\n", ofile); \
1631 /* Fill in any hole at the beginning of the text segment. */
1633 printf("ZERO before text len=0x%x\n", text_offs);
1634 write_zeroes(text_offs, gf);
1636 /* Write the text segment. */
1637 fwrite(text, text_len, 1, gf);
1642 /* Write the data segment. */
1643 fwrite(data, data_len, 1, gf);
1646 fwrite(reloc, reloc_len * 4, 1, gf);
1658 * this __MUST__ be at the VERY end of the file - do NOT move!!
1664 * vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab