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 */
49 /* from $(INSTALLDIR)/include */
50 #include <bfd.h> /* Main header file for the BFD library */
52 #if defined(TARGET_h8300)
53 #include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
54 #elif defined(TARGET_microblaze)
55 #include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
56 #elif defined(__CYGWIN__)
57 #include "cygwin-elf.h" /* Cygwin uses a local copy */
59 #include <elf.h> /* TARGET_* ELF support for the BFD library */
62 /* from uClinux-x.x.x/include/linux */
63 #include "flat.h" /* Binary flat header description */
73 #if defined(TARGET_m68k)
74 #define ARCH "m68k/coldfire"
75 #elif defined(TARGET_arm)
77 #elif defined(TARGET_sparc)
79 #elif defined(TARGET_v850)
81 #elif defined(TARGET_sh)
83 #elif defined(TARGET_h8300)
85 #elif defined(TARGET_microblaze)
86 #define ARCH "microblaze"
87 #elif defined(TARGET_e1)
88 #define ARCH "e1-coff"
90 #error "Don't know how to support your CPU architecture??"
93 #if defined(TARGET_m68k) || defined(TARGET_h8300)
95 * Define a maximum number of bytes allowed in the offset table.
96 * We'll fail if the table is larger than this.
98 * This limit may be different for platforms other than m68k, but
99 * 8000 entries is a lot, trust me :-) (davidm)
101 #define GOT_LIMIT 32767
103 * we have to mask out the shared library id here and there, this gives
104 * us the real address bits when needed
106 #define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
108 #define real_address_bits(x) (x)
116 int verbose = 0; /* extra output when running */
117 int pic_with_got = 0; /* do elf/got processing with PIC code */
118 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
119 int ktrace = 0; /* instruct loader output kernel trace on load */
120 int compress = 0; /* 1 = compress everything, 2 = compress data only */
121 int use_resolved = 0; /* If true, get the value of symbol references from */
122 /* the program contents, not from the relocation table. */
123 /* In this case, the input ELF file must be already */
124 /* fully resolved (using the `-q' flag with recent */
125 /* versions of GNU ld will give you a fully resolved */
126 /* output file with relocation entries). */
128 const char *progname, *filename;
134 static char where[200];
137 /* Use exactly one of these: */
138 E_NOFILE = 0, /* "progname: " */
139 E_FILE = 1, /* "filename: " */
140 E_FILELINE = 2, /* "filename:lineno: " */
141 E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */
143 /* Add in any of these with |': */
148 void ewhere (const char *format, ...);
149 void einfo (int type, const char *format, ...);
153 ewhere (const char *format, ...) {
155 va_start (args, format);
156 vsprintf (where, format, args);
162 einfo (int type, const char *format, ...) {
165 switch (type & 0x0f) {
167 fprintf (stderr, "%s: ", progname);
170 fprintf (stderr, "%s: ", filename);
173 ewhere ("%d", lineno);
176 fprintf (stderr, "%s:%s: ", filename, where);
180 if (type & E_WARNING) {
181 fprintf (stderr, "warning: ");
187 va_start (args, format);
188 vfprintf (stderr, format, args);
194 fprintf (stderr, "\n");
199 get_symbols (bfd *abfd, long *num)
202 asymbol **symbol_table;
203 long number_of_symbols;
205 storage_needed = bfd_get_symtab_upper_bound (abfd);
207 if (storage_needed < 0)
210 if (storage_needed == 0)
213 symbol_table = (asymbol **) malloc (storage_needed);
215 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
217 if (number_of_symbols < 0)
220 *num = number_of_symbols;
227 dump_symbols(asymbol **symbol_table, long number_of_symbols)
230 printf("SYMBOL TABLE:\n");
231 for (i=0; i<number_of_symbols; i++) {
232 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
233 symbol_table[i]->value);
242 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
245 for (i=0; i<number_of_symbols; i++) {
246 if (symbol_table[i]->section == sec) {
247 if (!strcmp(symbol_table[i]->name, name)) {
248 return symbol_table[i]->value;
258 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
264 for (i=0; i<number_of_symbols; i++) {
265 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
266 offset = bss_len + comsize;
267 comsize += symbol_table[i]->value;
268 symbol_table[i]->value = offset;
280 int number_of_symbols,
281 unsigned long *n_relocs,
282 unsigned char *text, int text_len, unsigned long text_vma,
283 unsigned char *data, int data_len, unsigned long data_vma,
286 unsigned long *flat_relocs;
287 asection *a, *sym_section, *r;
288 arelent **relpp, **p, *q;
289 const char *sym_name, *section_name;
290 unsigned char *sectionp;
291 unsigned long pflags;
293 long sym_addr, sym_vma, section_vma;
294 int relsize, relcount;
295 int flat_reloc_count;
296 int sym_reloc_size, rc;
303 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
304 "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
305 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
306 text, text_len, data, data_len);
310 dump_symbols(symbols, number_of_symbols);
315 flat_reloc_count = 0;
319 /* Determine how big our offset table is in bytes.
320 * This isn't too difficult as we've terminated the table with -1.
321 * Also note that both the relocatable and absolute versions have this
322 * terminator even though the relocatable one doesn't have the GOT!
325 unsigned long *lp = (unsigned long *)data;
326 /* Should call ntohl(*lp) here but is isn't going to matter */
327 while (*lp != 0xffffffff) lp++;
328 got_size = ((unsigned char *)lp) - data;
330 printf("GOT table contains %d entries (%d bytes)\n",
331 got_size/sizeof(unsigned long), got_size);
333 if (got_size > GOT_LIMIT) {
334 fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
335 got_size, GOT_LIMIT);
341 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
342 section_vma = bfd_section_vma(abs_bfd, a);
345 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
346 a->flags, section_vma);
348 // if (bfd_is_abs_section(a))
350 if (bfd_is_und_section(a))
352 if (bfd_is_com_section(a))
354 // if ((a->flags & SEC_RELOC) == 0)
358 * Only relocate things in the data sections if we are PIC/GOT.
359 * otherwise do text as well
361 if (!pic_with_got && (a->flags & SEC_CODE))
362 sectionp = text + (a->vma - text_vma);
363 else if (a->flags & SEC_DATA)
364 sectionp = data + (a->vma - data_vma);
368 /* Now search for the equivalent section in the relocation binary
369 * and use that relocation information to build reloc entries
372 for (r=rel_bfd->sections; r != NULL; r=r->next)
373 if (strcmp(a->name, r->name) == 0)
378 printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
379 r->flags, bfd_section_vma(abs_bfd, r));
380 if ((r->flags & SEC_RELOC) == 0)
382 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
385 printf("%s(%d): no relocation entries section=0x%x\n",
386 __FILE__, __LINE__, r->name);
390 symb = get_symbols(rel_bfd, &nsymb);
391 relpp = (arelent **) xmalloc(relsize);
392 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
395 printf("%s(%d): no relocation entries section=%s\n",
396 __FILE__, __LINE__, r->name);
399 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
400 unsigned char *r_mem;
401 int relocation_needed = 0;
403 #ifdef TARGET_microblaze
404 /* The MICROBLAZE_XX_NONE relocs can be skipped.
405 They represent PC relative branches that the
406 linker has already resolved */
408 switch ((*p)->howto->type)
410 case R_MICROBLAZE_NONE:
411 case R_MICROBLAZE_64_NONE:
414 #endif /* TARGET_microblaze */
417 /* Skip this relocation entirely if possible (we
418 do this early, before doing any other
419 processing on it). */
420 switch ((*p)->howto->type) {
421 #ifdef R_V850_9_PCREL
424 #ifdef R_V850_22_PCREL
425 case R_V850_22_PCREL:
427 #ifdef R_V850_SDA_16_16_OFFSET
428 case R_V850_SDA_16_16_OFFSET:
430 #ifdef R_V850_SDA_15_16_OFFSET
431 case R_V850_SDA_15_16_OFFSET:
433 #ifdef R_V850_ZDA_15_16_OFFSET
434 case R_V850_ZDA_15_16_OFFSET:
436 #ifdef R_V850_TDA_6_8_OFFSET
437 case R_V850_TDA_6_8_OFFSET:
439 #ifdef R_V850_TDA_7_8_OFFSET
440 case R_V850_TDA_7_8_OFFSET:
442 #ifdef R_V850_TDA_7_7_OFFSET
443 case R_V850_TDA_7_7_OFFSET:
445 #ifdef R_V850_TDA_16_16_OFFSET
446 case R_V850_TDA_16_16_OFFSET:
448 #ifdef R_V850_TDA_4_5_OFFSET
449 case R_V850_TDA_4_5_OFFSET:
451 #ifdef R_V850_TDA_4_4_OFFSET
452 case R_V850_TDA_4_4_OFFSET:
454 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
455 case R_V850_SDA_16_16_SPLIT_OFFSET:
457 #ifdef R_V850_CALLT_6_7_OFFSET
458 case R_V850_CALLT_6_7_OFFSET:
460 #ifdef R_V850_CALLT_16_16_OFFSET
461 case R_V850_CALLT_16_16_OFFSET:
463 /* These are relative relocations, which
464 have already been fixed up by the
465 linker at this point, so just ignore
469 #endif /* USE_V850_RELOCS */
472 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
473 sym_name = (*(q->sym_ptr_ptr))->name;
474 sym_section = (*(q->sym_ptr_ptr))->section;
475 section_name=(*(q->sym_ptr_ptr))->section->name;
477 printf("ERROR: undefined relocation entry\n");
481 /* Adjust the address to account for the GOT table which wasn't
482 * present in the relative file link.
485 q->address += got_size;
487 /* A pointer to what's being relocated, used often
489 r_mem = sectionp + q->address;
492 * Fixup offset in the actual section.
496 if ((sym_addr = get_symbol_offset((char *) sym_name,
497 sym_section, symbols, number_of_symbols)) == -1) {
501 sym_addr = (*(q->sym_ptr_ptr))->value;
504 /* Use the address of the symbol already in
505 the program text. How this is handled may
506 still depend on the particular relocation
508 switch (q->howto->type) {
512 /* We specially handle adjacent
513 HI16_S/ZDA_15_16_OFFSET and
514 HI16_S/LO16 pairs that reference the
515 same address (these are usually
516 movhi/ld and movhi/movea pairs,
519 r2_type = R_V850_NONE;
521 r2_type = p[1]->howto->type;
522 if ((r2_type == R_V850_ZDA_15_16_OFFSET
523 || r2_type == R_V850_LO16)
524 && (p[0]->sym_ptr_ptr
525 == p[1]->sym_ptr_ptr)
526 && (p[0]->addend == p[1]->addend))
528 relocation_needed = 1;
531 case R_V850_ZDA_15_16_OFFSET:
539 /* We don't really need the
540 actual value -- the bits
541 produced by the linker are
542 what we want in the final
543 flat file -- but get it
547 unsigned char *r2_mem =
555 /* Sign extend LO. */
559 /* Maybe ignore the LSB
563 if (r2_type != R_V850_LO16)
571 goto bad_v850_reloc_err;
575 /* See if this is actually the
576 2nd half of a pair. */
578 && (p[-1]->howto->type
580 && (p[-1]->sym_ptr_ptr
581 == p[0]->sym_ptr_ptr)
582 && (p[-1]->addend == p[0]->addend))
583 break; /* not an error */
585 goto bad_v850_reloc_err;
589 printf("ERROR: reloc type %s unsupported in this context\n",
593 #endif /* TARGET_V850 */
596 /* The default is to assume that the
597 relocation is relative and has
598 already been fixed up by the
599 linker (perhaps we ought to make
600 give an error by default, and
601 require `safe' relocations to be
602 enumberated explicitly?). */
603 if (bfd_big_endian (abs_bfd))
615 relocation_needed = 1;
618 /* Calculate the sym address ourselves. */
619 sym_reloc_size = bfd_get_reloc_size(q->howto);
621 #if !defined(TARGET_h8300) && !defined(TARGET_e1)
622 if (sym_reloc_size != 4) {
623 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
624 (*p)->howto->type, sym_reloc_size, sym_name);
631 switch ((*p)->howto->type) {
633 #if defined(TARGET_m68k)
635 relocation_needed = 1;
636 sym_vma = bfd_section_vma(abs_bfd, sym_section);
637 sym_addr += sym_vma + q->addend;
641 sym_addr += sym_vma + q->addend;
642 sym_addr -= q->address;
646 #if defined(TARGET_arm)
648 relocation_needed = 1;
651 "%s vma=0x%x, value=0x%x, address=0x%x "
652 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
654 sym_vma, (*(q->sym_ptr_ptr))->value,
655 q->address, sym_addr,
656 (*p)->howto->rightshift,
657 *(unsigned long *)r_mem);
658 sym_vma = bfd_section_vma(abs_bfd, sym_section);
659 sym_addr += sym_vma + q->addend;
663 /* Should be fine as is */
668 "%s vma=0x%x, value=0x%x, address=0x%x "
669 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
671 sym_vma, (*(q->sym_ptr_ptr))->value,
672 q->address, sym_addr,
673 (*p)->howto->rightshift,
674 *(unsigned long *)r_mem);
677 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
683 relocation_needed = 1;
684 sym_vma = bfd_section_vma(abs_bfd, sym_section);
685 sym_addr += sym_vma + q->addend;
687 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
688 #ifdef R_V850_ZDA_16_16_OFFSET
689 case R_V850_ZDA_16_16_OFFSET:
691 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
692 case R_V850_ZDA_16_16_SPLIT_OFFSET:
694 /* Can't support zero-relocations. */
695 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
696 sym_name, q->addend);
698 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
699 #endif /* TARGET_v850 */
703 if (sym_reloc_size != 4) {
704 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
708 relocation_needed = 1;
709 sym_addr = (*(q->sym_ptr_ptr))->value;
711 r_mem -= 1; /* tracks q->address */
712 sym_vma = bfd_section_vma(abs_bfd, sym_section);
713 sym_addr += sym_vma + q->addend;
714 sym_addr |= (*(unsigned char *)r_mem<<24);
717 if (sym_reloc_size != 4) {
718 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
722 /* Absolute symbol done not relocation */
723 relocation_needed = !bfd_is_abs_section(sym_section);
724 sym_addr = (*(q->sym_ptr_ptr))->value;
725 sym_vma = bfd_section_vma(abs_bfd, sym_section);
726 sym_addr += sym_vma + q->addend;
729 case R_H8_DIR32A16: /* currently 32, could be made 16 */
730 if (sym_reloc_size != 4) {
731 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
735 relocation_needed = 1;
736 sym_addr = (*(q->sym_ptr_ptr))->value;
737 sym_vma = bfd_section_vma(abs_bfd, sym_section);
738 sym_addr += sym_vma + q->addend;
742 sym_addr = (*(q->sym_ptr_ptr))->value;
743 sym_addr += sym_vma + q->addend;
744 sym_addr -= (q->address + 2);
745 if (bfd_big_endian(abs_bfd))
746 *(unsigned short *)r_mem =
747 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
751 sym_addr = (*(q->sym_ptr_ptr))->value;
752 sym_addr += sym_vma + q->addend;
753 sym_addr -= (q->address + 1);
754 *(unsigned char *)r_mem = sym_addr;
758 #ifdef TARGET_microblaze
759 case R_MICROBLAZE_64:
760 /* The symbol is split over two consecutive instructions.
761 Flag this to the flat loader by setting the high bit of
762 the relocation symbol. */
764 unsigned char *p = r_mem;
765 unsigned long offset;
768 /* work out the relocation */
769 sym_vma = bfd_section_vma(abs_bfd, sym_section);
770 /* grab any offset from the text */
771 offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
772 /* Update the address */
773 sym_addr += offset + sym_vma + q->addend;
774 /* Write relocated pointer back */
775 p[2] = (sym_addr >> 24) & 0xff;
776 p[3] = (sym_addr >> 16) & 0xff;
777 p[6] = (sym_addr >> 8) & 0xff;
778 p[7] = sym_addr & 0xff;
780 /* create a new reloc entry */
781 flat_relocs = realloc(flat_relocs,
782 (flat_reloc_count + 1) * sizeof(unsigned long));
783 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
785 relocation_needed = 0;
787 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
788 bfd_section_vma(abs_bfd, sym_section));
790 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
791 "section=%s size=%d "
792 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
793 q->address, sym_name, addstr,
794 section_name, sym_reloc_size,
795 sym_addr, section_vma + q->address);
797 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
798 section_vma + q->address);
802 case R_MICROBLAZE_32:
804 unsigned char *p = r_mem;
805 unsigned long offset;
807 /* grab any offset from the text */
808 offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
809 sym_vma = bfd_section_vma(abs_bfd, sym_section);
810 /* This is a horrible kludge. For some
811 reason, *sometimes* the offset is in
812 both addend and the code. Detect
813 it, and cancel the effect. Otherwise
814 the offset gets added twice - ouch.
815 There should be a better test
816 for this condition, based on the
817 BFD data structures */
818 if(offset==q->addend)
821 sym_addr += offset + sym_vma + q->addend;
822 relocation_needed = 1;
825 case R_MICROBLAZE_64_PCREL:
827 //sym_addr = (*(q->sym_ptr_ptr))->value;
828 sym_addr += sym_vma + q->addend;
829 sym_addr -= (q->address + 4);
830 sym_addr = htonl(sym_addr);
832 * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
834 * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
835 /* We've done all the work, so continue
836 to next reloc instead of break */
839 #endif /* TARGET_microblaze */
844 relocation_needed = 1;
845 sym_vma = bfd_section_vma(abs_bfd, sym_section);
846 sym_addr += sym_vma + q->addend;
850 sym_addr += sym_vma + q->addend;
851 sym_addr -= q->address;
853 case R_SPARC_WDISP30:
854 sym_addr = (((*(q->sym_ptr_ptr))->value-
855 q->address) >> 2) & 0x3fffffff;
857 ntohl(*(unsigned long *)r_mem)
862 relocation_needed = 1;
864 sym_vma = bfd_section_vma(abs_bfd, sym_section);
865 sym_addr += sym_vma + q->addend;
867 htonl(*(unsigned long *)r_mem)
872 relocation_needed = 1;
874 sym_vma = bfd_section_vma(abs_bfd, sym_section);
875 sym_addr += sym_vma + q->addend;
876 sym_addr &= 0x000003ff;
878 htonl(*(unsigned long *)r_mem)
882 #endif /* TARGET_sparc */
886 relocation_needed = 1;
887 sym_vma = bfd_section_vma(abs_bfd, sym_section);
888 sym_addr += sym_vma + q->addend;
892 sym_addr += sym_vma + q->addend;
893 sym_addr -= q->address;
895 #endif /* TARGET_sh */
898 #define htoe1l(x) htonl(x)
905 #define DBG_E1 printf
907 #define DBG_E1(x, ... )
910 #define _32BITS_RELOC 0x00000000
911 #define _30BITS_RELOC 0x80000000
912 #define _28BITS_RELOC 0x40000000
915 unsigned long sec_vma, exist_val, S;
917 relocation_needed = 1;
918 DBG_E1("Handling Reloc <CONST31>\n");
919 sec_vma = bfd_section_vma(abs_bfd, sym_section);
920 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
921 sec_vma, sym_addr, q->address);
922 sym_addr = sec_vma + sym_addr;
923 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
924 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
925 exist_val = htoe1l(exist_val);
926 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
927 sym_addr += exist_val;
928 pflags = _30BITS_RELOC;
930 case R_E1_CONST31_PCREL:
931 relocation_needed = 0;
932 DBG_E1("Handling Reloc <CONST31_PCREL>\n");
933 DBG_E1("DONT RELOCATE AT LOADING\n");
934 sec_vma = bfd_section_vma(abs_bfd, sym_section);
935 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
936 sec_vma, sym_addr, q->address);
937 sym_addr = sec_vma + sym_addr;
938 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
940 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
942 q->address = q->address + section_vma;
943 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
945 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
946 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
947 DBG_E1( "sym_addr := sym_addr - q->address - "
948 "sizeof(CONST31_PCREL): [0x%x]\n",
950 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
951 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
952 exist_val = htoe1l(exist_val);
953 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
954 sym_addr |= exist_val;
955 DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr );
957 case R_E1_DIS29W_PCREL:
958 relocation_needed = 0;
959 DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
960 DBG_E1("DONT RELOCATE AT LOADING\n");
961 sec_vma = bfd_section_vma(abs_bfd, sym_section);
962 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
963 sec_vma, sym_addr, q->address);
964 sym_addr = sec_vma + sym_addr;
965 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
967 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
969 q->address = q->address + section_vma;
970 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
972 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
973 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
974 DBG_E1( "sym_addr := sym_addr - q->address - "
975 "sizeof(CONST31_PCREL): [0x%x]\n",
977 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
978 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
979 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
980 exist_val = htoe1l(exist_val);
981 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
982 sym_addr += exist_val;
985 DBG_E1("Handling Reloc <DIS29W>\n");
986 goto DIS29_RELOCATION;
988 DBG_E1("Handling Reloc <DIS29H>\n");
989 goto DIS29_RELOCATION;
991 DBG_E1("Handling Reloc <DIS29B>\n");
993 relocation_needed = 1;
994 sec_vma = bfd_section_vma(abs_bfd, sym_section);
995 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
997 sym_addr = sec_vma + sym_addr;
998 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr);
999 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1000 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1001 exist_val = htoe1l(exist_val);
1002 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1003 sym_addr += exist_val;
1004 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1005 pflags = _28BITS_RELOC;
1007 case R_E1_IMM32_PCREL:
1008 relocation_needed = 0;
1009 DBG_E1("Handling Reloc <IMM32_PCREL>\n");
1010 DBG_E1("DONT RELOCATE AT LOADING\n");
1011 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1012 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1014 sym_addr = sec_vma + sym_addr;
1016 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1017 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1019 q->address = q->address + section_vma;
1020 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1022 if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
1023 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1024 DBG_E1( "sym_addr := sym_addr - q->address - "
1025 "sizeof(CONST31_PCREL): [0x%x]\n",
1027 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1028 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1029 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1030 exist_val = htoe1l(exist_val);
1031 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1032 sym_addr += exist_val;
1035 relocation_needed = 1;
1036 DBG_E1("Handling Reloc <IMM32>\n");
1037 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1038 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1040 sym_addr = sec_vma + sym_addr;
1041 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1042 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1043 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1044 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1045 exist_val = htoe1l(exist_val);
1046 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1047 sym_addr += exist_val;
1048 pflags = _32BITS_RELOC;
1051 relocation_needed = 1;
1052 DBG_E1("Handling Reloc <WORD>\n");
1053 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1054 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1056 sym_addr = sec_vma + sym_addr;
1057 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1058 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
1059 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1060 exist_val = htoe1l(exist_val);
1061 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1062 sym_addr += exist_val;
1063 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1064 pflags = _32BITS_RELOC;
1067 #undef _32BITS_RELOC
1068 #undef _30BITS_RELOC
1069 #undef _28BITS_RELOC
1072 /* missing support for other types of relocs */
1073 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
1079 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
1080 bfd_section_vma(abs_bfd, sym_section));
1084 * for full elf relocation we have to write back the
1085 * start_code relative value to use.
1087 if (!pic_with_got) {
1088 #if defined(TARGET_arm)
1097 * horrible nasty hack to support different endianess
1099 if (!bfd_big_endian(abs_bfd)) {
1111 tmp.l = *(unsigned long *)r_mem;
1112 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
1113 if (((*p)->howto->type != R_ARM_PC24) &&
1114 ((*p)->howto->type != R_ARM_PLT32))
1115 hl |= (tmp.c[i3] << 24);
1116 else if (tmp.c[i2] & 0x80)
1117 hl |= 0xff000000; /* sign extend */
1119 tmp.c[i0] = hl & 0xff;
1120 tmp.c[i1] = (hl >> 8) & 0xff;
1121 tmp.c[i2] = (hl >> 16) & 0xff;
1122 if (((*p)->howto->type != R_ARM_PC24) &&
1123 ((*p)->howto->type != R_ARM_PLT32))
1124 tmp.c[i3] = (hl >> 24) & 0xff;
1125 if ((*p)->howto->type == R_ARM_ABS32)
1126 *(unsigned long *)r_mem = htonl(hl);
1128 *(unsigned long *)r_mem = tmp.l;
1130 #elif defined(TARGET_e1)
1131 #define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/
1132 switch ((*p)->howto->type) {
1134 case R_E1_CONST31_PCREL:
1135 case R_E1_DIS29W_PCREL:
1139 case R_E1_IMM32_PCREL:
1141 DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
1142 (sectionp + q->address + 2), sym_addr );
1143 *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
1147 DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
1148 (sectionp + q->address), sym_addr );
1149 *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
1152 printf("ERROR:Unhandled Relocation. Exiting...\n");
1156 #else /* ! TARGET_arm && ! TARGET_e1 */
1158 switch (q->howto->type) {
1163 /* Do nothing -- for cases we handle,
1164 the bits produced by the linker are
1165 what we want in the final flat file
1166 (and other cases are errors). Note
1167 that unlike most relocated values,
1168 it is stored in little-endian order,
1169 but this is necessary to avoid
1170 trashing the low-bit, and the float
1171 loaders knows about it. */
1173 #endif /* TARGET_V850 */
1175 /* The alignment of the build host
1176 might be stricter than that of the
1177 target, so be careful. We store in
1178 network byte order. */
1179 r_mem[0] = (sym_addr >> 24) & 0xff;
1180 r_mem[1] = (sym_addr >> 16) & 0xff;
1181 r_mem[2] = (sym_addr >> 8) & 0xff;
1182 r_mem[3] = sym_addr & 0xff;
1184 #endif /* !TARGET_arm */
1188 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
1189 "section=%s size=%d "
1190 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
1191 q->address, sym_name, addstr,
1192 section_name, sym_reloc_size,
1193 sym_addr, section_vma + q->address);
1196 * Create relocation entry (PC relative doesn't need this).
1198 if (relocation_needed) {
1199 flat_relocs = realloc(flat_relocs,
1200 (flat_reloc_count + 1) * sizeof(unsigned long));
1202 flat_relocs[flat_reloc_count] = pflags |
1203 (section_vma + q->address);
1206 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
1207 section_vma + q->address);
1209 switch ((*p)->howto->type) {
1211 case R_E1_CONST31_PCREL:
1212 case R_E1_DIS29W_PCREL:
1216 case R_E1_IMM32_PCREL:
1218 flat_relocs[flat_reloc_count] = pflags |
1219 (section_vma + q->address + OPCODE_SIZE);
1221 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1222 flat_relocs[flat_reloc_count] );
1225 flat_relocs[flat_reloc_count] = pflags |
1226 (section_vma + q->address);
1228 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1229 flat_relocs[flat_reloc_count] );
1234 relocation_needed = 0;
1239 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
1240 __FILE__, __LINE__, sym_name, q->address, section_name,
1241 flat_relocs[flat_reloc_count]);
1248 printf("%d bad relocs\n", bad_relocs);
1255 *n_relocs = flat_reloc_count;
1262 /* shared lib symbols stuff */
1265 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
1268 for (i=0; i<number_of_symbols; i++) {
1269 if (symbol_table[i]->section == sec) {
1270 if (!strcmp(symbol_table[i]->name, name)) {
1271 return symbol_table[i]->value;
1279 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
1290 signed short *tab = malloc(32768); /* we don't know how many yet*/
1292 asection *text_section = bfd_get_section_by_name (abfd, ".text");
1294 if (!(ef = fopen(ename, "rb"))) {
1295 fprintf (stderr,"Can't open %s\n",ename);
1299 fgets(libname, 80, ef);
1301 if (number_of_symbols < 0) {
1302 fprintf (stderr,"Corrupt symbol table!\n");
1306 if ((etext_addr = get_symbol("etext",
1309 number_of_symbols)) == -1) {
1310 fprintf (stderr,"Can't find the symbol etext\n");
1316 buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
1318 if ((sym_addr = get_symbol(buf,
1321 number_of_symbols)) == -1) {
1322 fprintf (stderr,"Can't find the symbol %s\n",buf);
1325 tab[++count] = htons(sym_addr - etext_addr);
1333 fprintf (stderr,"*** %d symbols not found\n",foobar);
1337 strcpy((char *)&tab[++count],libname);
1338 tab[0] = htons(count * 2);
1339 write(fd, tab, count * 2 + strlen(libname) + 2);
1345 static char * program;
1347 static void usage(void)
1349 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1350 "[-o <output-file>] <elf-file>\n\n"
1351 " -v : verbose operation\n"
1352 " -r : force load to RAM\n"
1353 " -k : enable kernel trace on load (for debug)\n"
1354 " -z : compress code/data/relocs\n"
1355 " -d : compress data/relocs\n"
1356 " -a : use existing symbol references\n"
1357 " instead of recalculating from\n"
1358 " relocation info\n"
1359 " -R reloc-file : read relocations from a separate file\n"
1360 " -p abs-pic-file : GOT/PIC processing with files\n"
1361 " -s stacksize : set application stack size\n"
1362 " -o output-file : output file name\n\n",
1364 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1369 /* Write NUM zeroes to STREAM. */
1370 static void write_zeroes (unsigned long num, FILE *stream)
1374 /* It'd be nice if we could just use fseek, but that doesn't seem to
1375 work for stdio output files. */
1376 bzero(zeroes, 1024);
1377 while (num > sizeof(zeroes)) {
1378 fwrite(zeroes, sizeof(zeroes), 1, stream);
1379 num -= sizeof(zeroes);
1382 fwrite(zeroes, num, 1, stream);
1387 int main(int argc, char *argv[])
1390 bfd *rel_bfd, *abs_bfd;
1392 char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1401 asymbol **symbol_table;
1402 long number_of_symbols;
1404 unsigned long data_len = 0;
1405 unsigned long bss_len = 0;
1406 unsigned long text_len = 0;
1407 unsigned long reloc_len;
1409 unsigned long data_vma = ~0;
1410 unsigned long bss_vma = ~0;
1411 unsigned long text_vma = ~0;
1413 unsigned long text_offs;
1417 unsigned long *reloc;
1419 struct flat_hdr hdr;
1431 #else /* We need plenty of stack for both of them (Aggregate and Register) */
1435 while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1462 stack = atoi(optarg);
1468 fprintf(stderr, "%s Unknown option\n", argv[0]);
1475 * if neither the -r or -p options was given, default to
1476 * a RAM load as that is the only option that makes sense.
1478 if (!load_to_ram && !pfile)
1481 filename = fname = argv[argc-1];
1492 if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1493 fprintf(stderr, "Can't open %s\n", rel_file);
1497 if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1498 fprintf(stderr, "File is not an object file\n");
1502 if (abs_file == rel_file)
1503 abs_bfd = rel_bfd; /* one file does all */
1505 if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1506 fprintf(stderr, "Can't open %s\n", abs_file);
1510 if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1511 fprintf(stderr, "File is not an object file\n");
1516 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1517 fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1521 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1522 /* `Absolute' file is not absolute, so neither are address
1523 contained therein. */
1525 "%s: `-a' option specified with non-fully-resolved input file\n",
1526 bfd_get_filename (abs_bfd));
1530 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1532 /* Group output sections into text, data, and bss, and calc their sizes. */
1533 for (s = abs_bfd->sections; s != NULL; s = s->next) {
1534 unsigned long *vma, *len;
1535 bfd_size_type sec_size;
1538 if (s->flags & SEC_CODE) {
1541 } else if (s->flags & SEC_DATA) {
1544 } else if (s->flags & SEC_ALLOC) {
1550 sec_size = bfd_section_size(abs_bfd, s);
1551 sec_vma = bfd_section_vma(abs_bfd, s);
1553 if (sec_vma < *vma) {
1555 *len += sec_vma - *vma;
1559 } else if (sec_vma + sec_size > *vma + *len)
1560 *len = sec_vma + sec_size - *vma;
1563 if (text_len == 0) {
1564 fprintf (stderr, "%s: no .text section", abs_file);
1568 text = malloc(text_len);
1571 printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1573 /* Read in all text sections. */
1574 for (s = abs_bfd->sections; s != NULL; s = s->next)
1575 if (s->flags & SEC_CODE)
1576 if (!bfd_get_section_contents(abs_bfd, s,
1577 text + (s->vma - text_vma), 0,
1578 bfd_section_size(abs_bfd, s)))
1580 fprintf(stderr, "read error section %s\n", s->name);
1584 if (data_len == 0) {
1585 fprintf (stderr, "%s: no .data section", abs_file);
1588 data = malloc(data_len);
1591 printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1593 if ((text_vma + text_len) != data_vma) {
1594 if ((text_vma + text_len) > data_vma) {
1595 printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1599 printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1600 data_vma, text_len);
1601 text_len = data_vma - text_vma;
1604 /* Read in all data sections. */
1605 for (s = abs_bfd->sections; s != NULL; s = s->next)
1606 if (s->flags & SEC_DATA)
1607 if (!bfd_get_section_contents(abs_bfd, s,
1608 data + (s->vma - data_vma), 0,
1609 bfd_section_size(abs_bfd, s)))
1611 fprintf(stderr, "read error section %s\n", s->name);
1615 /* Put common symbols in bss. */
1616 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1619 printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1621 if ((data_vma + data_len) != bss_vma) {
1622 if ((data_vma + data_len) > bss_vma) {
1623 printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1628 printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1629 bss_vma, text_len, data_len, text_len + data_len);
1630 data_len = bss_vma - data_vma;
1633 reloc = (unsigned long *)
1634 output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1635 text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1638 printf("No relocations in code!\n");
1640 text_offs = real_address_bits(text_vma);
1642 /* Fill in the binflt_flat header */
1643 memcpy(hdr.magic,"bFLT",4);
1644 hdr.rev = htonl(FLAT_VERSION);
1645 hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1646 hdr.data_start = htonl(16 * 4 + text_offs + text_len);
1647 hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len);
1648 hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1649 hdr.stack_size = htonl(stack); /* FIXME */
1650 hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1651 hdr.reloc_count = htonl(reloc_len);
1653 | (load_to_ram ? FLAT_FLAG_RAM : 0)
1654 | (ktrace ? FLAT_FLAG_KTRACE : 0)
1655 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1656 | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1658 hdr.build_date = htonl((unsigned long)time(NULL));
1659 bzero(hdr.filler, sizeof(hdr.filler));
1661 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1664 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1665 text_len, data_len, bss_len);
1667 printf(", relocs=0x%04x", reloc_len);
1672 ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1673 strcpy(ofile, fname);
1674 strcat(ofile, ".bflt");
1677 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1678 fprintf (stderr, "Can't open output file %s\n", ofile);
1682 write(fd, &hdr, sizeof(hdr));
1686 * get the compression command ready
1688 sprintf(cmd, "gzip -f -9 >> %s", ofile);
1690 #define START_COMPRESSOR do { \
1696 if (!(gf = popen(cmd, "wb"))) { \
1697 fprintf(stderr, "Can't run cmd %s\n", cmd); \
1703 gf = fopen(ofile, "ab"); /* Add 'b' to support non-posix (ie windows) */
1705 fprintf(stderr, "Can't open file %s for writing\n", ofile); \
1712 /* Fill in any hole at the beginning of the text segment. */
1714 printf("ZERO before text len=0x%x\n", text_offs);
1715 write_zeroes(text_offs, gf);
1717 /* Write the text segment. */
1718 fwrite(text, text_len, 1, gf);
1723 /* Write the data segment. */
1724 fwrite(data, data_len, 1, gf);
1727 fwrite(reloc, reloc_len * 4, 1, gf);