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) 2006 Support the -a (use_resolved) option for TARGET_arm.
10 * Shaun Jackman <sjackman@gmail.com>
11 * (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>
12 * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
13 * (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
14 * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
15 * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
16 * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
17 * (c) 2001, zflat support <davidm@snapgear.com>
18 * (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
19 * David McCullough <davidm@snapgear.com>
21 * Now supports PIC with GOT tables. This works by taking a '.elf' file
22 * and a fully linked elf executable (at address 0) and produces a flat
23 * file that can be loaded with some fixups. It still supports the old
24 * style fully relocatable elf format files.
26 * Originally obj-res.c
28 * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
29 * (c) 1998, D. Jeff Dionne
30 * (c) 1998, The Silver Hammer Group Ltd.
31 * (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
33 * This is Free Software, under the GNU Public Licence v2 or greater.
35 * Relocation added March 1997, Kresten Krab Thorup
36 * krab@california.daimi.aau.dk
39 #include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
40 #include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */
41 #include <stdarg.h> /* Allows va_list to exist in the these namespaces */
42 #include <string.h> /* Userland prototypes of the string handling funcs */
44 #include <unistd.h> /* Userland prototypes of the Unix std system calls */
45 #include <fcntl.h> /* Flag value for file handling functions */
48 /* from $(INSTALLDIR)/include */
49 #include <bfd.h> /* Main header file for the BFD library */
50 #include <libiberty.h>
53 const char *elf2flt_progname;
55 #if defined(TARGET_h8300)
56 #include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
57 #elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(TARGET_nios) || defined(TARGET_nios2)
58 #include "cygwin-elf.h" /* Cygwin uses a local copy */
59 #elif defined(TARGET_microblaze)
60 #include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
62 #include <elf.h> /* TARGET_* ELF support for the BFD library */
65 /* Always include Blackfin-specific defines in addition to common ELF stuff
66 * above as the common elf headers often do not have our relocs.
68 #if defined(TARGET_bfin) && !defined(R_BFIN_RIMM16)
72 #if defined(__MINGW32__)
76 /* from uClinux-x.x.x/include/linux */
77 #include "flat.h" /* Binary flat header description */
88 #if defined(TARGET_m68k)
89 #define ARCH "m68k/coldfire"
90 #elif defined(TARGET_arm)
92 #elif defined(TARGET_sparc)
94 #elif defined(TARGET_v850)
96 #elif defined(TARGET_sh)
98 #elif defined(TARGET_h8300)
100 #elif defined(TARGET_microblaze)
101 #define ARCH "microblaze"
102 #elif defined(TARGET_e1)
103 #define ARCH "e1-coff"
104 #elif defined(TARGET_bfin)
106 #elif defined(TARGET_nios)
108 #elif defined(TARGET_nios2)
111 #error "Don't know how to support your CPU architecture??"
114 #if defined(TARGET_m68k) || defined(TARGET_h8300) || defined(TARGET_bfin)
116 * Define a maximum number of bytes allowed in the offset table.
117 * We'll fail if the table is larger than this.
119 * This limit may be different for platforms other than m68k, but
120 * 8000 entries is a lot, trust me :-) (davidm)
122 #define GOT_LIMIT 32767
124 * we have to mask out the shared library id here and there, this gives
125 * us the real address bits when needed
127 #define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
129 #define real_address_bits(x) (x)
137 int verbose = 0; /* extra output when running */
138 int pic_with_got = 0; /* do elf/got processing with PIC code */
139 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
140 int ktrace = 0; /* instruct loader output kernel trace on load */
141 int docompress = 0; /* 1 = compress everything, 2 = compress data only */
142 int use_resolved = 0; /* If true, get the value of symbol references from */
143 /* the program contents, not from the relocation table. */
144 /* In this case, the input ELF file must be already */
145 /* fully resolved (using the `-q' flag with recent */
146 /* versions of GNU ld will give you a fully resolved */
147 /* output file with relocation entries). */
149 /* Set if the text section contains any relocations. If it does, we must
150 set the load_to_ram flag. */
151 int text_has_relocs = 0;
154 get_symbols (bfd *abfd, long *num)
156 int32_t storage_needed;
157 asymbol **symbol_table;
158 long number_of_symbols;
160 storage_needed = bfd_get_symtab_upper_bound (abfd);
162 if (storage_needed < 0)
165 if (storage_needed == 0)
168 symbol_table = xmalloc (storage_needed);
170 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
172 if (number_of_symbols < 0)
175 *num = number_of_symbols;
182 dump_symbols(asymbol **symbol_table, long number_of_symbols)
185 printf("SYMBOL TABLE:\n");
186 for (i=0; i<number_of_symbols; i++) {
187 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
188 symbol_table[i]->value);
197 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
200 for (i=0; i<number_of_symbols; i++) {
201 if (symbol_table[i]->section == sec) {
202 if (!strcmp(symbol_table[i]->name, name)) {
203 return symbol_table[i]->value;
214 get_gp_value(asymbol **symbol_table, long number_of_symbols)
217 for (i=0; i<number_of_symbols; i++) {
218 if (!strcmp(symbol_table[i]->name, "_gp"))
219 return symbol_table[i]->value;
228 add_com_to_bss(asymbol **symbol_table, int32_t number_of_symbols, int32_t bss_len)
234 for (i=0; i<number_of_symbols; i++) {
235 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
236 offset = bss_len + comsize;
237 comsize += symbol_table[i]->value;
238 symbol_table[i]->value = offset;
245 /* FUNCTION : weak_und_symbol
246 ABSTRACT : return true if symbol is weak and undefined.
249 weak_und_symbol(const char *reloc_section_name,
250 struct bfd_symbol *symbol)
252 if (!(strstr (reloc_section_name, "text")
253 || strstr (reloc_section_name, "data")
254 || strstr (reloc_section_name, "bss"))) {
255 if (symbol->flags & BSF_WEAK) {
257 fprintf(stderr, "found weak undefined symbol %s\n", symbol->name);
266 bfin_set_reloc (uint32_t *reloc,
267 const char *reloc_section_name,
268 const char *sym_name,
269 struct bfd_symbol *symbol,
270 int sp, int32_t offset)
272 unsigned int type = 0;
275 if (strstr (reloc_section_name, "stack")) {
277 printf ("Stack-relative reloc, offset %08lx\n", offset);
278 /* This must be a stack_start reloc for stack checking. */
281 val = (offset & ((1 << 26) - 1));
282 val |= (sp & (1 << 3) - 1) << 26;
288 static bfd *compare_relocs_bfd;
291 compare_relocs (const void *pa, const void *pb)
293 const arelent *const *a = pa, *const *b = pb;
294 const arelent *ra = *a, *rb = *b;
295 unsigned long va, vb;
296 uint32_t a_vma, b_vma;
298 if (!ra->sym_ptr_ptr || !*ra->sym_ptr_ptr)
300 else if (!rb->sym_ptr_ptr || !*rb->sym_ptr_ptr)
303 a_vma = bfd_section_vma(compare_relocs_bfd,
304 (*(ra->sym_ptr_ptr))->section);
305 b_vma = bfd_section_vma(compare_relocs_bfd,
306 (*(rb->sym_ptr_ptr))->section);
307 va = (*(ra->sym_ptr_ptr))->value + a_vma + ra->addend;
308 vb = (*(rb->sym_ptr_ptr))->value + b_vma + rb->addend;
317 int number_of_symbols,
319 unsigned char *text, int text_len, uint32_t text_vma,
320 unsigned char *data, int data_len, uint32_t data_vma,
323 uint32_t *flat_relocs;
324 asection *a, *sym_section, *r;
325 arelent **relpp, **p, *q;
326 const char *sym_name, *section_name;
327 unsigned char *sectionp;
328 unsigned long pflags;
330 uint32_t sym_addr, sym_vma, section_vma;
331 int relsize, relcount;
332 int flat_reloc_count;
333 int sym_reloc_size, rc;
339 unsigned long persistent_data = 0;
343 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
344 "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
345 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
346 text, text_len, data, data_len);
350 dump_symbols(symbols, number_of_symbols);
355 flat_reloc_count = 0;
359 /* Determine how big our offset table is in bytes.
360 * This isn't too difficult as we've terminated the table with -1.
361 * Also note that both the relocatable and absolute versions have this
362 * terminator even though the relocatable one doesn't have the GOT!
364 if (pic_with_got && !use_resolved) {
365 uint32_t *lp = (uint32_t *)data;
366 /* Should call ntohl(*lp) here but is isn't going to matter */
367 while (*lp != 0xffffffff) lp++;
368 got_size = ((unsigned char *)lp) - data;
370 printf("GOT table contains %d entries (%d bytes)\n",
371 got_size/sizeof(uint32_t), got_size);
373 if (got_size > GOT_LIMIT)
374 fatal("GOT too large: %d bytes (limit = %d bytes)",
375 got_size, GOT_LIMIT);
379 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
380 section_vma = bfd_section_vma(abs_bfd, a);
383 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
384 a->flags, section_vma);
386 // if (bfd_is_abs_section(a))
388 if (bfd_is_und_section(a))
390 if (bfd_is_com_section(a))
392 // if ((a->flags & SEC_RELOC) == 0)
396 * Only relocate things in the data sections if we are PIC/GOT.
397 * otherwise do text as well
399 if (!pic_with_got && (a->flags & SEC_CODE))
400 sectionp = text + (a->vma - text_vma);
401 else if (a->flags & SEC_DATA)
402 sectionp = data + (a->vma - data_vma);
406 /* Now search for the equivalent section in the relocation binary
407 * and use that relocation information to build reloc entries
410 for (r=rel_bfd->sections; r != NULL; r=r->next)
411 if (strcmp(a->name, r->name) == 0)
416 printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
417 r->flags, bfd_section_vma(abs_bfd, r));
418 if ((r->flags & SEC_RELOC) == 0)
420 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
423 printf("%s(%d): no relocation entries section=0x%x\n",
424 __FILE__, __LINE__, r->name);
428 symb = get_symbols(rel_bfd, &nsymb);
429 relpp = xmalloc(relsize);
431 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
434 printf("%s(%d): no relocation entries section=%s\n",
435 __FILE__, __LINE__, r->name);
439 compare_relocs_bfd = abs_bfd;
440 qsort (relpp, relcount, sizeof *relpp, compare_relocs);
442 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
443 unsigned char *r_mem;
444 int relocation_needed = 0;
446 #ifdef TARGET_microblaze
447 /* The MICROBLAZE_XX_NONE relocs can be skipped.
448 They represent PC relative branches that the
449 linker has already resolved */
451 switch ((*p)->howto->type)
453 case R_MICROBLAZE_NONE:
454 case R_MICROBLAZE_64_NONE:
455 case R_MICROBLAZE_32_PCREL_LO:
458 #endif /* TARGET_microblaze */
461 /* Skip this relocation entirely if possible (we
462 do this early, before doing any other
463 processing on it). */
464 switch ((*p)->howto->type) {
465 #ifdef R_V850_9_PCREL
468 #ifdef R_V850_22_PCREL
469 case R_V850_22_PCREL:
471 #ifdef R_V850_SDA_16_16_OFFSET
472 case R_V850_SDA_16_16_OFFSET:
474 #ifdef R_V850_SDA_15_16_OFFSET
475 case R_V850_SDA_15_16_OFFSET:
477 #ifdef R_V850_ZDA_15_16_OFFSET
478 case R_V850_ZDA_15_16_OFFSET:
480 #ifdef R_V850_TDA_6_8_OFFSET
481 case R_V850_TDA_6_8_OFFSET:
483 #ifdef R_V850_TDA_7_8_OFFSET
484 case R_V850_TDA_7_8_OFFSET:
486 #ifdef R_V850_TDA_7_7_OFFSET
487 case R_V850_TDA_7_7_OFFSET:
489 #ifdef R_V850_TDA_16_16_OFFSET
490 case R_V850_TDA_16_16_OFFSET:
492 #ifdef R_V850_TDA_4_5_OFFSET
493 case R_V850_TDA_4_5_OFFSET:
495 #ifdef R_V850_TDA_4_4_OFFSET
496 case R_V850_TDA_4_4_OFFSET:
498 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
499 case R_V850_SDA_16_16_SPLIT_OFFSET:
501 #ifdef R_V850_CALLT_6_7_OFFSET
502 case R_V850_CALLT_6_7_OFFSET:
504 #ifdef R_V850_CALLT_16_16_OFFSET
505 case R_V850_CALLT_16_16_OFFSET:
507 /* These are relative relocations, which
508 have already been fixed up by the
509 linker at this point, so just ignore
513 #endif /* USE_V850_RELOCS */
516 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
517 sym_name = (*(q->sym_ptr_ptr))->name;
518 sym_section = (*(q->sym_ptr_ptr))->section;
519 section_name=(*(q->sym_ptr_ptr))->section->name;
521 printf("ERROR: undefined relocation entry\n");
526 /* Adjust the address to account for the GOT table which wasn't
527 * present in the relative file link.
529 if (pic_with_got && !use_resolved)
530 q->address += got_size;
533 /* A pointer to what's being relocated, used often
535 r_mem = sectionp + q->address;
538 * Fixup offset in the actual section.
541 #if !defined TARGET_e1 && !defined TARGET_bfin
542 if ((sym_addr = get_symbol_offset((char *) sym_name,
543 sym_section, symbols, number_of_symbols)) == -1) {
547 sym_addr = (*(q->sym_ptr_ptr))->value;
550 /* Use the address of the symbol already in
551 the program text. How this is handled may
552 still depend on the particular relocation
554 switch (q->howto->type) {
558 /* We specially handle adjacent
559 HI16_S/ZDA_15_16_OFFSET and
560 HI16_S/LO16 pairs that reference the
561 same address (these are usually
562 movhi/ld and movhi/movea pairs,
565 r2_type = R_V850_NONE;
567 r2_type = p[1]->howto->type;
568 if ((r2_type == R_V850_ZDA_15_16_OFFSET
569 || r2_type == R_V850_LO16)
570 && (p[0]->sym_ptr_ptr
571 == p[1]->sym_ptr_ptr)
572 && (p[0]->addend == p[1]->addend))
574 relocation_needed = 1;
577 case R_V850_ZDA_15_16_OFFSET:
585 /* We don't really need the
586 actual value -- the bits
587 produced by the linker are
588 what we want in the final
589 flat file -- but get it
593 unsigned char *r2_mem =
601 /* Sign extend LO. */
605 /* Maybe ignore the LSB
609 if (r2_type != R_V850_LO16)
617 goto bad_resolved_reloc;
621 /* See if this is actually the
622 2nd half of a pair. */
624 && (p[-1]->howto->type
626 && (p[-1]->sym_ptr_ptr
627 == p[0]->sym_ptr_ptr)
628 && (p[-1]->addend == p[0]->addend))
629 break; /* not an error */
631 goto bad_resolved_reloc;
634 goto bad_resolved_reloc;
636 goto good_32bit_resolved_reloc;
637 #elif defined(TARGET_arm)
639 relocation_needed = 1;
648 relocation_needed = 0;
651 goto bad_resolved_reloc;
652 #elif defined(TARGET_m68k)
654 goto good_32bit_resolved_reloc;
657 /* The linker has already resolved
658 PC relocs for us. In PIC links,
659 the symbol must be in the data
664 goto bad_resolved_reloc;
665 #elif defined TARGET_bfin
669 sym_vma = bfd_section_vma(abs_bfd, sym_section);
670 sym_addr += sym_vma + q->addend;
672 if (weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))
674 if (q->howto->type == R_BFIN_RIMM16 && (0xFFFF0000 & sym_addr)) {
675 fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name);
678 if ((0xFFFF0000 & sym_addr) != persistent_data) {
679 flat_relocs = (uint32_t *)
680 (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
682 printf ("New persistent data for %08lx\n", sym_addr);
683 persistent_data = 0xFFFF0000 & sym_addr;
684 flat_relocs[flat_reloc_count++]
685 = (sym_addr >> 16) | (3 << 26);
688 flat_relocs = (uint32_t *)
689 (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
690 if (bfin_set_reloc (flat_relocs + flat_reloc_count,
691 sym_section->name, sym_name,
693 q->howto->type == R_BFIN_HUIMM16 ? 1 : 0,
694 section_vma + q->address))
696 if (a->flags & SEC_CODE)
701 case R_BFIN_BYTE4_DATA:
702 sym_vma = bfd_section_vma(abs_bfd, sym_section);
703 sym_addr += sym_vma + q->addend;
705 if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))
708 flat_relocs = (uint32_t *)
709 (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
710 if (bfin_set_reloc (flat_relocs + flat_reloc_count,
711 sym_section->name, sym_name,
713 2, section_vma + q->address))
715 if (a->flags & SEC_CODE)
722 /* The default is to assume that the
723 relocation is relative and has
724 already been fixed up by the
725 linker (perhaps we ought to make
726 give an error by default, and
727 require `safe' relocations to be
728 enumberated explicitly?). */
729 goto good_32bit_resolved_reloc;
731 good_32bit_resolved_reloc:
732 if (bfd_big_endian (abs_bfd))
744 relocation_needed = 1;
748 printf("ERROR: reloc type %s unsupported in this context\n",
754 /* Calculate the sym address ourselves. */
755 sym_reloc_size = bfd_get_reloc_size(q->howto);
757 #if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin) && !defined(TARGET_m68k)
758 if (sym_reloc_size != 4) {
759 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
760 (*p)->howto->type, sym_reloc_size, sym_name);
767 switch ((*p)->howto->type) {
769 #if defined(TARGET_m68k)
771 relocation_needed = 1;
772 sym_vma = bfd_section_vma(abs_bfd, sym_section);
773 sym_addr += sym_vma + q->addend;
778 sym_addr += sym_vma + q->addend;
779 sym_addr -= q->address;
783 #if defined(TARGET_arm)
785 relocation_needed = 1;
788 "%s vma=0x%x, value=0x%x, address=0x%x "
789 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
791 sym_vma, (*(q->sym_ptr_ptr))->value,
792 q->address, sym_addr,
793 (*p)->howto->rightshift,
795 sym_vma = bfd_section_vma(abs_bfd, sym_section);
796 sym_addr += sym_vma + q->addend;
800 /* Should be fine as is */
805 "%s vma=0x%x, value=0x%x, address=0x%x "
806 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
808 sym_vma, (*(q->sym_ptr_ptr))->value,
809 q->address, sym_addr,
810 (*p)->howto->rightshift,
814 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
820 relocation_needed = 1;
821 sym_vma = bfd_section_vma(abs_bfd, sym_section);
822 sym_addr += sym_vma + q->addend;
824 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
825 #ifdef R_V850_ZDA_16_16_OFFSET
826 case R_V850_ZDA_16_16_OFFSET:
828 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
829 case R_V850_ZDA_16_16_SPLIT_OFFSET:
831 /* Can't support zero-relocations. */
832 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
833 sym_name, q->addend);
835 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
836 #endif /* TARGET_v850 */
840 if (sym_reloc_size != 4) {
841 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
845 relocation_needed = 1;
846 sym_addr = (*(q->sym_ptr_ptr))->value;
848 r_mem -= 1; /* tracks q->address */
849 sym_vma = bfd_section_vma(abs_bfd, sym_section);
850 sym_addr += sym_vma + q->addend;
851 sym_addr |= (*(unsigned char *)r_mem<<24);
854 if (sym_reloc_size != 4) {
855 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
859 /* Absolute symbol done not relocation */
860 relocation_needed = !bfd_is_abs_section(sym_section);
861 sym_addr = (*(q->sym_ptr_ptr))->value;
862 sym_vma = bfd_section_vma(abs_bfd, sym_section);
863 sym_addr += sym_vma + q->addend;
866 case R_H8_DIR32A16: /* currently 32, could be made 16 */
867 if (sym_reloc_size != 4) {
868 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
872 relocation_needed = 1;
873 sym_addr = (*(q->sym_ptr_ptr))->value;
874 sym_vma = bfd_section_vma(abs_bfd, sym_section);
875 sym_addr += sym_vma + q->addend;
879 sym_addr = (*(q->sym_ptr_ptr))->value;
880 sym_addr += sym_vma + q->addend;
881 sym_addr -= (q->address + 2);
882 if (bfd_big_endian(abs_bfd))
883 *(unsigned short *)r_mem =
884 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
888 sym_addr = (*(q->sym_ptr_ptr))->value;
889 sym_addr += sym_vma + q->addend;
890 sym_addr -= (q->address + 1);
891 *(unsigned char *)r_mem = sym_addr;
895 #ifdef TARGET_microblaze
896 case R_MICROBLAZE_64:
897 /* The symbol is split over two consecutive instructions.
898 Flag this to the flat loader by setting the high bit of
899 the relocation symbol. */
901 unsigned char *p = r_mem;
904 /* work out the relocation */
905 sym_vma = bfd_section_vma(abs_bfd, sym_section);
906 sym_addr += sym_vma + q->addend;
907 /* Write relocated pointer back */
908 p[2] = (sym_addr >> 24) & 0xff;
909 p[3] = (sym_addr >> 16) & 0xff;
910 p[6] = (sym_addr >> 8) & 0xff;
911 p[7] = sym_addr & 0xff;
913 /* create a new reloc entry */
914 flat_relocs = realloc(flat_relocs,
915 (flat_reloc_count + 1) * sizeof(uint32_t));
916 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
918 relocation_needed = 0;
920 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
921 bfd_section_vma(abs_bfd, sym_section));
923 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
924 "section=%s size=%d "
925 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
926 q->address, sym_name, addstr,
927 section_name, sym_reloc_size,
928 sym_addr, section_vma + q->address);
930 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
931 section_vma + q->address);
935 case R_MICROBLAZE_32:
937 unsigned char *p = r_mem;
939 sym_vma = bfd_section_vma(abs_bfd, sym_section);
940 sym_addr += sym_vma + q->addend;
941 relocation_needed = 1;
944 case R_MICROBLAZE_64_PCREL:
946 sym_addr += sym_vma + q->addend;
947 sym_addr -= (q->address + 4);
948 sym_addr = htonl(sym_addr);
950 * ((unsigned short *) (r_mem+2)) = (sym_addr) & 0xFFFF;
952 * ((unsigned short *) (r_mem+6)) = (sym_addr >> 16) & 0xFFFF;
953 /* We've done all the work, so continue
954 to next reloc instead of break */
957 #endif /* TARGET_microblaze */
960 #define htoniosl(x) (x)
961 #define niostohl(x) (x)
962 case R_NIOS2_BFD_RELOC_32:
963 relocation_needed = 1;
964 pflags = (FLAT_NIOS2_R_32 << 28);
965 sym_vma = bfd_section_vma(abs_bfd, sym_section);
966 sym_addr += sym_vma + q->addend;
967 /* modify target, in target order */
968 *(unsigned long *)r_mem = htoniosl(sym_addr);
972 unsigned long exist_val;
973 relocation_needed = 1;
974 pflags = (FLAT_NIOS2_R_CALL26 << 28);
975 sym_vma = bfd_section_vma(abs_bfd, sym_section);
976 sym_addr += sym_vma + q->addend;
978 /* modify target, in target order */
979 // exist_val = niostohl(*(unsigned long *)r_mem);
980 exist_val = ((sym_addr >> 2) << 6);
981 *(unsigned long *)r_mem = htoniosl(exist_val);
984 case R_NIOS2_HIADJ16:
987 unsigned long exist_val;
989 /* handle the adjacent HI/LO pairs */
991 r2_type = R_NIOS2_NONE;
993 r2_type = p[1]->howto->type;
994 if ((r2_type == R_NIOS2_LO16)
995 && (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)
996 && (p[0]->addend == p[1]->addend))
998 unsigned char * r2_mem = sectionp + p[1]->address;
999 if (p[1]->address - q->address!=4)
1000 printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);
1001 relocation_needed = 1;
1002 pflags = (q->howto->type == R_NIOS2_HIADJ16)
1003 ? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
1006 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1007 sym_addr += sym_vma + q->addend;
1009 /* modify high 16 bits, in target order */
1010 exist_val = niostohl(*(unsigned long *)r_mem);
1011 exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1012 if (q->howto->type == R_NIOS2_HIADJ16)
1013 exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);
1015 exist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);
1016 *(unsigned long *)r_mem = htoniosl(exist_val);
1018 /* modify low 16 bits, in target order */
1019 exist_val = niostohl(*(unsigned long *)r2_mem);
1020 exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1021 exist_val |= ((sym_addr & 0xFFFF) << 6);
1022 *(unsigned long *)r2_mem = htoniosl(exist_val);
1025 goto NIOS2_RELOC_ERR;
1031 unsigned long exist_val, temp;
1032 //long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);
1033 long gp = get_gp_value(symbols, number_of_symbols);
1035 printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);
1036 goto NIOS2_RELOC_ERR;
1038 /* _gp holds a absolute value, otherwise the ld cannot generate correct code */
1039 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1040 //printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
1041 sym_addr += sym_vma + q->addend;
1043 //printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);
1044 /* modify the target, in target order (little_endian) */
1045 exist_val = niostohl(*(unsigned long *)r_mem);
1046 temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);
1048 temp |= (exist_val & 0x3f);
1049 *(unsigned long *)r_mem = htoniosl(temp);
1051 printf("omit: offset=0x%x symbol=%s%s "
1052 "section=%s size=%d "
1053 "fixup=0x%x (reloc=0x%x) GPREL\n",
1054 q->address, sym_name, addstr,
1055 section_name, sym_reloc_size,
1056 sym_addr, section_vma + q->address);
1059 case R_NIOS2_PCREL16:
1061 unsigned long exist_val;
1063 sym_addr += sym_vma + q->addend;
1064 sym_addr -= (q->address + 4);
1065 /* modify the target, in target order (little_endian) */
1066 exist_val = niostohl(*(unsigned long *)r_mem);
1067 exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1068 exist_val |= ((sym_addr & 0xFFFF) << 6);
1069 *(unsigned long *)r_mem = htoniosl(exist_val);
1071 printf("omit: offset=0x%x symbol=%s%s "
1072 "section=%s size=%d "
1073 "fixup=0x%x (reloc=0x%x) PCREL\n",
1074 q->address, sym_name, addstr,
1075 section_name, sym_reloc_size,
1076 sym_addr, section_vma + q->address);
1081 /* check if this is actually the 2nd half of a pair */
1083 && ((p[-1]->howto->type == R_NIOS2_HIADJ16)
1084 || (p[-1]->howto->type == R_NIOS2_HI16))
1085 && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
1086 && (p[-1]->addend == p[0]->addend)) {
1088 printf("omit: offset=0x%x symbol=%s%s "
1089 "section=%s size=%d LO16\n",
1090 q->address, sym_name, addstr,
1091 section_name, sym_reloc_size);
1095 /* error, fall through */
1099 case R_NIOS2_CACHE_OPX:
1103 case R_NIOS2_BFD_RELOC_16:
1104 case R_NIOS2_BFD_RELOC_8:
1105 case R_NIOS2_GNU_VTINHERIT:
1106 case R_NIOS2_GNU_VTENTRY:
1111 printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);
1114 #endif /* TARGET_nios2 */
1119 relocation_needed = 1;
1120 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1121 sym_addr += sym_vma + q->addend;
1125 sym_addr += sym_vma + q->addend;
1126 sym_addr -= q->address;
1128 case R_SPARC_WDISP30:
1129 sym_addr = (((*(q->sym_ptr_ptr))->value-
1130 q->address) >> 2) & 0x3fffffff;
1132 ntohl(*(uint32_t *)r_mem)
1137 relocation_needed = 1;
1138 pflags = 0x80000000;
1139 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1140 sym_addr += sym_vma + q->addend;
1142 htonl(*(uint32_t *)r_mem)
1147 relocation_needed = 1;
1148 pflags = 0x40000000;
1149 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1150 sym_addr += sym_vma + q->addend;
1151 sym_addr &= 0x000003ff;
1153 htonl(*(uint32_t *)r_mem)
1157 #endif /* TARGET_sparc */
1162 relocation_needed = 1;
1163 sym_vma = bfd_section_vma(abs_bfd, sym_section);
1164 sym_addr += sym_vma + q->addend;
1168 sym_addr += sym_vma + q->addend;
1169 sym_addr -= q->address;
1171 #endif /* TARGET_sh */
1174 #define htoe1l(x) htonl(x)
1181 #define DBG_E1 printf
1183 #define DBG_E1(x, ... )
1186 #define _32BITS_RELOC 0x00000000
1187 #define _30BITS_RELOC 0x80000000
1188 #define _28BITS_RELOC 0x40000000
1191 unsigned long sec_vma, exist_val, S;
1193 relocation_needed = 1;
1194 DBG_E1("Handling Reloc <CONST31>\n");
1195 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1196 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1197 sec_vma, sym_addr, q->address);
1198 sym_addr = sec_vma + sym_addr;
1199 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1200 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1201 exist_val = htoe1l(exist_val);
1202 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1203 sym_addr += exist_val;
1204 pflags = _30BITS_RELOC;
1206 case R_E1_CONST31_PCREL:
1207 relocation_needed = 0;
1208 DBG_E1("Handling Reloc <CONST31_PCREL>\n");
1209 DBG_E1("DONT RELOCATE AT LOADING\n");
1210 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1211 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1212 sec_vma, sym_addr, q->address);
1213 sym_addr = sec_vma + sym_addr;
1214 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1216 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1218 q->address = q->address + section_vma;
1219 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1221 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
1222 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1223 DBG_E1( "sym_addr := sym_addr - q->address - "
1224 "sizeof(CONST31_PCREL): [0x%x]\n",
1226 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1227 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1228 exist_val = htoe1l(exist_val);
1229 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1230 sym_addr |= exist_val;
1231 DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr );
1233 case R_E1_DIS29W_PCREL:
1234 relocation_needed = 0;
1235 DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
1236 DBG_E1("DONT RELOCATE AT LOADING\n");
1237 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1238 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1239 sec_vma, sym_addr, q->address);
1240 sym_addr = sec_vma + sym_addr;
1241 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1243 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1245 q->address = q->address + section_vma;
1246 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1248 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
1249 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1250 DBG_E1( "sym_addr := sym_addr - q->address - "
1251 "sizeof(CONST31_PCREL): [0x%x]\n",
1253 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1254 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1255 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1256 exist_val = htoe1l(exist_val);
1257 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1258 sym_addr += exist_val;
1261 DBG_E1("Handling Reloc <DIS29W>\n");
1262 goto DIS29_RELOCATION;
1264 DBG_E1("Handling Reloc <DIS29H>\n");
1265 goto DIS29_RELOCATION;
1267 DBG_E1("Handling Reloc <DIS29B>\n");
1269 relocation_needed = 1;
1270 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1271 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
1273 sym_addr = sec_vma + sym_addr;
1274 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr);
1275 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1276 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1277 exist_val = htoe1l(exist_val);
1278 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1279 sym_addr += exist_val;
1280 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1281 pflags = _28BITS_RELOC;
1283 case R_E1_IMM32_PCREL:
1284 relocation_needed = 0;
1285 DBG_E1("Handling Reloc <IMM32_PCREL>\n");
1286 DBG_E1("DONT RELOCATE AT LOADING\n");
1287 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1288 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1290 sym_addr = sec_vma + sym_addr;
1292 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1293 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1295 q->address = q->address + section_vma;
1296 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1298 if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
1299 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1300 DBG_E1( "sym_addr := sym_addr - q->address - "
1301 "sizeof(CONST31_PCREL): [0x%x]\n",
1303 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1304 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1305 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1306 exist_val = htoe1l(exist_val);
1307 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1308 sym_addr += exist_val;
1311 relocation_needed = 1;
1312 DBG_E1("Handling Reloc <IMM32>\n");
1313 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1314 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1316 sym_addr = sec_vma + sym_addr;
1317 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1318 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1319 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);
1320 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1321 exist_val = htoe1l(exist_val);
1322 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1323 sym_addr += exist_val;
1324 pflags = _32BITS_RELOC;
1327 relocation_needed = 1;
1328 DBG_E1("Handling Reloc <WORD>\n");
1329 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1330 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1332 sym_addr = sec_vma + sym_addr;
1333 DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );
1334 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
1335 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1336 exist_val = htoe1l(exist_val);
1337 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1338 sym_addr += exist_val;
1339 DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);
1340 pflags = _32BITS_RELOC;
1343 #undef _32BITS_RELOC
1344 #undef _30BITS_RELOC
1345 #undef _28BITS_RELOC
1348 /* missing support for other types of relocs */
1349 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
1355 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
1356 bfd_section_vma(abs_bfd, sym_section));
1360 * for full elf relocation we have to write back the
1361 * start_code relative value to use.
1363 if (!pic_with_got) {
1364 #if defined(TARGET_arm)
1373 * horrible nasty hack to support different endianess
1375 if (!bfd_big_endian(abs_bfd)) {
1387 tmp.l = *(uint32_t *)r_mem;
1388 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
1390 (((*p)->howto->type != R_ARM_PC24) &&
1391 ((*p)->howto->type != R_ARM_PLT32)))
1392 hl |= (tmp.c[i3] << 24);
1393 else if (tmp.c[i2] & 0x80)
1394 hl |= 0xff000000; /* sign extend */
1397 tmp.c[i0] = hl & 0xff;
1398 tmp.c[i1] = (hl >> 8) & 0xff;
1399 tmp.c[i2] = (hl >> 16) & 0xff;
1401 (((*p)->howto->type != R_ARM_PC24) &&
1402 ((*p)->howto->type != R_ARM_PLT32)))
1403 tmp.c[i3] = (hl >> 24) & 0xff;
1404 if ((*p)->howto->type == R_ARM_ABS32)
1405 *(uint32_t *)r_mem = htonl(hl);
1407 *(uint32_t *)r_mem = tmp.l;
1408 #elif defined(TARGET_e1)
1409 #define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/
1410 switch ((*p)->howto->type) {
1412 case R_E1_CONST31_PCREL:
1413 case R_E1_DIS29W_PCREL:
1417 case R_E1_IMM32_PCREL:
1419 DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
1420 (sectionp + q->address + 2), sym_addr );
1421 *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
1425 DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
1426 (sectionp + q->address), sym_addr );
1427 *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
1430 printf("ERROR:Unhandled Relocation. Exiting...\n");
1434 #elif defined TARGET_bfin
1435 if ((*p)->howto->type == R_BFIN_RIMM16
1436 || (*p)->howto->type == R_BFIN_HUIMM16
1437 || (*p)->howto->type == R_BFIN_LUIMM16)
1439 /* for l and h we set the lower 16 bits which is only when it will be used */
1440 bfd_putl16 (sym_addr, sectionp + q->address);
1441 } else if ((*p)->howto->type == R_BFIN_BYTE4_DATA) {
1442 bfd_putl32 (sym_addr, sectionp + q->address);
1444 #else /* ! TARGET_arm && ! TARGET_e1 && ! TARGET_bfin */
1446 switch (q->howto->type) {
1451 /* Do nothing -- for cases we handle,
1452 the bits produced by the linker are
1453 what we want in the final flat file
1454 (and other cases are errors). Note
1455 that unlike most relocated values,
1456 it is stored in little-endian order,
1457 but this is necessary to avoid
1458 trashing the low-bit, and the float
1459 loaders knows about it. */
1461 #endif /* TARGET_V850 */
1464 case R_NIOS2_BFD_RELOC_32:
1465 case R_NIOS2_CALL26:
1466 case R_NIOS2_HIADJ16:
1470 #endif /* TARGET_nios2 */
1472 #if defined(TARGET_m68k)
1474 if (sym_addr < -0x8000 || sym_addr > 0x7fff) {
1475 fprintf (stderr, "Relocation overflow for R_68K_PC16 relocation against %s\n", sym_name);
1478 r_mem[0] = (sym_addr >> 8) & 0xff;
1479 r_mem[1] = sym_addr & 0xff;
1485 /* The alignment of the build host
1486 might be stricter than that of the
1487 target, so be careful. We store in
1488 network byte order. */
1489 r_mem[0] = (sym_addr >> 24) & 0xff;
1490 r_mem[1] = (sym_addr >> 16) & 0xff;
1491 r_mem[2] = (sym_addr >> 8) & 0xff;
1492 r_mem[3] = sym_addr & 0xff;
1494 #endif /* !TARGET_arm */
1498 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
1499 "section=%s size=%d "
1500 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
1501 q->address, sym_name, addstr,
1502 section_name, sym_reloc_size,
1503 sym_addr, section_vma + q->address);
1506 * Create relocation entry (PC relative doesn't need this).
1508 if (relocation_needed) {
1510 flat_relocs = realloc(flat_relocs,
1511 (flat_reloc_count + 1) * sizeof(uint32_t));
1513 flat_relocs[flat_reloc_count] = pflags |
1514 (section_vma + q->address);
1517 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
1518 section_vma + q->address);
1520 switch ((*p)->howto->type) {
1522 case R_E1_CONST31_PCREL:
1523 case R_E1_DIS29W_PCREL:
1527 case R_E1_IMM32_PCREL:
1529 flat_relocs[flat_reloc_count] = pflags |
1530 (section_vma + q->address + OPCODE_SIZE);
1532 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1533 flat_relocs[flat_reloc_count] );
1536 flat_relocs[flat_reloc_count] = pflags |
1537 (section_vma + q->address);
1539 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1540 flat_relocs[flat_reloc_count] );
1545 #endif //TARGET_bfin
1546 relocation_needed = 0;
1551 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
1552 __FILE__, __LINE__, sym_name, q->address, section_name,
1553 flat_relocs[flat_reloc_count]);
1560 printf("%d bad relocs\n", bad_relocs);
1567 *n_relocs = flat_reloc_count;
1573 static void usage(void)
1575 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1576 "[-o <output-file>] <elf-file>\n\n"
1577 " -v : verbose operation\n"
1578 " -r : force load to RAM\n"
1579 " -k : enable kernel trace on load (for debug)\n"
1580 " -z : compress code/data/relocs\n"
1581 " -d : compress data/relocs\n"
1582 " -a : use existing symbol references\n"
1583 " instead of recalculating from\n"
1584 " relocation info\n"
1585 " -R reloc-file : read relocations from a separate file\n"
1586 " -p abs-pic-file : GOT/PIC processing with files\n"
1587 " -s stacksize : set application stack size\n"
1588 " -o output-file : output file name\n\n",
1590 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1595 /* Write NUM zeroes to STREAM. */
1596 static void write_zeroes (unsigned long num, stream *stream)
1600 /* It'd be nice if we could just use fseek, but that doesn't seem to
1601 work for stdio output files. */
1602 memset(zeroes, 0x00, 1024);
1603 while (num > sizeof(zeroes)) {
1604 fwrite_stream(zeroes, sizeof(zeroes), 1, stream);
1605 num -= sizeof(zeroes);
1608 fwrite_stream(zeroes, num, 1, stream);
1613 int main(int argc, char *argv[])
1616 bfd *rel_bfd, *abs_bfd;
1618 char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1625 asymbol **symbol_table;
1626 long number_of_symbols;
1628 uint32_t data_len = 0;
1629 uint32_t bss_len = 0;
1630 uint32_t text_len = 0;
1633 uint32_t data_vma = ~0;
1634 uint32_t bss_vma = ~0;
1635 uint32_t text_vma = ~0;
1643 struct flat_hdr hdr;
1645 elf2flt_progname = argv[0];
1646 xmalloc_set_program_name(elf2flt_progname);
1651 if (sizeof(hdr) != 64)
1653 "Potential flat header incompatibility detected\n"
1654 "header size should be 64 but is %d",
1659 #else /* We need plenty of stack for both of them (Aggregate and Register) */
1663 while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1690 if (sscanf(optarg, "%i", &stack) != 1) {
1691 fprintf(stderr, "%s invalid stack size %s\n", argv[0], optarg);
1699 fprintf(stderr, "%s Unknown option\n", argv[0]);
1706 * if neither the -r or -p options was given, default to
1707 * a RAM load as that is the only option that makes sense.
1709 if (!load_to_ram && !pfile)
1712 fname = argv[argc-1];
1723 if (!(rel_bfd = bfd_openr(rel_file, 0)))
1724 fatal_perror("Can't open '%s'", rel_file);
1726 if (bfd_check_format (rel_bfd, bfd_object) == 0)
1727 fatal("File is not an object file");
1729 if (abs_file == rel_file)
1730 abs_bfd = rel_bfd; /* one file does all */
1732 if (!(abs_bfd = bfd_openr(abs_file, 0)))
1733 fatal_perror("Can't open '%s'", abs_file);
1735 if (bfd_check_format (abs_bfd, bfd_object) == 0)
1736 fatal("File is not an object file");
1739 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC))
1740 fatal("%s: Input file contains no relocation info", rel_file);
1742 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P))
1743 /* `Absolute' file is not absolute, so neither are address
1744 contained therein. */
1745 fatal("%s: `-a' option specified with non-fully-resolved input file",
1746 bfd_get_filename (abs_bfd));
1748 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1750 /* Group output sections into text, data, and bss, and calc their sizes. */
1751 for (s = abs_bfd->sections; s != NULL; s = s->next) {
1752 uint32_t *vma, *len;
1753 bfd_size_type sec_size;
1756 if (s->flags & SEC_CODE) {
1759 } else if (s->flags & SEC_DATA) {
1762 } else if (s->flags & SEC_ALLOC) {
1768 sec_size = bfd_section_size(abs_bfd, s);
1769 sec_vma = bfd_section_vma(abs_bfd, s);
1771 if (sec_vma < *vma) {
1773 *len += sec_vma - *vma;
1777 } else if (sec_vma + sec_size > *vma + *len)
1778 *len = sec_vma + sec_size - *vma;
1782 fatal("%s: no .text section", abs_file);
1784 text = xmalloc(text_len);
1787 printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1789 /* Read in all text sections. */
1790 for (s = abs_bfd->sections; s != NULL; s = s->next)
1791 if (s->flags & SEC_CODE)
1792 if (!bfd_get_section_contents(abs_bfd, s,
1793 text + (s->vma - text_vma), 0,
1794 bfd_section_size(abs_bfd, s)))
1796 fatal("read error section %s", s->name);
1800 fatal("%s: no .data section", abs_file);
1801 data = xmalloc(data_len);
1804 printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1806 if ((text_vma + text_len) != data_vma) {
1807 if ((text_vma + text_len) > data_vma) {
1808 printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1812 printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1813 data_vma, text_len);
1814 text_len = data_vma - text_vma;
1817 /* Read in all data sections. */
1818 for (s = abs_bfd->sections; s != NULL; s = s->next)
1819 if (s->flags & SEC_DATA)
1820 if (!bfd_get_section_contents(abs_bfd, s,
1821 data + (s->vma - data_vma), 0,
1822 bfd_section_size(abs_bfd, s)))
1824 fatal("read error section %s", s->name);
1828 bss_vma = data_vma + data_len;
1830 /* Put common symbols in bss. */
1831 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1834 printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1836 if ((data_vma + data_len) != bss_vma) {
1837 if ((data_vma + data_len) > bss_vma) {
1838 printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1843 printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1844 bss_vma, text_len, data_len, text_len + data_len);
1845 data_len = bss_vma - data_vma;
1848 reloc = (uint32_t *)
1849 output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1850 text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1852 if (reloc == NULL && verbose)
1853 printf("No relocations in code!\n");
1855 text_offs = real_address_bits(text_vma);
1857 /* Fill in the binflt_flat header */
1858 memcpy(hdr.magic,"bFLT",4);
1859 hdr.rev = htonl(FLAT_VERSION);
1860 hdr.entry = htonl(sizeof(hdr) + bfd_get_start_address(abs_bfd));
1861 hdr.data_start = htonl(sizeof(hdr) + text_offs + text_len);
1862 hdr.data_end = htonl(sizeof(hdr) + text_offs + text_len +data_len);
1863 hdr.bss_end = htonl(sizeof(hdr) + text_offs + text_len +data_len+bss_len);
1864 hdr.stack_size = htonl(stack); /* FIXME */
1865 hdr.reloc_start = htonl(sizeof(hdr) + text_offs + text_len +data_len);
1866 hdr.reloc_count = htonl(reloc_len);
1868 | (load_to_ram || text_has_relocs ? FLAT_FLAG_RAM : 0)
1869 | (ktrace ? FLAT_FLAG_KTRACE : 0)
1870 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1871 | (docompress ? (docompress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1873 hdr.build_date = htonl((uint32_t)time(NULL));
1874 memset(hdr.filler, 0x00, sizeof(hdr.filler));
1876 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1879 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1880 text_len, data_len, bss_len);
1882 printf(", relocs=0x%04x", reloc_len);
1887 ofile = xmalloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1888 strcpy(ofile, fname);
1889 strcat(ofile, ".bflt");
1892 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0)
1893 fatal_perror("Can't open output file %s", ofile);
1895 write(fd, &hdr, sizeof(hdr));
1898 if (fopen_stream_u(&gf, ofile, "a" BINARY_FILE_OPTS))
1899 fatal_perror("Can't open file %s for writing", ofile);
1901 if (docompress == 1)
1902 reopen_stream_compressed(&gf);
1904 /* Fill in any hole at the beginning of the text segment. */
1906 printf("ZERO before text len=0x%x\n", text_offs);
1907 write_zeroes(text_offs, &gf);
1909 /* Write the text segment. */
1910 fwrite_stream(text, text_len, 1, &gf);
1912 if (docompress == 2)
1913 reopen_stream_compressed(&gf);
1915 /* Write the data segment. */
1916 fwrite_stream(data, data_len, 1, &gf);
1919 fwrite_stream(reloc, reloc_len * 4, 1, &gf);
1928 * this __MUST__ be at the VERY end of the file - do NOT move!!
1934 * vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab