2 * elf2flt.c: Convert ELF (or any BFD format) to FLAT binary format
4 * (c) 1999-2002, Greg Ungerer <gerg@snapgear.com>
5 * Created elf2flt from coff2flt (see copyrights below). Added all the
6 * ELF format file handling. Extended relocation support for all of
9 * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
10 * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
11 * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
12 * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
13 * (c) 2001, zflat support <davidm@snapgear.com>
14 * (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
15 * David McCullough <davidm@snapgear.com>
17 * Now supports PIC with GOT tables. This works by taking a '.elf' file
18 * and a fully linked elf executable (at address 0) and produces a flat
19 * file that can be loaded with some fixups. It still supports the old
20 * style fully relocatable elf format files.
22 * Originally obj-res.c
24 * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
25 * (c) 1998, D. Jeff Dionne
26 * (c) 1998, The Silver Hammer Group Ltd.
27 * (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
29 * This is Free Software, under the GNU Public Licence v2 or greater.
31 * Relocation added March 1997, Kresten Krab Thorup
32 * krab@california.daimi.aau.dk
35 #include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
36 #include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */
37 #include <stdarg.h> /* Allows va_list to exist in the these namespaces */
38 #include <string.h> /* Userland prototypes of the string handling funcs */
40 #include <unistd.h> /* Userland prototypes of the Unix std system calls */
41 #include <fcntl.h> /* Flag value for file handling functions */
44 #include <netinet/in.h> /* Consts and structs defined by the internet system */
46 /* from $(INSTALLDIR)/include */
47 #include <bfd.h> /* Main header file for the BFD library */
49 #if defined(TARGET_h8300)
50 #include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
52 #include <elf.h> /* TARGET_* ELF support for the BFD library */
55 /* from uClinux-x.x.x/include/linux */
56 #include "flat.h" /* Binary flat header description */
63 #if defined(TARGET_m68k)
64 #define ARCH "m68k/coldfire"
65 #elif defined(TARGET_arm)
67 #elif defined(TARGET_sparc)
69 #elif defined(TARGET_v850)
71 #elif defined(TARGET_sh)
73 #elif defined(TARGET_h8300)
75 #elif defined(TARGET_microblaze)
76 #define ARCH "microblaze"
78 #error "Don't know how to support your CPU architecture??"
83 * Define a maximum number of bytes allowed in the offset table.
84 * We'll fail if the table is larger than this.
86 * This limit may be different for platforms other than m68k, but
87 * 8000 entries is a lot, trust me :-) (davidm)
89 #define GOT_LIMIT 32767
91 * we have to mask out the shared library id here and there, this gives
92 * us the real address bits when needed
94 #define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))
96 #define real_address_bits(x) (x)
104 int verbose = 0; /* extra output when running */
105 int pic_with_got = 0; /* do elf/got processing with PIC code */
106 int load_to_ram = 0; /* instruct loader to allocate everything into RAM */
107 int ktrace = 0; /* instruct loader output kernel trace on load */
108 int compress = 0; /* 1 = compress everything, 2 = compress data only */
109 int use_resolved = 0; /* If true, get the value of symbol references from */
110 /* the program contents, not from the relocation table. */
111 /* In this case, the input ELF file must be already */
112 /* fully resolved (using the `-q' flag with recent */
113 /* versions of GNU ld will give you a fully resolved */
114 /* output file with relocation entries). */
116 const char *progname, *filename;
122 static char where[200];
125 /* Use exactly one of these: */
126 E_NOFILE = 0, /* "progname: " */
127 E_FILE = 1, /* "filename: " */
128 E_FILELINE = 2, /* "filename:lineno: " */
129 E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */
131 /* Add in any of these with |': */
136 void ewhere (const char *format, ...);
137 void einfo (int type, const char *format, ...);
141 ewhere (const char *format, ...) {
143 va_start (args, format);
144 vsprintf (where, format, args);
150 einfo (int type, const char *format, ...) {
153 switch (type & 0x0f) {
155 fprintf (stderr, "%s: ", progname);
158 fprintf (stderr, "%s: ", filename);
161 ewhere ("%d", lineno);
164 fprintf (stderr, "%s:%s: ", filename, where);
168 if (type & E_WARNING) {
169 fprintf (stderr, "warning: ");
175 va_start (args, format);
176 vfprintf (stderr, format, args);
182 fprintf (stderr, "\n");
187 get_symbols (bfd *abfd, long *num)
190 asymbol **symbol_table;
191 long number_of_symbols;
193 storage_needed = bfd_get_symtab_upper_bound (abfd);
195 if (storage_needed < 0)
198 if (storage_needed == 0)
201 symbol_table = (asymbol **) malloc (storage_needed);
203 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
205 if (number_of_symbols < 0)
208 *num = number_of_symbols;
215 dump_symbols(asymbol **symbol_table, long number_of_symbols)
218 printf("SYMBOL TABLE:\n");
219 for (i=0; i<number_of_symbols; i++) {
220 printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,
221 symbol_table[i]->value);
230 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
233 for (i=0; i<number_of_symbols; i++) {
234 if (symbol_table[i]->section == sec) {
235 if (!strcmp(symbol_table[i]->name, name)) {
236 return symbol_table[i]->value;
246 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
252 for (i=0; i<number_of_symbols; i++) {
253 if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
254 offset = bss_len + comsize;
255 comsize += symbol_table[i]->value;
256 symbol_table[i]->value = offset;
268 int number_of_symbols,
269 unsigned long *n_relocs,
270 unsigned char *text, int text_len, unsigned long text_vma,
271 unsigned char *data, int data_len, unsigned long data_vma,
274 unsigned long *flat_relocs;
275 asection *a, *sym_section, *r;
276 arelent **relpp, **p, *q;
277 const char *sym_name, *section_name;
278 unsigned char *sectionp;
279 unsigned long pflags;
281 long sym_addr, sym_vma, section_vma;
282 int relsize, relcount;
283 int flat_reloc_count;
284 int sym_reloc_size, rc;
291 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
292 "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
293 __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
294 text, text_len, data, data_len);
298 dump_symbols(symbols, number_of_symbols);
303 flat_reloc_count = 0;
307 /* Determine how big our offset table is in bytes.
308 * This isn't too difficult as we've terminated the table with -1.
309 * Also note that both the relocatable and absolute versions have this
310 * terminator even though the relocatable one doesn't have the GOT!
313 unsigned long *lp = (unsigned long *)data;
314 /* Should call ntohl(*lp) here but is isn't going to matter */
315 while (*lp != 0xffffffff) lp++;
316 got_size = ((unsigned char *)lp) - data;
318 printf("GOT table contains %d entries (%d bytes)\n",
319 got_size/sizeof(unsigned long), got_size);
321 if (got_size > GOT_LIMIT) {
322 fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
323 got_size, GOT_LIMIT);
329 for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
330 section_vma = bfd_section_vma(abs_bfd, a);
333 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
334 a->flags, section_vma);
336 // if (bfd_is_abs_section(a))
338 if (bfd_is_und_section(a))
340 if (bfd_is_com_section(a))
342 // if ((a->flags & SEC_RELOC) == 0)
346 * Only relocate things in the data sections if we are PIC/GOT.
347 * otherwise do text as well
349 if (!pic_with_got && (a->flags & SEC_CODE))
350 sectionp = text + (a->vma - text_vma);
351 else if (a->flags & SEC_DATA)
352 sectionp = data + (a->vma - data_vma);
356 /* Now search for the equivalent section in the relocation binary
357 * and use that relocation information to build reloc entries
360 for (r=rel_bfd->sections; r != NULL; r=r->next)
361 if (strcmp(a->name, r->name) == 0)
366 printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
367 r->flags, bfd_section_vma(abs_bfd, r));
368 if ((r->flags & SEC_RELOC) == 0)
370 relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
373 printf("%s(%d): no relocation entries section=0x%x\n",
374 __FILE__, __LINE__, r->name);
378 symb = get_symbols(rel_bfd, &nsymb);
379 relpp = (arelent **) xmalloc(relsize);
380 relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
383 printf("%s(%d): no relocation entries section=%s\n",
384 __FILE__, __LINE__, r->name);
387 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
388 unsigned char *r_mem;
389 int relocation_needed = 0;
391 #ifdef TARGET_microblaze
392 /* The MICROBLAZE_XX_NONE relocs can be skipped.
393 They represent PC relative branches that the
394 linker has already resolved */
396 switch ((*p)->howto->type)
398 case R_MICROBLAZE_NONE:
399 case R_MICROBLAZE_64_NONE:
402 #endif /* TARGET_microblaze */
405 /* Skip this relocation entirely if possible (we
406 do this early, before doing any other
407 processing on it). */
408 switch ((*p)->howto->type) {
409 #ifdef R_V850_9_PCREL
412 #ifdef R_V850_22_PCREL
413 case R_V850_22_PCREL:
415 #ifdef R_V850_SDA_16_16_OFFSET
416 case R_V850_SDA_16_16_OFFSET:
418 #ifdef R_V850_SDA_15_16_OFFSET
419 case R_V850_SDA_15_16_OFFSET:
421 #ifdef R_V850_ZDA_15_16_OFFSET
422 case R_V850_ZDA_15_16_OFFSET:
424 #ifdef R_V850_TDA_6_8_OFFSET
425 case R_V850_TDA_6_8_OFFSET:
427 #ifdef R_V850_TDA_7_8_OFFSET
428 case R_V850_TDA_7_8_OFFSET:
430 #ifdef R_V850_TDA_7_7_OFFSET
431 case R_V850_TDA_7_7_OFFSET:
433 #ifdef R_V850_TDA_16_16_OFFSET
434 case R_V850_TDA_16_16_OFFSET:
436 #ifdef R_V850_TDA_4_5_OFFSET
437 case R_V850_TDA_4_5_OFFSET:
439 #ifdef R_V850_TDA_4_4_OFFSET
440 case R_V850_TDA_4_4_OFFSET:
442 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
443 case R_V850_SDA_16_16_SPLIT_OFFSET:
445 #ifdef R_V850_CALLT_6_7_OFFSET
446 case R_V850_CALLT_6_7_OFFSET:
448 #ifdef R_V850_CALLT_16_16_OFFSET
449 case R_V850_CALLT_16_16_OFFSET:
451 /* These are relative relocations, which
452 have already been fixed up by the
453 linker at this point, so just ignore
457 #endif /* USE_V850_RELOCS */
460 if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
461 sym_name = (*(q->sym_ptr_ptr))->name;
462 sym_section = (*(q->sym_ptr_ptr))->section;
463 section_name=(*(q->sym_ptr_ptr))->section->name;
465 printf("ERROR: undefined relocation entry\n");
469 /* Adjust the address to account for the GOT table which wasn't
470 * present in the relative file link.
473 q->address += got_size;
475 /* A pointer to what's being relocated, used often
477 r_mem = sectionp + q->address;
480 * Fixup offset in the actual section.
483 if ((sym_addr = get_symbol_offset((char *) sym_name,
484 sym_section, symbols, number_of_symbols)) == -1) {
489 /* Use the address of the symbol already in
490 the program text. How this is handled may
491 still depend on the particular relocation
493 switch (q->howto->type) {
497 /* We specially handle adjacent
498 HI16_S/ZDA_15_16_OFFSET and
499 HI16_S/LO16 pairs that reference the
500 same address (these are usually
501 movhi/ld and movhi/movea pairs,
504 r2_type = R_V850_NONE;
506 r2_type = p[1]->howto->type;
507 if ((r2_type == R_V850_ZDA_15_16_OFFSET
508 || r2_type == R_V850_LO16)
509 && (p[0]->sym_ptr_ptr
510 == p[1]->sym_ptr_ptr)
511 && (p[0]->addend == p[1]->addend))
513 relocation_needed = 1;
516 case R_V850_ZDA_15_16_OFFSET:
524 /* We don't really need the
525 actual value -- the bits
526 produced by the linker are
527 what we want in the final
528 flat file -- but get it
532 unsigned char *r2_mem =
540 /* Sign extend LO. */
544 /* Maybe ignore the LSB
548 if (r2_type != R_V850_LO16)
556 goto bad_v850_reloc_err;
560 /* See if this is actually the
561 2nd half of a pair. */
563 && (p[-1]->howto->type
565 && (p[-1]->sym_ptr_ptr
566 == p[0]->sym_ptr_ptr)
567 && (p[-1]->addend == p[0]->addend))
568 break; /* not an error */
570 goto bad_v850_reloc_err;
574 printf("ERROR: reloc type %s unsupported in this context\n",
578 #endif /* TARGET_V850 */
581 /* The default is to assume that the
582 relocation is relative and has
583 already been fixed up by the
584 linker (perhaps we ought to make
585 give an error by default, and
586 require `safe' relocations to be
587 enumberated explicitly?). */
588 if (bfd_big_endian (abs_bfd))
600 relocation_needed = 1;
603 /* Calculate the sym address ourselves. */
604 sym_reloc_size = bfd_get_reloc_size(q->howto);
607 if (sym_reloc_size != 4) {
608 printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
609 (*p)->howto->type, sym_reloc_size, sym_name);
616 switch ((*p)->howto->type) {
618 #if defined(TARGET_m68k)
620 relocation_needed = 1;
621 sym_vma = bfd_section_vma(abs_bfd, sym_section);
622 sym_addr += sym_vma + q->addend;
626 sym_addr += sym_vma + q->addend;
627 sym_addr -= q->address;
631 #if defined(TARGET_arm)
633 relocation_needed = 1;
636 "%s vma=0x%x, value=0x%x, address=0x%x "
637 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
639 sym_vma, (*(q->sym_ptr_ptr))->value,
640 q->address, sym_addr,
641 (*p)->howto->rightshift,
642 *(unsigned long *)r_mem);
643 sym_vma = bfd_section_vma(abs_bfd, sym_section);
644 sym_addr += sym_vma + q->addend;
648 /* Should be fine as is */
653 "%s vma=0x%x, value=0x%x, address=0x%x "
654 "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
656 sym_vma, (*(q->sym_ptr_ptr))->value,
657 q->address, sym_addr,
658 (*p)->howto->rightshift,
659 *(unsigned long *)r_mem);
662 sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
668 relocation_needed = 1;
669 sym_vma = bfd_section_vma(abs_bfd, sym_section);
670 sym_addr += sym_vma + q->addend;
672 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
673 #ifdef R_V850_ZDA_16_16_OFFSET
674 case R_V850_ZDA_16_16_OFFSET:
676 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
677 case R_V850_ZDA_16_16_SPLIT_OFFSET:
679 /* Can't support zero-relocations. */
680 printf ("ERROR: %s+0x%x: zero relocations not supported\n",
681 sym_name, q->addend);
683 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
684 #endif /* TARGET_v850 */
688 if (sym_reloc_size != 4) {
689 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
693 relocation_needed = 1;
694 sym_addr = (*(q->sym_ptr_ptr))->value;
696 r_mem -= 1; /* tracks q->address */
697 sym_vma = bfd_section_vma(abs_bfd, sym_section);
698 sym_addr += sym_vma + q->addend;
699 sym_addr |= (*(unsigned char *)r_mem<<24);
702 if (sym_reloc_size != 4) {
703 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
707 relocation_needed = 1;
708 sym_addr = (*(q->sym_ptr_ptr))->value;
709 sym_vma = bfd_section_vma(abs_bfd, sym_section);
710 sym_addr += sym_vma + q->addend;
713 case R_H8_DIR32A16: /* currently 32, could be made 16 */
714 if (sym_reloc_size != 4) {
715 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
719 relocation_needed = 1;
720 sym_addr = (*(q->sym_ptr_ptr))->value;
721 sym_vma = bfd_section_vma(abs_bfd, sym_section);
722 sym_addr += sym_vma + q->addend;
726 sym_addr = (*(q->sym_ptr_ptr))->value;
727 sym_addr += sym_vma + q->addend;
728 sym_addr -= (q->address + 2);
729 if (bfd_big_endian(abs_bfd))
730 *(unsigned short *)r_mem =
731 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
735 sym_addr = (*(q->sym_ptr_ptr))->value;
736 sym_addr += sym_vma + q->addend;
737 sym_addr -= (q->address + 1);
738 *(unsigned char *)r_mem = sym_addr;
742 #ifdef TARGET_microblaze
743 case R_MICROBLAZE_64:
744 /* The symbol is split over two consecutive instructions.
745 Flag this to the flat loader by setting the high bit of
746 the relocation symbol. */
748 unsigned char *p = r_mem;
749 unsigned long offset;
752 /* work out the relocation */
753 sym_vma = bfd_section_vma(abs_bfd, sym_section);
754 /* grab any offset from the text */
755 offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
756 /* Update the address */
757 sym_addr += offset + sym_vma + q->addend;
758 /* Write relocated pointer back */
759 p[2] = (sym_addr >> 24) & 0xff;
760 p[3] = (sym_addr >> 16) & 0xff;
761 p[6] = (sym_addr >> 8) & 0xff;
762 p[7] = sym_addr & 0xff;
764 /* create a new reloc entry */
765 flat_relocs = realloc(flat_relocs,
766 (flat_reloc_count + 1) * sizeof(unsigned long));
767 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
769 relocation_needed = 0;
771 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
772 bfd_section_vma(abs_bfd, sym_section));
774 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
775 "section=%s size=%d "
776 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
777 q->address, sym_name, addstr,
778 section_name, sym_reloc_size,
779 sym_addr, section_vma + q->address);
781 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
782 section_vma + q->address);
786 case R_MICROBLAZE_32:
788 unsigned char *p = r_mem;
789 unsigned long offset;
791 /* grab any offset from the text */
792 offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
793 //sym_addr = (*(q->sym_ptr_ptr))->value;
794 sym_vma = bfd_section_vma(abs_bfd, sym_section);
795 sym_addr += offset + sym_vma + q->addend;
797 relocation_needed = 1;
800 case R_MICROBLAZE_64_PCREL:
802 //sym_addr = (*(q->sym_ptr_ptr))->value;
803 sym_addr += sym_vma + q->addend;
804 sym_addr -= (q->address + 4);
805 sym_addr = htonl(sym_addr);
807 * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
809 * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
810 /* We've done all the work, so continue
811 to next reloc instead of break */
814 #endif /* TARGET_microblaze */
819 relocation_needed = 1;
820 sym_vma = bfd_section_vma(abs_bfd, sym_section);
821 sym_addr += sym_vma + q->addend;
825 sym_addr += sym_vma + q->addend;
826 sym_addr -= q->address;
828 case R_SPARC_WDISP30:
829 sym_addr = (((*(q->sym_ptr_ptr))->value-
830 q->address) >> 2) & 0x3fffffff;
832 ntohl(*(unsigned long *)r_mem)
837 relocation_needed = 1;
839 sym_vma = bfd_section_vma(abs_bfd, sym_section);
840 sym_addr += sym_vma + q->addend;
842 htonl(*(unsigned long *)r_mem)
847 relocation_needed = 1;
849 sym_vma = bfd_section_vma(abs_bfd, sym_section);
850 sym_addr += sym_vma + q->addend;
851 sym_addr &= 0x000003ff;
853 htonl(*(unsigned long *)r_mem)
857 #endif /* TARGET_sparc */
861 relocation_needed = 1;
862 sym_vma = bfd_section_vma(abs_bfd, sym_section);
863 sym_addr += sym_vma + q->addend;
867 sym_addr += sym_vma + q->addend;
868 sym_addr -= q->address;
870 #endif /* TARGET_sh */
873 /* missing support for other types of relocs */
874 printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
880 sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
881 bfd_section_vma(abs_bfd, sym_section));
885 * for full elf relocation we have to write back the
886 * start_code relative value to use.
889 #if defined(TARGET_arm)
898 * horrible nasty hack to support different endianess
900 if (!bfd_big_endian(abs_bfd)) {
912 tmp.l = *(unsigned long *)r_mem;
913 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
914 if (((*p)->howto->type != R_ARM_PC24) &&
915 ((*p)->howto->type != R_ARM_PLT32))
916 hl |= (tmp.c[i3] << 24);
917 else if (tmp.c[i2] & 0x80)
918 hl |= 0xff000000; /* sign extend */
920 tmp.c[i0] = hl & 0xff;
921 tmp.c[i1] = (hl >> 8) & 0xff;
922 tmp.c[i2] = (hl >> 16) & 0xff;
923 if (((*p)->howto->type != R_ARM_PC24) &&
924 ((*p)->howto->type != R_ARM_PLT32))
925 tmp.c[i3] = (hl >> 24) & 0xff;
926 if ((*p)->howto->type == R_ARM_ABS32)
927 *(unsigned long *)r_mem = htonl(hl);
929 *(unsigned long *)r_mem = tmp.l;
931 #else /* ! TARGET_arm */
933 switch (q->howto->type) {
938 /* Do nothing -- for cases we handle,
939 the bits produced by the linker are
940 what we want in the final flat file
941 (and other cases are errors). Note
942 that unlike most relocated values,
943 it is stored in little-endian order,
944 but this is necessary to avoid
945 trashing the low-bit, and the float
946 loaders knows about it. */
948 #endif /* TARGET_V850 */
950 /* The alignment of the build host
951 might be stricter than that of the
952 target, so be careful. We store in
953 network byte order. */
954 r_mem[0] = (sym_addr >> 24) & 0xff;
955 r_mem[1] = (sym_addr >> 16) & 0xff;
956 r_mem[2] = (sym_addr >> 8) & 0xff;
957 r_mem[3] = sym_addr & 0xff;
959 #endif /* !TARGET_arm */
963 printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
964 "section=%s size=%d "
965 "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
966 q->address, sym_name, addstr,
967 section_name, sym_reloc_size,
968 sym_addr, section_vma + q->address);
971 * Create relocation entry (PC relative doesn't need this).
973 if (relocation_needed) {
974 flat_relocs = realloc(flat_relocs,
975 (flat_reloc_count + 1) * sizeof(unsigned long));
976 flat_relocs[flat_reloc_count] = pflags |
977 (section_vma + q->address);
980 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
981 section_vma + q->address);
983 relocation_needed = 0;
988 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
989 __FILE__, __LINE__, sym_name, q->address, section_name,
990 flat_relocs[flat_reloc_count]);
997 printf("%d bad relocs\n", bad_relocs);
1004 *n_relocs = flat_reloc_count;
1011 /* shared lib symbols stuff */
1014 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
1017 for (i=0; i<number_of_symbols; i++) {
1018 if (symbol_table[i]->section == sec) {
1019 if (!strcmp(symbol_table[i]->name, name)) {
1020 return symbol_table[i]->value;
1028 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
1039 signed short *tab = malloc(32768); /* we don't know how many yet*/
1041 asection *text_section = bfd_get_section_by_name (abfd, ".text");
1043 if (!(ef = fopen(ename, "r"))) {
1044 fprintf (stderr,"Can't open %s\n",ename);
1048 fgets(libname, 80, ef);
1050 if (number_of_symbols < 0) {
1051 fprintf (stderr,"Corrupt symbol table!\n");
1055 if ((etext_addr = get_symbol("etext",
1058 number_of_symbols)) == -1) {
1059 fprintf (stderr,"Can't find the symbol etext\n");
1065 buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
1067 if ((sym_addr = get_symbol(buf,
1070 number_of_symbols)) == -1) {
1071 fprintf (stderr,"Can't find the symbol %s\n",buf);
1074 tab[++count] = htons(sym_addr - etext_addr);
1082 fprintf (stderr,"*** %d symbols not found\n",foobar);
1086 strcpy((char *)&tab[++count],libname);
1087 tab[0] = htons(count * 2);
1088 write(fd, tab, count * 2 + strlen(libname) + 2);
1094 static char * program;
1096 static void usage(void)
1098 fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1099 "[-o <output-file>] <elf-file>\n\n"
1100 " -v : verbose operation\n"
1101 " -r : force load to RAM\n"
1102 " -k : enable kernel trace on load (for debug)\n"
1103 " -z : compress code/data/relocs\n"
1104 " -d : compress data/relocs\n"
1105 " -a : use existing symbol references\n"
1106 " instead of recalculating from\n"
1107 " relocation info\n"
1108 " -R reloc-file : read relocations from a separate file\n"
1109 " -p abs-pic-file : GOT/PIC processing with files\n"
1110 " -s stacksize : set application stack size\n"
1111 " -o output-file : output file name\n\n",
1113 fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1118 /* Write NUM zeroes to STREAM. */
1119 static void write_zeroes (unsigned long num, FILE *stream)
1123 /* It'd be nice if we could just use fseek, but that doesn't seem to
1124 work for stdio output files. */
1125 bzero(zeroes, 1024);
1126 while (num > sizeof(zeroes)) {
1127 fwrite(zeroes, sizeof(zeroes), 1, stream);
1128 num -= sizeof(zeroes);
1131 fwrite(zeroes, num, 1, stream);
1136 int main(int argc, char *argv[])
1139 bfd *rel_bfd, *abs_bfd;
1141 char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1150 asymbol **symbol_table;
1151 long number_of_symbols;
1153 unsigned long data_len = 0;
1154 unsigned long bss_len = 0;
1155 unsigned long text_len = 0;
1156 unsigned long reloc_len;
1158 unsigned long data_vma = ~0;
1159 unsigned long bss_vma = ~0;
1160 unsigned long text_vma = ~0;
1162 unsigned long text_offs;
1166 unsigned long *reloc;
1168 struct flat_hdr hdr;
1179 while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1206 stack = atoi(optarg);
1212 fprintf(stderr, "%s Unknown option\n", argv[0]);
1219 * if neither the -r or -p options was given, default to
1220 * a RAM load as that is the only option that makes sense.
1222 if (!load_to_ram && !pfile)
1225 filename = fname = argv[argc-1];
1236 if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1237 fprintf(stderr, "Can't open %s\n", rel_file);
1241 if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1242 fprintf(stderr, "File is not an object file\n");
1246 if (abs_file == rel_file)
1247 abs_bfd = rel_bfd; /* one file does all */
1249 if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1250 fprintf(stderr, "Can't open %s\n", abs_file);
1254 if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1255 fprintf(stderr, "File is not an object file\n");
1260 if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1261 fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1265 if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1266 /* `Absolute' file is not absolute, so neither are address
1267 contained therein. */
1269 "%s: `-a' option specified with non-fully-resolved input file\n",
1270 bfd_get_filename (abs_bfd));
1274 symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1276 /* Group output sections into text, data, and bss, and calc their sizes. */
1277 for (s = abs_bfd->sections; s != NULL; s = s->next) {
1278 unsigned long *vma, *len;
1280 if (s->flags & SEC_CODE) {
1283 } else if (s->flags & SEC_DATA) {
1286 } else if (s->flags & SEC_ALLOC) {
1292 if (s->vma < *vma) {
1294 *len += s->vma - *vma;
1296 *len = s->_raw_size;
1298 } else if (s->vma + s->_raw_size > *vma + *len)
1299 *len = s->vma + s->_raw_size - *vma;
1302 if (text_len == 0) {
1303 fprintf (stderr, "%s: no .text section", abs_file);
1307 text = malloc(text_len);
1310 printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1312 /* Read in all text sections. */
1313 for (s = abs_bfd->sections; s != NULL; s = s->next)
1314 if (s->flags & SEC_CODE)
1315 if (!bfd_get_section_contents(abs_bfd, s,
1316 text + (s->vma - text_vma), 0,
1319 fprintf(stderr, "read error section %s\n", s->name);
1323 if (data_len == 0) {
1324 fprintf (stderr, "%s: no .data section", abs_file);
1327 data = malloc(data_len);
1330 printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1332 if ((text_vma + text_len) != data_vma) {
1333 if ((text_vma + text_len) > data_vma) {
1334 printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1338 printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1339 data_vma, text_len);
1340 text_len = data_vma - text_vma;
1343 /* Read in all data sections. */
1344 for (s = abs_bfd->sections; s != NULL; s = s->next)
1345 if (s->flags & SEC_DATA)
1346 if (!bfd_get_section_contents(abs_bfd, s,
1347 data + (s->vma - data_vma), 0,
1350 fprintf(stderr, "read error section %s\n", s->name);
1354 /* Put common symbols in bss. */
1355 bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1358 printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1360 if ((data_vma + data_len) != bss_vma) {
1361 if ((data_vma + data_len) > bss_vma) {
1362 printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1367 printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1368 bss_vma, text_len, data_len, text_len + data_len);
1369 data_len = bss_vma - data_vma;
1372 reloc = (unsigned long *)
1373 output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1374 text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1377 printf("No relocations in code!\n");
1379 text_offs = real_address_bits(text_vma);
1381 /* Fill in the binflt_flat header */
1382 memcpy(hdr.magic,"bFLT",4);
1383 hdr.rev = htonl(FLAT_VERSION);
1384 hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1385 hdr.data_start = htonl(16 * 4 + text_offs + text_len);
1386 hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len);
1387 hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1388 hdr.stack_size = htonl(stack); /* FIXME */
1389 hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1390 hdr.reloc_count = htonl(reloc_len);
1392 | (load_to_ram ? FLAT_FLAG_RAM : 0)
1393 | (ktrace ? FLAT_FLAG_KTRACE : 0)
1394 | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1395 | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1397 hdr.build_date = htonl((unsigned long)time(NULL));
1398 bzero(hdr.filler, sizeof(hdr.filler));
1400 for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1403 printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1404 text_len, data_len, bss_len);
1406 printf(", relocs=0x%04x", reloc_len);
1411 ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1412 strcpy(ofile, fname);
1413 strcat(ofile, ".bflt");
1416 if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1417 fprintf (stderr, "Can't open output file %s\n", ofile);
1421 write(fd, &hdr, sizeof(hdr));
1425 * get the compression command ready
1427 sprintf(cmd, "gzip -f -9 >> %s", ofile);
1429 #define START_COMPRESSOR do { \
1430 if (gf) fclose(gf); \
1431 if (!(gf = popen(cmd, "w"))) { \
1432 fprintf(stderr, "Can't run cmd %s\n", cmd); \
1437 gf = fopen(ofile, "a");
1439 fprintf(stderr, "Can't opne file %s for writing\n", ofile); \
1446 /* Fill in any hole at the beginning of the text segment. */
1448 printf("ZERO before text len=0x%x\n", text_offs);
1449 write_zeroes(text_offs, gf);
1451 /* Write the text segment. */
1452 fwrite(text, text_len, 1, gf);
1457 /* Write the data segment. */
1458 fwrite(data, data_len, 1, gf);
1461 fwrite(reloc, reloc_len * 4, 1, gf);