X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=elf2flt.c;h=23cd4a99d2aeb2daf8d12736a337b50496797dcd;hb=29ba55b4e6ac0ceb6f96fbc967863eb6b72ff05b;hp=23e5e978e2021ceba0b1a80b6536bc28ef88d710;hpb=8784cd929f19dd579b01fc515afbf88a4e889145;p=uclinux-h8%2Felf2flt.git diff --git a/elf2flt.c b/elf2flt.c index 23e5e97..23cd4a9 100644 --- a/elf2flt.c +++ b/elf2flt.c @@ -6,7 +6,11 @@ * 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 + * (c) 2004, Nios II support, Wentao Xu * (c) 2003, H8 support, ktrace + * (c) 2003-2004, MicroBlaze support, John Williams * (c) 2001-2003, arm/arm-pic/arm-big-endian support * (c) 2001, v850 changes, Mile Bader * (c) 2003, SuperH support, Paul Mundt @@ -40,22 +44,33 @@ #include /* Userland prototypes of the Unix std system calls */ #include /* Flag value for file handling functions */ #include - +#ifndef WIN32 #include /* Consts and structs defined by the internet system */ +#define BINARY_FILE_OPTS +#else +#include +#define BINARY_FILE_OPTS "b" +#endif /* from $(INSTALLDIR)/include */ #include /* Main header file for the BFD library */ #if defined(TARGET_h8300) #include /* 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 /* TARGET_* ELF support for the BFD library */ -#elif defined(__CYGWIN__) -#include "cygwin-elf.h" /* Cygwin uses a local copy */ +#elif defined(TARGET_bfin) +#include "elf/bfin.h" #else #include /* TARGET_* ELF support for the BFD library */ #endif +#if defined(__MINGW32__) +#include +#endif + /* from uClinux-x.x.x/include/linux */ #include "flat.h" /* Binary flat header description */ @@ -83,11 +98,24 @@ #define ARCH "microblaze" #elif defined(TARGET_e1) #define ARCH "e1-coff" +#elif defined(TARGET_bfin) +#define ARCH "bfin" +#define FLAT_RELOC_TYPE_TEXT 0 +#define FLAT_RELOC_TYPE_DATA 1 +#define FLAT_RELOC_TYPE_BSS 2 +#define FLAT_RELOC_TYPE_STACK 3 +#define FLAT_RELOC_PART_LO 0 +#define FLAT_RELOC_PART_HI 1 +#define PCREL24_MAGIC_OFFSET -1 +#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 -#if defined(TARGET_m68k) || defined(TARGET_h8300) +#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. @@ -207,7 +235,7 @@ get_symbols (bfd *abfd, long *num) if (storage_needed == 0) return NULL; - symbol_table = (asymbol **) malloc (storage_needed); + symbol_table = xmalloc (storage_needed); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); @@ -242,7 +270,7 @@ get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number for (i=0; isection == sec) { if (!strcmp(symbol_table[i]->name, name)) { - return symbol_table[i]->value; + return symbol_table[i]->value; } } } @@ -252,6 +280,19 @@ get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number long +get_gp_value(asymbol **symbol_table, long number_of_symbols) +{ + long i; + for (i=0; iname, "_gp")) + return symbol_table[i]->value; + } + return -1; +} + + + +long add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len) { long i, comsize; @@ -268,9 +309,75 @@ add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len) return comsize; } +#ifdef TARGET_bfin +/* FUNCTION : weak_und_symbol + ABSTRACT : return true if symbol is weak and undefined. +*/ +static int +weak_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_BFIN + fprintf(stderr, "found weak undefined symbol %s\n", symbol->name); +#endif + return TRUE; + } + } + return FALSE; +} + +static int +bfin_set_reloc (uint32_t *reloc, + const char *reloc_section_name, + const char *sym_name, + struct bfd_symbol *symbol, + int sp, int hilo, int32_t offset) +{ + unsigned int type; + uint32_t val; + + if (strstr (reloc_section_name, "text")) + type = FLAT_RELOC_TYPE_TEXT; + else if (strstr (reloc_section_name, "data")) + type = FLAT_RELOC_TYPE_DATA; + else if (strstr (reloc_section_name, "bss")) + type = FLAT_RELOC_TYPE_BSS; + else if (strstr (reloc_section_name, "stack")) + type = FLAT_RELOC_TYPE_STACK; + else if (symbol->flags & BSF_WEAK){ + /* weak symbol support ... if a weak symbol is undefined at the + end of a final link, it should return 0 rather than error + We will assume text section for the moment. + */ + type = FLAT_RELOC_TYPE_TEXT; + } else if (strstr (reloc_section_name, "*ABS*")){ + /* (A data section initialization of something in the shared libc's text section + does not resolve - i.e. a global pointer to function initialized with + a libc function). + The text section here is appropriate as the section information + of the shared library is lost. The loader will do some calcs. + */ + type = FLAT_RELOC_TYPE_TEXT; + } else { + printf ("Unknown Type - relocation for %s in bad section - %s\n", sym_name, reloc_section_name); + return 1; + } + + val = (offset & ((1 << 26) - 1)) << 6; + val |= (sp & (1 << 3) - 1) << 3; + val |= (hilo & 1) << 2; + val |= (type & (1 << 2) - 1); + *reloc = val; + return 0; +} +#endif -unsigned long * +uint32_t * output_relocs ( bfd *abs_bfd, asymbol **symbols, @@ -280,7 +387,7 @@ output_relocs ( unsigned char *data, int data_len, unsigned long data_vma, bfd *rel_bfd) { - unsigned long *flat_relocs; + uint32_t *flat_relocs; asection *a, *sym_section, *r; arelent **relpp, **p, *q; const char *sym_name, *section_name; @@ -318,7 +425,7 @@ dump_symbols(symbols, number_of_symbols); * 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) { + if (pic_with_got && !use_resolved) { unsigned long *lp = (unsigned long *)data; /* Should call ntohl(*lp) here but is isn't going to matter */ while (*lp != 0xffffffff) lp++; @@ -385,7 +492,8 @@ dump_symbols(symbols, number_of_symbols); } symb = get_symbols(rel_bfd, &nsymb); - relpp = (arelent **) xmalloc(relsize); + relpp = xmalloc(relsize); + relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb); if (relcount <= 0) { if (verbose) @@ -409,7 +517,7 @@ dump_symbols(symbols, number_of_symbols); continue; } #endif /* TARGET_microblaze */ - + #ifdef TARGET_v850 /* Skip this relocation entirely if possible (we do this early, before doing any other @@ -475,12 +583,14 @@ dump_symbols(symbols, number_of_symbols); 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) + if (pic_with_got && !use_resolved) q->address += got_size; - +#endif + /* A pointer to what's being relocated, used often below. */ r_mem = sectionp + q->address; @@ -565,7 +675,7 @@ dump_symbols(symbols, number_of_symbols); + lo; } } else - goto bad_v850_reloc_err; + goto bad_resolved_reloc; break; case R_V850_LO16: @@ -579,16 +689,37 @@ dump_symbols(symbols, number_of_symbols); && (p[-1]->addend == p[0]->addend)) break; /* not an error */ else - goto bad_v850_reloc_err; + goto bad_resolved_reloc; case R_V850_HI16: - bad_v850_reloc_err: - printf("ERROR: reloc type %s unsupported in this context\n", - q->howto->name); - bad_relocs++; + 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: + relocation_needed = 0; break; -#endif /* TARGET_V850 */ - + 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 resolved + PC relocs for us. In PIC links, + the symbol must be in the data + segment. */ + case R_68K_NONE: + continue; + default: + goto bad_resolved_reloc; +#else default: /* The default is to assume that the relocation is relative and has @@ -597,6 +728,9 @@ dump_symbols(symbols, number_of_symbols); give an error by default, and require `safe' relocations to be enumberated explicitly?). */ + goto good_32bit_resolved_reloc; +#endif + good_32bit_resolved_reloc: if (bfd_big_endian (abs_bfd)) sym_addr = (r_mem[0] << 24) @@ -610,12 +744,19 @@ dump_symbols(symbols, number_of_symbols); + (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) +#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); @@ -633,6 +774,7 @@ dump_symbols(symbols, number_of_symbols); 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; @@ -716,13 +858,11 @@ dump_symbols(symbols, number_of_symbols); bad_relocs++; continue; } - relocation_needed = 1; + /* 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; - /* no reloc from area7 */ - if (sym_addr > 0xe00000) - relocation_needed = 0; break; case R_H8_DIR32: case R_H8_DIR32A16: /* currently 32, could be made 16 */ @@ -778,7 +918,7 @@ dump_symbols(symbols, number_of_symbols); /* create a new reloc entry */ flat_relocs = realloc(flat_relocs, - (flat_reloc_count + 1) * sizeof(unsigned long)); + (flat_reloc_count + 1) * sizeof(uint32_t)); flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address); flat_reloc_count++; relocation_needed = 0; @@ -837,6 +977,163 @@ dump_symbols(symbols, number_of_symbols); #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; + else + r2_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); + else + exist_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); + + } else + goto 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_sparc case R_SPARC_32: case R_SPARC_UA32: @@ -880,6 +1177,113 @@ dump_symbols(symbols, number_of_symbols); break; #endif /* TARGET_sparc */ +#ifdef TARGET_bfin + case R_pcrel12_jump: + case R_pcrel12_jump_s: + case R_pcrel24: + case R_pcrel24_jump_l: + case R_pcrel24_jump_x: + case R_pcrel24_call_x: + case R_pcrel10: + case R_pcrel11: + case R_pcrel5m2: + sym_addr += q->addend;// get the symbol addr + sym_vma = bfd_section_vma(abs_bfd, sym_section); + sym_addr -= q->address; // make it PC relative + // implicitly assumes code section and symbol section are same + break; + case R_got: + /* Ignore these. */ + break; + + case R_rimm16: + sym_addr += q->addend; + if(weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr)))) + continue; + if(0xFFFF0000 & sym_addr){ + fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name); + bad_relocs++; + } + 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)), + 0, FLAT_RELOC_PART_LO, + section_vma + q->address)) + bad_relocs++; + flat_reloc_count++; + break; + + case R_luimm16: + case R_huimm16: + { + unsigned int sp; + unsigned int reloc_count_incr; + unsigned int hi_lo; + + if (q->howto->type == R_luimm16) + hi_lo = FLAT_RELOC_PART_LO; + else + hi_lo = FLAT_RELOC_PART_HI; + + sym_addr += q->addend; + + flat_relocs = (uint32_t *) + (realloc (flat_relocs, (flat_reloc_count + 2) * sizeof (uint32_t))); + reloc_count_incr = 1; + if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr)))) + continue; + if (0xFFFF0000 & sym_addr) { + /* value is > 16 bits - use an extra field */ + /* see if we have already output that symbol */ + /* reloc may be addend from symbol and */ + /* we can only store 16 bit offsets */ + sp = 1; + if ((*(q->sym_ptr_ptr))->udata.i == 0 + || flat_relocs[(*(q->sym_ptr_ptr))->udata.i] != sym_addr + || ((*(q->sym_ptr_ptr))->udata.i & 0xFFFF0000)) + { + reloc_count_incr = 2; + flat_relocs[flat_reloc_count + 1] = sym_addr; + (*(q->sym_ptr_ptr))->udata.i = flat_reloc_count + 1; + sym_addr = 0; // indication to loader to read next + } else{ + sym_addr = (*(q->sym_ptr_ptr))->udata.i; + } + } else { + sp = 0; + } + + if (bfin_set_reloc (flat_relocs + flat_reloc_count, + sym_section->name, sym_name, + (*(q->sym_ptr_ptr)), + sp, hi_lo, + section_vma + q->address)) + bad_relocs++; + flat_reloc_count += reloc_count_incr; + break; + } + case R_byte4_data: + sym_addr += 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, FLAT_RELOC_PART_LO, + section_vma + q->address)) + bad_relocs++; + + flat_reloc_count++; + break; + +#endif //TARGET_bfin + #ifdef TARGET_sh case R_SH_DIR32: relocation_needed = 1; @@ -1109,23 +1513,67 @@ DIS29_RELOCATION: tmp.l = *(unsigned long *)r_mem; hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16); - if (((*p)->howto->type != R_ARM_PC24) && - ((*p)->howto->type != R_ARM_PLT32)) + 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 */ - hl += sym_addr; + if (!use_resolved) + hl += sym_addr; tmp.c[i0] = hl & 0xff; tmp.c[i1] = (hl >> 8) & 0xff; tmp.c[i2] = (hl >> 16) & 0xff; - if (((*p)->howto->type != R_ARM_PC24) && - ((*p)->howto->type != R_ARM_PLT32)) + 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) *(unsigned long *)r_mem = htonl(hl); else *(unsigned long *)r_mem = tmp.l; +#elif defined(TARGET_bfin) + if ((*p)->howto->type == R_pcrel24 + || (*p)->howto->type == R_pcrel24_jump_l + || (*p)->howto->type == R_pcrel24_jump_x + || (*p)->howto->type == R_pcrel24_call_x) + { + sym_addr += 2*-1*PCREL24_MAGIC_OFFSET; + *((unsigned short *)(sectionp + q->address) + 1 + PCREL24_MAGIC_OFFSET) + = (sym_addr >> 1) & 0xffff; + *((unsigned short *)(sectionp + q->address) + PCREL24_MAGIC_OFFSET) + = (0xff00 & *((unsigned short *) (sectionp + q->address) + PCREL24_MAGIC_OFFSET) + | ((sym_addr >> 17) & 0xff)); + } else if ((*p)->howto->type == R_byte4_data) { + *((uint32_t *)(sectionp + q->address)) = sym_addr; + } else if ((*p)->howto->type == R_pcrel12_jump + || (*p)->howto->type == R_pcrel12_jump_s) { + *((unsigned short *)(sectionp + q->address)) + = (0xf000 & *((unsigned short *)(sectionp + q->address)) + | ((sym_addr >> 1) & 0xfff)); + } else if ((*p)->howto->type == R_pcrel10) { + *((unsigned short *)(sectionp + q->address)) + = (~0x3ff & *((unsigned short *)(sectionp + q->address)) + | ((sym_addr >> 1) & 0x3ff)); + } else if ((*p)->howto->type == R_rimm16 + || (*p)->howto->type == R_huimm16 + || (*p)->howto->type == R_luimm16) { + /* for l and h we set the lower 16 bits which is only when it will be used */ + *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr; + } else if ((*p)->howto->type == R_pcrel5m2) { + *((unsigned short *)(sectionp + q->address)) + = (0xfff0 & *((unsigned short *)(sectionp + q->address)) + | ((sym_addr >> 1) & 0xf)); + } else if ((*p)->howto->type == R_pcrel11){ + *((unsigned short *)(sectionp + q->address)) + = (0xfc00 & *((unsigned short *)(sectionp + q->address)) + | ((sym_addr >> 1) & 0x3ff)); + } else if (0xE0 <= (*p)->howto->type && 0xF3 >= (*p)->howto->type) { + //arith relocs dont generate a real relocation + } else { + printf("Blackfin relocation fail for reloc type: 0x%x\n", (*p)->howto->type); + } #elif defined(TARGET_e1) #define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/ switch ((*p)->howto->type) { @@ -1170,6 +1618,28 @@ DIS29_RELOCATION: loaders knows about it. */ break; #endif /* TARGET_V850 */ + +#ifdef TARGET_nios2 + case 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; +#endif + default: /* The alignment of the build host might be stricter than that of the @@ -1183,6 +1653,19 @@ DIS29_RELOCATION: #endif /* !TARGET_arm */ } +#ifdef TARGET_bfin + else { + if ((*p)->howto->type == R_rimm16 + || (*p)->howto->type == R_huimm16 + || (*p)->howto->type == R_luimm16) + { + /* for l and h we set the lower 16 bits which is only when it will be used */ + *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr; + } else if ((*p)->howto->type == R_byte4_data) { + *((uint32_t *)(sectionp + q->address)) = sym_addr; + } + } +#endif if (verbose) printf(" RELOC[%d]: offset=0x%x symbol=%s%s " "section=%s size=%d " @@ -1195,8 +1678,9 @@ DIS29_RELOCATION: * Create relocation entry (PC relative doesn't need this). */ if (relocation_needed) { +#ifndef TARGET_bfin flat_relocs = realloc(flat_relocs, - (flat_reloc_count + 1) * sizeof(unsigned long)); + (flat_reloc_count + 1) * sizeof(uint32_t)); #ifndef TARGET_e1 flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address); @@ -1230,6 +1714,7 @@ DIS29_RELOCATION: } #endif flat_reloc_count++; +#endif relocation_needed = 0; pflags = 0; } @@ -1257,90 +1742,6 @@ printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n", -#if 0 -/* shared lib symbols stuff */ - -long -get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols) -{ - long i; - for (i=0; isection == sec) { - if (!strcmp(symbol_table[i]->name, name)) { - return symbol_table[i]->value; - } - } - } - return -1; -} - -int -output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols) -{ - long i; - FILE *ef; - char buf[80]; - char libname[80]; - long etext_addr; - long sym_addr; - - int foobar = 0; - int count = 0; - signed short *tab = malloc(32768); /* we don't know how many yet*/ - - asection *text_section = bfd_get_section_by_name (abfd, ".text"); - - if (!(ef = fopen(ename, "r"))) { - fprintf (stderr,"Can't open %s\n",ename); - exit(1); - } - - fgets(libname, 80, ef); - - if (number_of_symbols < 0) { - fprintf (stderr,"Corrupt symbol table!\n"); - exit(1); - } - - if ((etext_addr = get_symbol("etext", - text_section, - symbol_table, - number_of_symbols)) == -1) { - fprintf (stderr,"Can't find the symbol etext\n"); - exit(1); - } - - fgets(buf, 80, ef); - while (!feof(ef)) { - buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */ - - if ((sym_addr = get_symbol(buf, - text_section, - symbol_table, - number_of_symbols)) == -1) { - fprintf (stderr,"Can't find the symbol %s\n",buf); - foobar++; - } else { - tab[++count] = htons(sym_addr - etext_addr); - } - fgets(buf, 80, ef); - } - - fclose(ef); - - if (foobar) { - fprintf (stderr,"*** %d symbols not found\n",foobar); - exit(10); - } - - strcpy((char *)&tab[++count],libname); - tab[0] = htons(count * 2); - write(fd, tab, count * 2 + strlen(libname) + 2); - return 0; -} -#endif - - static char * program; static void usage(void) @@ -1372,7 +1773,7 @@ static void write_zeroes (unsigned long num, FILE *stream) if (num > 0) { /* It'd be nice if we could just use fseek, but that doesn't seem to work for stdio output files. */ - bzero(zeroes, 1024); + memset(zeroes, 0x00, 1024); while (num > sizeof(zeroes)) { fwrite(zeroes, sizeof(zeroes), 1, stream); num -= sizeof(zeroes); @@ -1396,7 +1797,6 @@ int main(int argc, char *argv[]) char cmd[1024]; FILE *gf = NULL; - asymbol **symbol_table; long number_of_symbols; @@ -1413,17 +1813,27 @@ int main(int argc, char *argv[]) void *text; void *data; - unsigned long *reloc; + uint32_t *reloc; struct flat_hdr hdr; + int gf_is_pipe = 0; program = argv[0]; progname = argv[0]; + xmalloc_set_program_name(program); if (argc < 2) usage(); + if (sizeof(hdr) != 64) { + fprintf(stderr, + "Potential flat header incompatibility detected\n" + "header size should be 64 but is %d\n", + sizeof(hdr)); + exit(64); + } + #ifndef TARGET_e1 stack = 4096; #else /* We need plenty of stack for both of them (Aggregate and Register) */ @@ -1457,7 +1867,10 @@ int main(int argc, char *argv[]) use_resolved = 1; break; case 's': - stack = atoi(optarg); + if (sscanf(optarg, "%i", &stack) != 1) { + fprintf(stderr, "%s invalid stack size %s\n", argv[0], optarg); + usage(); + } break; case 'R': rel_file = optarg; @@ -1530,6 +1943,8 @@ int main(int argc, char *argv[]) /* Group output sections into text, data, and bss, and calc their sizes. */ for (s = abs_bfd->sections; s != NULL; s = s->next) { unsigned long *vma, *len; + bfd_size_type sec_size; + bfd_vma sec_vma; if (s->flags & SEC_CODE) { vma = &text_vma; @@ -1543,14 +1958,17 @@ int main(int argc, char *argv[]) } else continue; - if (s->vma < *vma) { + sec_size = bfd_section_size(abs_bfd, s); + sec_vma = bfd_section_vma(abs_bfd, s); + + if (sec_vma < *vma) { if (*len > 0) - *len += s->vma - *vma; + *len += sec_vma - *vma; else - *len = s->_raw_size; - *vma = s->vma; - } else if (s->vma + s->_raw_size > *vma + *len) - *len = s->vma + s->_raw_size - *vma; + *len = sec_size; + *vma = sec_vma; + } else if (sec_vma + sec_size > *vma + *len) + *len = sec_vma + sec_size - *vma; } if (text_len == 0) { @@ -1558,7 +1976,7 @@ int main(int argc, char *argv[]) exit (2); } - text = malloc(text_len); + text = xmalloc(text_len); if (verbose) printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len); @@ -1568,7 +1986,7 @@ int main(int argc, char *argv[]) if (s->flags & SEC_CODE) if (!bfd_get_section_contents(abs_bfd, s, text + (s->vma - text_vma), 0, - s->_raw_size)) + bfd_section_size(abs_bfd, s))) { fprintf(stderr, "read error section %s\n", s->name); exit(2); @@ -1578,7 +1996,7 @@ int main(int argc, char *argv[]) fprintf (stderr, "%s: no .data section", abs_file); exit (2); } - data = malloc(data_len); + data = xmalloc(data_len); if (verbose) printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len); @@ -1599,7 +2017,7 @@ int main(int argc, char *argv[]) if (s->flags & SEC_DATA) if (!bfd_get_section_contents(abs_bfd, s, data + (s->vma - data_vma), 0, - s->_raw_size)) + bfd_section_size(abs_bfd, s))) { fprintf(stderr, "read error section %s\n", s->name); exit(2); @@ -1623,9 +2041,9 @@ int main(int argc, char *argv[]) data_len = bss_vma - data_vma; } - reloc = (unsigned long *) - output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len, - text, text_len, text_vma, data, data_len, data_vma, rel_bfd); + reloc = 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) printf("No relocations in code!\n"); @@ -1635,12 +2053,12 @@ int main(int argc, char *argv[]) /* Fill in the binflt_flat header */ memcpy(hdr.magic,"bFLT",4); hdr.rev = htonl(FLAT_VERSION); - hdr.entry = htonl(16 * 4 + bfd_get_start_address(abs_bfd)); - hdr.data_start = htonl(16 * 4 + text_offs + text_len); - hdr.data_end = htonl(16 * 4 + text_offs + text_len + data_len); - hdr.bss_end = htonl(16 * 4 + text_offs + text_len + data_len + bss_len); + hdr.entry = htonl(sizeof(hdr) + bfd_get_start_address(abs_bfd)); + hdr.data_start = htonl(sizeof(hdr) + text_offs + text_len); + hdr.data_end = htonl(sizeof(hdr) + text_offs + text_len +data_len); + hdr.bss_end = htonl(sizeof(hdr) + text_offs + text_len +data_len+bss_len); hdr.stack_size = htonl(stack); /* FIXME */ - hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len); + hdr.reloc_start = htonl(sizeof(hdr) + text_offs + text_len +data_len); hdr.reloc_count = htonl(reloc_len); hdr.flags = htonl(0 | (load_to_ram ? FLAT_FLAG_RAM : 0) @@ -1649,7 +2067,7 @@ int main(int argc, char *argv[]) | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0) ); hdr.build_date = htonl((unsigned long)time(NULL)); - bzero(hdr.filler, sizeof(hdr.filler)); + memset(hdr.filler, 0x00, sizeof(hdr.filler)); for (i=0; i> %s", ofile); #define START_COMPRESSOR do { \ - if (gf) fclose(gf); \ - if (!(gf = popen(cmd, "w"))) { \ + if (gf) \ + if (gf_is_pipe) \ + pclose(gf); \ + else \ + fclose(gf); \ + if (!(gf = popen(cmd, "w" BINARY_FILE_OPTS))) { \ fprintf(stderr, "Can't run cmd %s\n", cmd); \ exit(4); \ } \ + gf_is_pipe = 1; \ } while (0) - gf = fopen(ofile, "a"); + gf = fopen(ofile, "ab"); /* Add 'b' to support non-posix (ie windows) */ if (!gf) { - fprintf(stderr, "Can't opne file %s for writing\n", ofile); \ + fprintf(stderr, "Can't open file %s for writing\n", ofile); \ exit(4); } @@ -1714,7 +2137,21 @@ int main(int argc, char *argv[]) if (reloc) fwrite(reloc, reloc_len * 4, 1, gf); + if(gf_is_pipe) + pclose(gf); + else fclose(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 + */