Rev 872 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/** elf2emcoreapp.c: Convert ELF (or any BFD format) to emCORE executable format** (c) 2011, Michael Sparmann <theseven@gmx.net>** Based on:* elf2flt.c: Convert ELF (or any BFD format) to FLAT binary format** (c) 1999-2002, Greg Ungerer <gerg@snapgear.com>* Created elf2flt from coff2flt (see copyrights below). Added all the* ELF format file handling. Extended relocation support for all of* text and data.** (c) 2006 Support the -a (use_resolved) option for TARGET_arm.* Shaun Jackman <sjackman@gmail.com>* (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>* (c) 2003, H8 support, ktrace <davidm@snapgear.com>* (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>* (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>* (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>* (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>* (c) 2001, zflat support <davidm@snapgear.com>* (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and* David McCullough <davidm@snapgear.com>** Now supports PIC with GOT tables. This works by taking a '.elf' file* and a fully linked elf executable (at address 0) and produces a flat* file that can be loaded with some fixups. It still supports the old* style fully relocatable elf format files.** Originally obj-res.c** (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>* (c) 1998, D. Jeff Dionne* (c) 1998, The Silver Hammer Group Ltd.* (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>** This is Free Software, under the GNU Public Licence v2 or greater.** Relocation added March 1997, Kresten Krab Thorup* krab@california.daimi.aau.dk*/#include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */#include <stdlib.h> /* Userland prototypes of the ANSI C std lib functions */#include <stdarg.h> /* Allows va_list to exist in the these namespaces */#include <string.h> /* Userland prototypes of the string handling funcs */#include <strings.h>#include <unistd.h> /* Userland prototypes of the Unix std system calls */#include <fcntl.h> /* Flag value for file handling functions */#include <time.h>/* from $(INSTALLDIR)/include */#include <bfd.h> /* Main header file for the BFD library */#include <libiberty.h>#include "stubs.h"const char *elf2flt_progname;#if defined(TARGET_h8300)#include <elf/h8.h> /* TARGET_* ELF support for the BFD library */#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(TARGET_nios) || defined(TARGET_nios2)#include "cygwin-elf.h" /* Cygwin uses a local copy */#elif defined(TARGET_microblaze)#include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */#else#include <elf.h> /* TARGET_* ELF support for the BFD library */#endif/* Always include Blackfin-specific defines in addition to common ELF stuff* above as the common elf headers often do not have our relocs.*/#if defined(TARGET_bfin) && !defined(R_BFIN_RIMM16)#include "elf/bfin.h"#endif#if defined(__MINGW32__)#include <getopt.h>#endif#define _TOOL#include "../../emcore/trunk/execimage.h"#include "compress.h"#ifdef TARGET_e1#include <e1.h>#endif#ifdef TARGET_v850e#define TARGET_v850#endif#if defined(TARGET_m68k)#define ARCH "m68k/coldfire"#elif defined(TARGET_arm)#define ARCH "arm"#elif defined(TARGET_sparc)#define ARCH "sparc"#elif defined(TARGET_v850)#define ARCH "v850"#elif defined(TARGET_sh)#define ARCH "sh"#elif defined(TARGET_h8300)#define ARCH "h8300"#elif defined(TARGET_microblaze)#define ARCH "microblaze"#elif defined(TARGET_e1)#define ARCH "e1-coff"#elif defined(TARGET_bfin)#define ARCH "bfin"#elif defined(TARGET_nios)#define ARCH "nios"#elif defined(TARGET_nios2)#define ARCH "nios2"#else#error "Don't know how to support your CPU architecture??"#endif#ifndef R_ARM_V4BX#define R_ARM_V4BX 40#endif#ifndef R_ARM_JUMP24#define R_ARM_JUMP24 29#endif#ifndef R_ARM_CALL#define R_ARM_CALL 28#endif#if defined(TARGET_m68k) || defined(TARGET_h8300) || defined(TARGET_bfin)/** Define a maximum number of bytes allowed in the offset table.* We'll fail if the table is larger than this.** This limit may be different for platforms other than m68k, but* 8000 entries is a lot, trust me :-) (davidm)*/#define GOT_LIMIT 32767/** we have to mask out the shared library id here and there, this gives* us the real address bits when needed*/#define real_address_bits(x) (pic_with_got ? ((x) & 0xffffff) : (x))#else#define real_address_bits(x) (x)#endif#ifndef O_BINARY#define O_BINARY 0#endifint verbose = 0; /* extra output when running */int pic_with_got = 0; /* do elf/got processing with PIC code */int load_to_ram = 1; /* instruct loader to allocate everything into RAM */int ktrace = 0; /* instruct loader output kernel trace on load */int docompress = 0; /* 1 = compress everything */int lib = 0; /* 1 = this is a shared library */int use_resolved = 0; /* If true, get the value of symbol references from *//* the program contents, not from the relocation table. *//* In this case, the input ELF file must be already *//* fully resolved (using the `-q' flag with recent *//* versions of GNU ld will give you a fully resolved *//* output file with relocation entries). *//* Set if the text section contains any relocations. If it does, we mustset the load_to_ram flag. */int text_has_relocs = 0;asymbol**get_symbols (bfd *abfd, long *num){int32_t storage_needed;asymbol **symbol_table;long number_of_symbols;storage_needed = bfd_get_symtab_upper_bound (abfd);if (storage_needed < 0)abort ();if (storage_needed == 0)return NULL;symbol_table = xmalloc (storage_needed);number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);if (number_of_symbols < 0)abort ();*num = number_of_symbols;return symbol_table;}intdump_symbols(asymbol **symbol_table, long number_of_symbols){long i;printf("SYMBOL TABLE:\n");for (i=0; i<number_of_symbols; i++) {printf(" NAME=%s VALUE=0x%x\n", symbol_table[i]->name,symbol_table[i]->value);}printf("\n");return(0);}longget_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols){long i;for (i=0; i<number_of_symbols; i++) {if (symbol_table[i]->section == sec) {if (!strcmp(symbol_table[i]->name, name)) {return symbol_table[i]->value;}}}return -1;}#ifdef TARGET_nios2longget_gp_value(asymbol **symbol_table, long number_of_symbols){long i;for (i=0; i<number_of_symbols; i++) {if (!strcmp(symbol_table[i]->name, "_gp"))return symbol_table[i]->value;}return -1;}#endifint32_tadd_com_to_bss(asymbol **symbol_table, int32_t number_of_symbols, int32_t bss_len){int32_t i, comsize;int32_t offset;comsize = 0;for (i=0; i<number_of_symbols; i++) {if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {offset = bss_len + comsize;comsize += symbol_table[i]->value;symbol_table[i]->value = offset;}}return comsize;}#ifdef TARGET_bfin/* FUNCTION : weak_und_symbolABSTRACT : return true if symbol is weak and undefined.*/static intweak_und_symbol(const char *reloc_section_name,struct bfd_symbol *symbol){if (!(strstr (reloc_section_name, "text")|| strstr (reloc_section_name, "data")|| strstr (reloc_section_name, "bss"))) {if (symbol->flags & BSF_WEAK) {#ifdef DEBUG_BFINfprintf(stderr, "found weak undefined symbol %s\n", symbol->name);#endifreturn TRUE;}}return FALSE;}static intbfin_set_reloc (uint32_t *reloc,const char *reloc_section_name,const char *sym_name,struct bfd_symbol *symbol,int sp, int32_t offset){unsigned int type = 0;uint32_t val;if (strstr (reloc_section_name, "stack")) {if (verbose)printf ("Stack-relative reloc, offset %08lx\n", offset);/* This must be a stack_start reloc for stack checking. */type = 1;}val = (offset & ((1 << 26) - 1));val |= (sp & (1 << 3) - 1) << 26;val |= type << 29;*reloc = val;return 0;}static bfd *compare_relocs_bfd;static intcompare_relocs (const void *pa, const void *pb){const arelent *const *a = pa, *const *b = pb;const arelent *ra = *a, *rb = *b;unsigned long va, vb;uint32_t a_vma, b_vma;if (!ra->sym_ptr_ptr || !*ra->sym_ptr_ptr)return -1;else if (!rb->sym_ptr_ptr || !*rb->sym_ptr_ptr)return 1;a_vma = bfd_section_vma(compare_relocs_bfd,(*(ra->sym_ptr_ptr))->section);b_vma = bfd_section_vma(compare_relocs_bfd,(*(rb->sym_ptr_ptr))->section);va = (*(ra->sym_ptr_ptr))->value + a_vma + ra->addend;vb = (*(rb->sym_ptr_ptr))->value + b_vma + rb->addend;return va - vb;}#endifuint32_t *output_relocs (bfd *abs_bfd,asymbol **symbols,int number_of_symbols,uint32_t *n_relocs,unsigned char *text, int text_len, uint32_t text_vma,unsigned char *data, int data_len, uint32_t data_vma,bfd *rel_bfd){uint32_t *flat_relocs;asection *a, *sym_section, *r;arelent **relpp, **p, *q;const char *sym_name, *section_name;unsigned char *sectionp;unsigned long pflags;char addstr[16];uint32_t sym_addr, sym_vma, section_vma;int relsize, relcount;int flat_reloc_count;int sym_reloc_size, rc;int got_size = 0;int bad_relocs = 0;asymbol **symb;long nsymb;#ifdef TARGET_bfinunsigned long persistent_data = 0;#endif#if 0printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d""n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",__FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,text, text_len, data, data_len);#endif#if 0dump_symbols(symbols, number_of_symbols);#endif*n_relocs = 0;flat_relocs = NULL;flat_reloc_count = 0;rc = 0;pflags = 0;/* Determine how big our offset table is in bytes.* This isn't too difficult as we've terminated the table with -1.* Also note that both the relocatable and absolute versions have this* terminator even though the relocatable one doesn't have the GOT!*/if (pic_with_got && !use_resolved) {uint32_t *lp = (uint32_t *)data;/* Should call ntohl(*lp) here but is isn't going to matter */while (*lp != 0xffffffff) lp++;got_size = ((unsigned char *)lp) - data;if (verbose)printf("GOT table contains %d entries (%d bytes)\n",got_size/sizeof(uint32_t), got_size);#ifdef TARGET_m68kif (got_size > GOT_LIMIT)fatal("GOT too large: %d bytes (limit = %d bytes)",got_size, GOT_LIMIT);#endif}for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {section_vma = bfd_section_vma(abs_bfd, a);if (verbose)printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,a->flags, section_vma);// if (bfd_is_abs_section(a))// continue;if (bfd_is_und_section(a))continue;if (bfd_is_com_section(a))continue;// if ((a->flags & SEC_RELOC) == 0)// continue;/** Only relocate things in the data sections if we are PIC/GOT.* otherwise do text as well*/if ((!pic_with_got || ALWAYS_RELOC_TEXT) && (a->flags & SEC_CODE))sectionp = text + (a->vma - text_vma);else if (a->flags & SEC_DATA)sectionp = data + (a->vma - data_vma);elsecontinue;/* Now search for the equivalent section in the relocation binary* and use that relocation information to build reloc entries* for this one.*/for (r=rel_bfd->sections; r != NULL; r=r->next)if (strcmp(a->name, r->name) == 0)break;if (r == NULL)continue;if (verbose)printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,r->flags, bfd_section_vma(abs_bfd, r));if ((r->flags & SEC_RELOC) == 0)continue;relsize = bfd_get_reloc_upper_bound(rel_bfd, r);if (relsize <= 0) {if (verbose)printf("%s(%d): no relocation entries section=0x%x\n",__FILE__, __LINE__, r->name);continue;}symb = get_symbols(rel_bfd, &nsymb);relpp = xmalloc(relsize);relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);if (relcount <= 0) {if (verbose)printf("%s(%d): no relocation entries section=%s\n",__FILE__, __LINE__, r->name);continue;} else {#ifdef TARGET_bfincompare_relocs_bfd = abs_bfd;qsort (relpp, relcount, sizeof *relpp, compare_relocs);#endiffor (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {unsigned char *r_mem;int relocation_needed = 0;#ifdef TARGET_microblaze/* The MICROBLAZE_XX_NONE relocs can be skipped.They represent PC relative branches that thelinker has already resolved */switch ((*p)->howto->type){case R_MICROBLAZE_NONE:case R_MICROBLAZE_64_NONE:case R_MICROBLAZE_32_PCREL_LO:continue;}#endif /* TARGET_microblaze */#ifdef TARGET_v850/* Skip this relocation entirely if possible (wedo this early, before doing any otherprocessing on it). */switch ((*p)->howto->type) {#ifdef R_V850_9_PCRELcase R_V850_9_PCREL:#endif#ifdef R_V850_22_PCRELcase R_V850_22_PCREL:#endif#ifdef R_V850_SDA_16_16_OFFSETcase R_V850_SDA_16_16_OFFSET:#endif#ifdef R_V850_SDA_15_16_OFFSETcase R_V850_SDA_15_16_OFFSET:#endif#ifdef R_V850_ZDA_15_16_OFFSETcase R_V850_ZDA_15_16_OFFSET:#endif#ifdef R_V850_TDA_6_8_OFFSETcase R_V850_TDA_6_8_OFFSET:#endif#ifdef R_V850_TDA_7_8_OFFSETcase R_V850_TDA_7_8_OFFSET:#endif#ifdef R_V850_TDA_7_7_OFFSETcase R_V850_TDA_7_7_OFFSET:#endif#ifdef R_V850_TDA_16_16_OFFSETcase R_V850_TDA_16_16_OFFSET:#endif#ifdef R_V850_TDA_4_5_OFFSETcase R_V850_TDA_4_5_OFFSET:#endif#ifdef R_V850_TDA_4_4_OFFSETcase R_V850_TDA_4_4_OFFSET:#endif#ifdef R_V850_SDA_16_16_SPLIT_OFFSETcase R_V850_SDA_16_16_SPLIT_OFFSET:#endif#ifdef R_V850_CALLT_6_7_OFFSETcase R_V850_CALLT_6_7_OFFSET:#endif#ifdef R_V850_CALLT_16_16_OFFSETcase R_V850_CALLT_16_16_OFFSET:#endif/* These are relative relocations, whichhave already been fixed up by thelinker at this point, so just ignorethem. */continue;}#endif /* USE_V850_RELOCS */q = *p;if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {sym_name = (*(q->sym_ptr_ptr))->name;sym_section = (*(q->sym_ptr_ptr))->section;section_name=(*(q->sym_ptr_ptr))->section->name;} else {printf("ERROR: undefined relocation entry\n");rc = -1;continue;}#ifndef TARGET_bfin/* Adjust the address to account for the GOT table which wasn't* present in the relative file link.*/if (pic_with_got && !use_resolved)q->address += got_size;#endif/* A pointer to what's being relocated, used oftenbelow. */r_mem = sectionp + q->address;/** Fixup offset in the actual section.*/addstr[0] = 0;#if !defined TARGET_e1 && !defined TARGET_bfinif ((sym_addr = get_symbol_offset((char *) sym_name,sym_section, symbols, number_of_symbols)) == -1) {sym_addr = 0;}#elsesym_addr = (*(q->sym_ptr_ptr))->value;#endifif (use_resolved) {/* Use the address of the symbol already inthe program text. How this is handled maystill depend on the particular relocationthough. */switch (q->howto->type) {int r2_type;#ifdef TARGET_v850case R_V850_HI16_S:/* We specially handle adjacentHI16_S/ZDA_15_16_OFFSET andHI16_S/LO16 pairs that reference thesame address (these are usuallymovhi/ld and movhi/movea pairs,respectively). */if (relcount == 0)r2_type = R_V850_NONE;elser2_type = p[1]->howto->type;if ((r2_type == R_V850_ZDA_15_16_OFFSET|| r2_type == R_V850_LO16)&& (p[0]->sym_ptr_ptr== p[1]->sym_ptr_ptr)&& (p[0]->addend == p[1]->addend)){relocation_needed = 1;switch (r2_type) {case R_V850_ZDA_15_16_OFFSET:pflags = 0x10000000;break;case R_V850_LO16:pflags = 0x20000000;break;}/* We don't really need theactual value -- the bitsproduced by the linker arewhat we want in the finalflat file -- but get itanyway if useful fordebugging. */if (verbose) {unsigned char *r2_mem =sectionp+ p[1]->address;/* little-endian */int hi = r_mem[0]+ (r_mem[1] << 8);int lo = r2_mem[0]+ (r2_mem[1] << 8);/* Sign extend LO. */lo = (lo ^ 0x8000)- 0x8000;/* Maybe ignore the LSBof LO, which isactually part of theinstruction. */if (r2_type != R_V850_LO16)lo &= ~1;sym_addr =(hi << 16)+ lo;}} elsegoto bad_resolved_reloc;break;case R_V850_LO16:/* See if this is actually the2nd half of a pair. */if (p > relpp&& (p[-1]->howto->type== R_V850_HI16_S)&& (p[-1]->sym_ptr_ptr== p[0]->sym_ptr_ptr)&& (p[-1]->addend == p[0]->addend))break; /* not an error */elsegoto bad_resolved_reloc;case R_V850_HI16:goto bad_resolved_reloc;default:goto good_32bit_resolved_reloc;#elif defined(TARGET_arm)case R_ARM_ABS32:relocation_needed = 1;break;case R_ARM_REL32:case R_ARM_THM_PC11:case R_ARM_THM_PC22:case R_ARM_PC24:case R_ARM_PLT32:case R_ARM_GOTPC:case R_ARM_GOT32:case R_ARM_V4BX:relocation_needed = 0;break;default:goto bad_resolved_reloc;#elif defined(TARGET_m68k)case R_68K_32:goto good_32bit_resolved_reloc;case R_68K_PC32:case R_68K_PC16:/* The linker has already resolvedPC relocs for us. In PIC links,the symbol must be in the datasegment. */case R_68K_NONE:continue;default:goto bad_resolved_reloc;#elif defined TARGET_bfincase R_BFIN_RIMM16:case R_BFIN_LUIMM16:case R_BFIN_HUIMM16:sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;if (weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))continue;if (q->howto->type == R_BFIN_RIMM16 && (0xFFFF0000 & sym_addr)) {fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name);bad_relocs++;}if ((0xFFFF0000 & sym_addr) != persistent_data) {flat_relocs = (uint32_t *)(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));if (verbose)printf ("New persistent data for %08lx\n", sym_addr);persistent_data = 0xFFFF0000 & sym_addr;flat_relocs[flat_reloc_count++]= (sym_addr >> 16) | (3 << 26);}flat_relocs = (uint32_t *)(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));if (bfin_set_reloc (flat_relocs + flat_reloc_count,sym_section->name, sym_name,(*(q->sym_ptr_ptr)),q->howto->type == R_BFIN_HUIMM16 ? 1 : 0,section_vma + q->address))bad_relocs++;if (a->flags & SEC_CODE)text_has_relocs = 1;flat_reloc_count++;break;case R_BFIN_BYTE4_DATA:sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))continue;flat_relocs = (uint32_t *)(realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));if (bfin_set_reloc (flat_relocs + flat_reloc_count,sym_section->name, sym_name,(*(q->sym_ptr_ptr)),2, section_vma + q->address))bad_relocs++;if (a->flags & SEC_CODE)text_has_relocs = 1;flat_reloc_count++;break;#elsedefault:/* The default is to assume that therelocation is relative and hasalready been fixed up by thelinker (perhaps we ought to makegive an error by default, andrequire `safe' relocations to beenumberated explicitly?). */goto good_32bit_resolved_reloc;#endifgood_32bit_resolved_reloc:if (bfd_big_endian (abs_bfd))sym_addr =(r_mem[0] << 24)+ (r_mem[1] << 16)+ (r_mem[2] << 8)+ r_mem[3];elsesym_addr =r_mem[0]+ (r_mem[1] << 8)+ (r_mem[2] << 16)+ (r_mem[3] << 24);relocation_needed = 1;break;bad_resolved_reloc:printf("ERROR: reloc type %s unsupported in this context\n",q->howto->name);bad_relocs++;break;}} else {/* Calculate the sym address ourselves. */sym_reloc_size = bfd_get_reloc_size(q->howto);#if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin) && !defined(TARGET_m68k)if (sym_reloc_size != 4) {printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",(*p)->howto->type, sym_reloc_size, sym_name);bad_relocs++;rc = -1;continue;}#endifswitch ((*p)->howto->type) {#if defined(TARGET_m68k)case R_68K_32:relocation_needed = 1;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;case R_68K_PC16:case R_68K_PC32:sym_vma = 0;sym_addr += sym_vma + q->addend;sym_addr -= q->address;break;#endif#if defined(TARGET_arm)case R_ARM_ABS32:relocation_needed = 1;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;if (verbose)fprintf(stderr,"%s vma=0x%x, value=0x%x, address=0x%x ""sym_addr=0x%x rs=0x%x, opcode=0x%x\n","ABS32",sym_vma, (*(q->sym_ptr_ptr))->value,q->address, sym_addr,(*p)->howto->rightshift,*(uint32_t *)r_mem);break;case R_ARM_GOT32:case R_ARM_GOTPC:case R_ARM_V4BX:/* Should be fine as is */break;case R_ARM_PLT32:if (verbose)fprintf(stderr,"%s vma=0x%x, value=0x%x, address=0x%x ""sym_addr=0x%x rs=0x%x, opcode=0x%x\n","PLT32",0, (*(q->sym_ptr_ptr))->value,q->address, (sym_addr-q->address)>>(*p)->howto->rightshift,(*p)->howto->rightshift,*(uint32_t *)r_mem);case R_ARM_PC24:case R_ARM_JUMP24:case R_ARM_CALL:sym_vma = 0;sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;break;#endif#ifdef TARGET_v850case R_V850_32:relocation_needed = 1;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;#if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)#ifdef R_V850_ZDA_16_16_OFFSETcase R_V850_ZDA_16_16_OFFSET:#endif#ifdef R_V850_ZDA_16_16_SPLIT_OFFSETcase R_V850_ZDA_16_16_SPLIT_OFFSET:#endif/* Can't support zero-relocations. */printf ("ERROR: %s+0x%x: zero relocations not supported\n",sym_name, q->addend);continue;#endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */#endif /* TARGET_v850 */#ifdef TARGET_h8300case R_H8_DIR24R8:if (sym_reloc_size != 4) {printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);bad_relocs++;continue;}relocation_needed = 1;sym_addr = (*(q->sym_ptr_ptr))->value;q->address -= 1;r_mem -= 1; /* tracks q->address */sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;sym_addr |= (*(unsigned char *)r_mem<<24);break;case R_H8_DIR24A8:if (sym_reloc_size != 4) {printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);bad_relocs++;continue;}/* Absolute symbol done not relocation */relocation_needed = !bfd_is_abs_section(sym_section);sym_addr = (*(q->sym_ptr_ptr))->value;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;case R_H8_DIR32:case R_H8_DIR32A16: /* currently 32, could be made 16 */if (sym_reloc_size != 4) {printf("R_H8_DIR32 size %d\n", sym_reloc_size);bad_relocs++;continue;}relocation_needed = 1;sym_addr = (*(q->sym_ptr_ptr))->value;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;case R_H8_PCREL16:sym_vma = 0;sym_addr = (*(q->sym_ptr_ptr))->value;sym_addr += sym_vma + q->addend;sym_addr -= (q->address + 2);if (bfd_big_endian(abs_bfd))*(unsigned short *)r_mem =bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;continue;case R_H8_PCREL8:sym_vma = 0;sym_addr = (*(q->sym_ptr_ptr))->value;sym_addr += sym_vma + q->addend;sym_addr -= (q->address + 1);*(unsigned char *)r_mem = sym_addr;continue;#endif#ifdef TARGET_microblazecase R_MICROBLAZE_64:/* The symbol is split over two consecutive instructions.Flag this to the flat loader by setting the high bit ofthe relocation symbol. */{unsigned char *p = r_mem;pflags=0x80000000;/* work out the relocation */sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;/* Write relocated pointer back */p[2] = (sym_addr >> 24) & 0xff;p[3] = (sym_addr >> 16) & 0xff;p[6] = (sym_addr >> 8) & 0xff;p[7] = sym_addr & 0xff;/* create a new reloc entry */flat_relocs = realloc(flat_relocs,(flat_reloc_count + 1) * sizeof(uint32_t));flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);flat_reloc_count++;relocation_needed = 0;pflags = 0;sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -bfd_section_vma(abs_bfd, sym_section));if (verbose)printf(" RELOC[%d]: offset=0x%x symbol=%s%s ""section=%s size=%d ""fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,q->address, sym_name, addstr,section_name, sym_reloc_size,sym_addr, section_vma + q->address);if (verbose)printf("reloc[%d] = 0x%x\n", flat_reloc_count,section_vma + q->address);continue;}case R_MICROBLAZE_32:{unsigned char *p = r_mem;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;relocation_needed = 1;break;}case R_MICROBLAZE_64_PCREL:sym_vma = 0;sym_addr += sym_vma + q->addend;sym_addr -= (q->address + 4);sym_addr = htonl(sym_addr);/* insert 16 MSB */* ((unsigned short *) (r_mem+2)) = (sym_addr) & 0xFFFF;/* then 16 LSB */* ((unsigned short *) (r_mem+6)) = (sym_addr >> 16) & 0xFFFF;/* We've done all the work, so continueto next reloc instead of break */continue;#endif /* TARGET_microblaze */#ifdef TARGET_nios2#define htoniosl(x) (x)#define niostohl(x) (x)case R_NIOS2_BFD_RELOC_32:relocation_needed = 1;pflags = (FLAT_NIOS2_R_32 << 28);sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;/* modify target, in target order */*(unsigned long *)r_mem = htoniosl(sym_addr);break;case R_NIOS2_CALL26:{unsigned long exist_val;relocation_needed = 1;pflags = (FLAT_NIOS2_R_CALL26 << 28);sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;/* modify target, in target order */// exist_val = niostohl(*(unsigned long *)r_mem);exist_val = ((sym_addr >> 2) << 6);*(unsigned long *)r_mem = htoniosl(exist_val);break;}case R_NIOS2_HIADJ16:case R_NIOS2_HI16:{unsigned long exist_val;int r2_type;/* handle the adjacent HI/LO pairs */if (relcount == 0)r2_type = R_NIOS2_NONE;elser2_type = p[1]->howto->type;if ((r2_type == R_NIOS2_LO16)&& (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)&& (p[0]->addend == p[1]->addend)){unsigned char * r2_mem = sectionp + p[1]->address;if (p[1]->address - q->address!=4)printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);relocation_needed = 1;pflags = (q->howto->type == R_NIOS2_HIADJ16)? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;pflags <<= 28;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;/* modify high 16 bits, in target order */exist_val = niostohl(*(unsigned long *)r_mem);exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);if (q->howto->type == R_NIOS2_HIADJ16)exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);elseexist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);*(unsigned long *)r_mem = htoniosl(exist_val);/* modify low 16 bits, in target order */exist_val = niostohl(*(unsigned long *)r2_mem);exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);exist_val |= ((sym_addr & 0xFFFF) << 6);*(unsigned long *)r2_mem = htoniosl(exist_val);} elsegoto NIOS2_RELOC_ERR;}break;case R_NIOS2_GPREL:{unsigned long exist_val, temp;//long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);long gp = get_gp_value(symbols, number_of_symbols);if (gp == -1) {printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);goto NIOS2_RELOC_ERR;}/* _gp holds a absolute value, otherwise the ld cannot generate correct code */sym_vma = bfd_section_vma(abs_bfd, sym_section);//printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);sym_addr += sym_vma + q->addend;sym_addr -= gp;//printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);/* modify the target, in target order (little_endian) */exist_val = niostohl(*(unsigned long *)r_mem);temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);temp <<= 6;temp |= (exist_val & 0x3f);*(unsigned long *)r_mem = htoniosl(temp);if (verbose)printf("omit: offset=0x%x symbol=%s%s ""section=%s size=%d ""fixup=0x%x (reloc=0x%x) GPREL\n",q->address, sym_name, addstr,section_name, sym_reloc_size,sym_addr, section_vma + q->address);continue;}case R_NIOS2_PCREL16:{unsigned long exist_val;sym_vma = 0;sym_addr += sym_vma + q->addend;sym_addr -= (q->address + 4);/* modify the target, in target order (little_endian) */exist_val = niostohl(*(unsigned long *)r_mem);exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);exist_val |= ((sym_addr & 0xFFFF) << 6);*(unsigned long *)r_mem = htoniosl(exist_val);if (verbose)printf("omit: offset=0x%x symbol=%s%s ""section=%s size=%d ""fixup=0x%x (reloc=0x%x) PCREL\n",q->address, sym_name, addstr,section_name, sym_reloc_size,sym_addr, section_vma + q->address);continue;}case R_NIOS2_LO16:/* check if this is actually the 2nd half of a pair */if ((p > relpp)&& ((p[-1]->howto->type == R_NIOS2_HIADJ16)|| (p[-1]->howto->type == R_NIOS2_HI16))&& (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)&& (p[-1]->addend == p[0]->addend)) {if (verbose)printf("omit: offset=0x%x symbol=%s%s ""section=%s size=%d LO16\n",q->address, sym_name, addstr,section_name, sym_reloc_size);continue;}/* error, fall through */case R_NIOS2_S16:case R_NIOS2_U16:case R_NIOS2_CACHE_OPX:case R_NIOS2_IMM5:case R_NIOS2_IMM6:case R_NIOS2_IMM8:case R_NIOS2_BFD_RELOC_16:case R_NIOS2_BFD_RELOC_8:case R_NIOS2_GNU_VTINHERIT:case R_NIOS2_GNU_VTENTRY:case R_NIOS2_UJMP:case R_NIOS2_CJMP:case R_NIOS2_CALLR:NIOS2_RELOC_ERR:printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);bad_relocs++;continue;#endif /* TARGET_nios2 */#ifdef TARGET_sparccase R_SPARC_32:case R_SPARC_UA32:relocation_needed = 1;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;case R_SPARC_PC22:sym_vma = 0;sym_addr += sym_vma + q->addend;sym_addr -= q->address;break;case R_SPARC_WDISP30:sym_addr = (((*(q->sym_ptr_ptr))->value-q->address) >> 2) & 0x3fffffff;sym_addr |= (ntohl(*(uint32_t *)r_mem)& 0xc0000000);break;case R_SPARC_HI22:relocation_needed = 1;pflags = 0x80000000;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;sym_addr |= (htonl(*(uint32_t *)r_mem)& 0xffc00000);break;case R_SPARC_LO10:relocation_needed = 1;pflags = 0x40000000;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;sym_addr &= 0x000003ff;sym_addr |= (htonl(*(uint32_t *)r_mem)& 0xfffffc00);break;#endif /* TARGET_sparc */#ifdef TARGET_shcase R_SH_DIR32:relocation_needed = 1;sym_vma = bfd_section_vma(abs_bfd, sym_section);sym_addr += sym_vma + q->addend;break;case R_SH_REL32:sym_vma = 0;sym_addr += sym_vma + q->addend;sym_addr -= q->address;break;#endif /* TARGET_sh */#ifdef TARGET_e1#define htoe1l(x) htonl(x)#if 0#define DEBUG_E1#endif#ifdef DEBUG_E1#define DBG_E1 printf#else#define DBG_E1(x, ... )#endif#define _32BITS_RELOC 0x00000000#define _30BITS_RELOC 0x80000000#define _28BITS_RELOC 0x40000000{char *p;unsigned long sec_vma, exist_val, S;case R_E1_CONST31:relocation_needed = 1;DBG_E1("Handling Reloc <CONST31>\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",sec_vma, sym_addr, q->address);sym_addr = sec_vma + sym_addr;exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);sym_addr += exist_val;pflags = _30BITS_RELOC;break;case R_E1_CONST31_PCREL:relocation_needed = 0;DBG_E1("Handling Reloc <CONST31_PCREL>\n");DBG_E1("DONT RELOCATE AT LOADING\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",sec_vma, sym_addr, q->address);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,section_vma );q->address = q->address + section_vma;DBG_E1("q->address += section_vma : 0x%x\n", q->address );if( (sym_addr = (sym_addr - q->address - 6)) < 0 )DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");DBG_E1( "sym_addr := sym_addr - q->address - ""sizeof(CONST31_PCREL): [0x%x]\n",sym_addr );exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);sym_addr |= exist_val;DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr );break;case R_E1_DIS29W_PCREL:relocation_needed = 0;DBG_E1("Handling Reloc <DIS29W_PCREL>\n");DBG_E1("DONT RELOCATE AT LOADING\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",sec_vma, sym_addr, q->address);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,section_vma );q->address = q->address + section_vma;DBG_E1("q->address += section_vma : 0x%x\n", q->address );if( (sym_addr = (sym_addr - q->address - 6)) < 0 )DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");DBG_E1( "sym_addr := sym_addr - q->address - ""sizeof(CONST31_PCREL): [0x%x]\n",sym_addr );DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);sym_addr += exist_val;break;case R_E1_DIS29W:DBG_E1("Handling Reloc <DIS29W>\n");goto DIS29_RELOCATION;case R_E1_DIS29H:DBG_E1("Handling Reloc <DIS29H>\n");goto DIS29_RELOCATION;case R_E1_DIS29B:DBG_E1("Handling Reloc <DIS29B>\n");DIS29_RELOCATION:relocation_needed = 1;sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",sec_vma, sym_addr);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr);exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);sym_addr += exist_val;DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);pflags = _28BITS_RELOC;break;case R_E1_IMM32_PCREL:relocation_needed = 0;DBG_E1("Handling Reloc <IMM32_PCREL>\n");DBG_E1("DONT RELOCATE AT LOADING\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",sec_vma, sym_addr);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,section_vma );q->address = q->address + section_vma;DBG_E1("q->address += section_vma : 0x%x\n", q->address );if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");DBG_E1( "sym_addr := sym_addr - q->address - ""sizeof(CONST31_PCREL): [0x%x]\n",sym_addr );DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);sym_addr += exist_val;break;case R_E1_IMM32:relocation_needed = 1;DBG_E1("Handling Reloc <IMM32>\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",sec_vma, sym_addr);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);sym_addr += exist_val;pflags = _32BITS_RELOC;break;case R_E1_WORD:relocation_needed = 1;DBG_E1("Handling Reloc <WORD>\n");sec_vma = bfd_section_vma(abs_bfd, sym_section);DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",sec_vma, sym_addr);sym_addr = sec_vma + sym_addr;DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr );exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);exist_val = htoe1l(exist_val);DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);sym_addr += exist_val;DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr);pflags = _32BITS_RELOC;break;}#undef _32BITS_RELOC#undef _30BITS_RELOC#undef _28BITS_RELOC#endifdefault:/* missing support for other types of relocs */printf("ERROR: bad reloc type %d\n", (*p)->howto->type);bad_relocs++;continue;}}sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -bfd_section_vma(abs_bfd, sym_section));#if 0/** for full elf relocation we have to write back the* start_code relative value to use.*/if (!pic_with_got) {#if defined(TARGET_arm)union {unsigned char c[4];uint32_t l;} tmp;int32_t hl;int i0, i1, i2, i3;/** horrible nasty hack to support different endianess*/if (!bfd_big_endian(abs_bfd)) {i0 = 0;i1 = 1;i2 = 2;i3 = 3;} else {i0 = 3;i1 = 2;i2 = 1;i3 = 0;}tmp.l = *(uint32_t *)r_mem;hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);if (use_resolved ||(((*p)->howto->type != R_ARM_PC24) &&((*p)->howto->type != R_ARM_PLT32)))hl |= (tmp.c[i3] << 24);else if (tmp.c[i2] & 0x80)hl |= 0xff000000; /* sign extend */if (!use_resolved)hl += sym_addr;tmp.c[i0] = hl & 0xff;tmp.c[i1] = (hl >> 8) & 0xff;tmp.c[i2] = (hl >> 16) & 0xff;if (use_resolved ||(((*p)->howto->type != R_ARM_PC24) &&((*p)->howto->type != R_ARM_PLT32)))tmp.c[i3] = (hl >> 24) & 0xff;if ((*p)->howto->type == R_ARM_ABS32)*(uint32_t *)r_mem = hl;else*(uint32_t *)r_mem = tmp.l;#elif defined(TARGET_e1)#define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/switch ((*p)->howto->type) {case R_E1_CONST31:case R_E1_CONST31_PCREL:case R_E1_DIS29W_PCREL:case R_E1_DIS29W:case R_E1_DIS29H:case R_E1_DIS29B:case R_E1_IMM32_PCREL:case R_E1_IMM32:DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",(sectionp + q->address + 2), sym_addr );*((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =htonl(sym_addr);break;case R_E1_WORD:DBG_E1("In addr : [0x%x] <- write [0x%x]\n",(sectionp + q->address), sym_addr );*((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);break;default:printf("ERROR:Unhandled Relocation. Exiting...\n");exit(0);break;}#elif defined TARGET_bfinif ((*p)->howto->type == R_BFIN_RIMM16|| (*p)->howto->type == R_BFIN_HUIMM16|| (*p)->howto->type == R_BFIN_LUIMM16){/* for l and h we set the lower 16 bits which is only when it will be used */bfd_putl16 (sym_addr, sectionp + q->address);} else if ((*p)->howto->type == R_BFIN_BYTE4_DATA) {bfd_putl32 (sym_addr, sectionp + q->address);}#else /* ! TARGET_arm && ! TARGET_e1 && ! TARGET_bfin */switch (q->howto->type) {#ifdef TARGET_v850case R_V850_HI16_S:case R_V850_HI16:case R_V850_LO16:/* Do nothing -- for cases we handle,the bits produced by the linker arewhat we want in the final flat file(and other cases are errors). Notethat unlike most relocated values,it is stored in little-endian order,but this is necessary to avoidtrashing the low-bit, and the floatloaders knows about it. */break;#endif /* TARGET_V850 */#ifdef TARGET_nios2case R_NIOS2_BFD_RELOC_32:case R_NIOS2_CALL26:case R_NIOS2_HIADJ16:case R_NIOS2_HI16:/* do nothing */break;#endif /* TARGET_nios2 */#if defined(TARGET_m68k)case R_68K_PC16:if (sym_addr < -0x8000 || sym_addr > 0x7fff) {fprintf (stderr, "Relocation overflow for R_68K_PC16 relocation against %s\n", sym_name);bad_relocs++;} else {r_mem[0] = (sym_addr >> 8) & 0xff;r_mem[1] = sym_addr & 0xff;}break;#endifdefault:/* The alignment of the build hostmight be stricter than that of thetarget, so be careful. We store innetwork byte order. */r_mem[0] = (sym_addr >> 24) & 0xff;r_mem[1] = (sym_addr >> 16) & 0xff;r_mem[2] = (sym_addr >> 8) & 0xff;r_mem[3] = sym_addr & 0xff;}#endif /* !TARGET_arm */}#endifif (verbose)printf(" RELOC[%d]: offset=0x%x symbol=%s%s ""section=%s size=%d ""fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,q->address, sym_name, addstr,section_name, sym_reloc_size,sym_addr, section_vma + q->address);/** Create relocation entry (PC relative doesn't need this).*/if (relocation_needed) {#ifndef TARGET_bfinflat_relocs = realloc(flat_relocs,(flat_reloc_count + 1) * sizeof(uint32_t));#ifndef TARGET_e1flat_relocs[flat_reloc_count] = pflags |(section_vma + q->address);if (verbose)printf("reloc[%d] = 0x%x\n", flat_reloc_count,section_vma + q->address);#elseswitch ((*p)->howto->type) {case R_E1_CONST31:case R_E1_CONST31_PCREL:case R_E1_DIS29W_PCREL:case R_E1_DIS29W:case R_E1_DIS29H:case R_E1_DIS29B:case R_E1_IMM32_PCREL:case R_E1_IMM32:flat_relocs[flat_reloc_count] = pflags |(section_vma + q->address + OPCODE_SIZE);if (verbose)printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,flat_relocs[flat_reloc_count] );break;case R_E1_WORD:flat_relocs[flat_reloc_count] = pflags |(section_vma + q->address);if (verbose)printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,flat_relocs[flat_reloc_count] );break;}#endifflat_reloc_count++;#endif //TARGET_bfinrelocation_needed = 0;pflags = 0;}#if 0printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",__FILE__, __LINE__, sym_name, q->address, section_name,flat_relocs[flat_reloc_count]);#endif}}}if (bad_relocs) {printf("%d bad relocs\n", bad_relocs);exit(1);}if (rc < 0)return(0);*n_relocs = flat_reloc_count;return flat_relocs;}static void usage(void){fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] ""[-o <output-file>] <elf-file>\n\n"" -v : verbose operation\n"" -l : the file to be processed is a shared library\n"" -z : compress code/data/relocs\n"" -a : use existing symbol references\n"" instead of recalculating from\n"" relocation info\n"" -R reloc-file : read relocations from a separate file\n"" -p abs-pic-file : GOT/PIC processing with files\n"" -s stacksize : set application stack size\n"" -o output-file : output file name\n\n",elf2flt_progname);fprintf(stderr, "Compiled for " ARCH " architecture\n\n");exit(2);}/* Write NUM zeroes to STREAM. */static void write_zeroes (unsigned long num, stream *stream){char zeroes[1024];if (num > 0) {/* It'd be nice if we could just use fseek, but that doesn't seem towork for stdio output files. */memset(zeroes, 0x00, 1024);while (num > sizeof(zeroes)) {fwrite_stream(zeroes, sizeof(zeroes), 1, stream);num -= sizeof(zeroes);}if (num > 0)fwrite_stream(zeroes, num, 1, stream);}}int main(int argc, char *argv[]){int fd;bfd *rel_bfd, *abs_bfd;asection *s;char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;char *fname = NULL;int opt;int i;int stack;stream gf;asymbol **symbol_table;long number_of_symbols;uint32_t data_len = 0;uint32_t bss_len = 0;uint32_t text_len = 0;uint32_t reloc_len;uint32_t data_vma = ~0;uint32_t bss_vma = ~0;uint32_t text_vma = ~0;uint32_t text_offs;void *text;void *data;uint32_t *reloc;struct emcoreapp_header hdr;elf2flt_progname = argv[0];xmalloc_set_program_name(elf2flt_progname);if (argc < 2)usage();#ifndef TARGET_e1stack = 4096;#else /* We need plenty of stack for both of them (Aggregate and Register) */stack = 0x2020;#endifwhile ((opt = getopt(argc, argv, "avzlp:s:o:R:")) != -1) {switch (opt) {case 'v':verbose++;break;case 'l':lib = 1;break;case 'z':docompress = 1;break;case 'p':pfile = optarg;break;case 'o':ofile = optarg;break;case 'a':use_resolved = 1;break;case 's':if (sscanf(optarg, "%i", &stack) != 1) {fprintf(stderr, "%s invalid stack size %s\n", argv[0], optarg);usage();}break;case 'R':rel_file = optarg;break;default:fprintf(stderr, "%s Unknown option\n", argv[0]);usage();break;}}fname = argv[argc-1];if (pfile) {pic_with_got = 1;abs_file = pfile;} elseabs_file = fname;if (! rel_file)rel_file = fname;if (!(rel_bfd = bfd_openr(rel_file, 0)))fatal_perror("Can't open '%s'", rel_file);if (bfd_check_format (rel_bfd, bfd_object) == 0)fatal("File is not an object file");if (abs_file == rel_file)abs_bfd = rel_bfd; /* one file does all */else {if (!(abs_bfd = bfd_openr(abs_file, 0)))fatal_perror("Can't open '%s'", abs_file);if (bfd_check_format (abs_bfd, bfd_object) == 0)fatal("File is not an object file");}if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC))fatal("%s: Input file contains no relocation info", rel_file);if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P))/* `Absolute' file is not absolute, so neither are addresscontained therein. */fatal("%s: `-a' option specified with non-fully-resolved input file",bfd_get_filename (abs_bfd));symbol_table = get_symbols(abs_bfd, &number_of_symbols);/* Group output sections into text, data, and bss, and calc their sizes. */for (s = abs_bfd->sections; s != NULL; s = s->next) {uint32_t *vma, *len;bfd_size_type sec_size;bfd_vma sec_vma;if (s->flags & SEC_CODE) {vma = &text_vma;len = &text_len;} else if (s->flags & SEC_DATA) {vma = &data_vma;len = &data_len;} else if (s->flags & SEC_ALLOC) {vma = &bss_vma;len = &bss_len;} elsecontinue;sec_size = bfd_section_size(abs_bfd, s);sec_vma = bfd_section_vma(abs_bfd, s);if (sec_vma < *vma) {if (*len > 0)*len += sec_vma - *vma;else*len = sec_size;*vma = sec_vma;} else if (sec_vma + sec_size > *vma + *len)*len = sec_vma + sec_size - *vma;}if (text_len == 0)fatal("%s: no .text section", abs_file);text = xmalloc(text_len);if (verbose)printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);/* Read in all text sections. */for (s = abs_bfd->sections; s != NULL; s = s->next)if (s->flags & SEC_CODE)if (!bfd_get_section_contents(abs_bfd, s,text + (s->vma - text_vma), 0,bfd_section_size(abs_bfd, s))){fatal("read error section %s", s->name);}if (data_len == 0)fatal("%s: no .data section", abs_file);data = xmalloc(data_len);if (verbose)printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);if ((text_vma + text_len) != data_vma) {if ((text_vma + text_len) > data_vma) {printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);exit(1);}if (verbose)printf("WARNING: data=0x%x does not directly follow text=0x%x\n",data_vma, text_len);text_len = data_vma - text_vma;}/* Read in all data sections. */for (s = abs_bfd->sections; s != NULL; s = s->next)if (s->flags & SEC_DATA)if (!bfd_get_section_contents(abs_bfd, s,data + (s->vma - data_vma), 0,bfd_section_size(abs_bfd, s))){fatal("read error section %s", s->name);}if (bss_vma == ~0)bss_vma = data_vma + data_len;/* Put common symbols in bss. */bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);if (verbose)printf("BSS -> vma=0x%x len=0x%x\n", bss_vma, bss_len);if ((data_vma + data_len) != bss_vma) {if ((data_vma + data_len) > bss_vma) {printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,data_len, bss_vma);exit(1);}if (verbose)printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",bss_vma, text_len, data_len, text_len + data_len);data_len = bss_vma - data_vma;}reloc = (uint32_t *)output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,text, text_len, text_vma, data, data_len, data_vma, rel_bfd);if (reloc == NULL && verbose)printf("No relocations in code!\n");text_offs = real_address_bits(text_vma);/* Fill in the binflt_flat header */memcpy(hdr.signature, "emCOexec", 8);hdr.version = EMCOREAPP_HEADER_VERSION;hdr.textstart = sizeof(hdr);hdr.textsize = text_len + data_len;hdr.bsssize = bss_len;hdr.stacksize = stack;hdr.entrypoint = bfd_get_start_address(abs_bfd);hdr.relocstart = sizeof(hdr) + text_len + data_len;hdr.reloccount = reloc_len;hdr.flags = (docompress ? EMCOREAPP_FLAG_COMPRESSED : 0)| (lib ? EMCOREAPP_FLAG_LIBRARY : 0);hdr.creationtime = (uint32_t)time(NULL);for (i=0; i<reloc_len; i++) reloc[i] = reloc[i];if (verbose) {printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",text_len, data_len, bss_len);if (reloc)printf(", relocs=0x%04x", reloc_len);printf("\n");}if (!ofile) {ofile = xmalloc(strlen(fname) + 10 + 1); /* 10 to add suffix */strcpy(ofile, fname);if (lib) strcat(ofile, ".emcorelib");else strcat(ofile, ".emcoreapp");}if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0)fatal_perror("Can't open output file %s", ofile);write(fd, &hdr, sizeof(hdr));close(fd);if (fopen_stream_u(&gf, ofile, "a" BINARY_FILE_OPTS))fatal_perror("Can't open file %s for writing", ofile);if (docompress == 1)reopen_stream_compressed(&gf);/* Fill in any hole at the beginning of the text segment. */if (verbose)printf("ZERO before text len=0x%x\n", text_offs);write_zeroes(text_offs, &gf);/* Write the text segment. */fwrite_stream(text, text_len, 1, &gf);if (docompress == 2)reopen_stream_compressed(&gf);/* Write the data segment. */fwrite_stream(data, data_len, 1, &gf);if (reloc)fwrite_stream(reloc, reloc_len * 4, 1, &gf);fclose_stream(&gf);exit(0);}/** this __MUST__ be at the VERY end of the file - do NOT move!!** Local Variables:* c-basic-offset: 4* tab-width: 8* end:* vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab*/