diff options
Diffstat (limited to 'toolchain/elf2flt/elf2flt/elf2flt.c')
-rw-r--r-- | toolchain/elf2flt/elf2flt/elf2flt.c | 253 |
1 files changed, 79 insertions, 174 deletions
diff --git a/toolchain/elf2flt/elf2flt/elf2flt.c b/toolchain/elf2flt/elf2flt/elf2flt.c index a073ec187..b0b1da595 100644 --- a/toolchain/elf2flt/elf2flt/elf2flt.c +++ b/toolchain/elf2flt/elf2flt/elf2flt.c @@ -6,6 +6,8 @@ * 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> @@ -44,8 +46,10 @@ #include <time.h> #ifndef WIN32 #include <netinet/in.h> /* Consts and structs defined by the internet system */ +#define BINARY_FILE_OPTS #else #include <winsock2.h> +#define BINARY_FILE_OPTS "b" #endif /* from $(INSTALLDIR)/include */ @@ -306,119 +310,6 @@ add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len) } #ifdef TARGET_bfin -/* stack to handle "arithmetic" relocations */ -#define RELOC_STACK_SIZE 100 -static bfd_vma reloc_stack[RELOC_STACK_SIZE]; -static unsigned int reloc_stack_tos = 0; -static char sym_section_name[80]; -static asection *stack_sym_section = 0; - -static void -reloc_stack_set_section(asection *section, const char *sym_section_name_in) -{ - /* TODO : we can add checks to make sure we do not - add different section names to the same arithmetic - expression. */ - strcpy(sym_section_name, sym_section_name_in); - stack_sym_section = section; -} - -static const char * -reloc_stack_get_section_name() -{ - return sym_section_name; -} -static asection *reloc_stack_get_section() -{ - return stack_sym_section; -} - -#define is_reloc_stack_empty() ((reloc_stack_tos > 0)?0:1) - -static void -reloc_stack_push(bfd_vma value) -{ - reloc_stack[reloc_stack_tos++] = value; -} - -static bfd_vma -reloc_stack_pop() -{ - return reloc_stack[--reloc_stack_tos]; -} - -static bfd_vma -reloc_stack_operate(unsigned int oper) -{ - bfd_vma value; - switch(oper){ - case 0xE2 : - value = reloc_stack[reloc_stack_tos - 2] + reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE3 : - value = reloc_stack[reloc_stack_tos - 2] - reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE4 : - value = reloc_stack[reloc_stack_tos - 2] * reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE5 : - value = reloc_stack[reloc_stack_tos - 2] / reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE6 : - value = reloc_stack[reloc_stack_tos - 2] % reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE7 : - value = reloc_stack[reloc_stack_tos - 2] << reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE8 : - value = reloc_stack[reloc_stack_tos - 2] >> reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xE9 : - value = reloc_stack[reloc_stack_tos - 2] & reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xEA : - value = reloc_stack[reloc_stack_tos - 2] | reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xEB : - value = reloc_stack[reloc_stack_tos - 2] ^ reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xEC : - value = reloc_stack[reloc_stack_tos - 2] && reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xED : - value = reloc_stack[reloc_stack_tos - 2] || reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 2; - break; - case 0xEF : - value = -reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos --; - break; - case 0xF0 : - value = ~reloc_stack[reloc_stack_tos - 1]; - reloc_stack_tos -= 1; - break; - default : - fprintf(stderr, "bfin relocation : Internal bug\n"); - return 0; - } - - // now push the new value back on stack - reloc_stack_push(value); - - return value; -} - /* FUNCTION : weak_und_symbol ABSTRACT : return true if symbol is weak and undefined. */ @@ -534,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++; @@ -682,16 +573,6 @@ dump_symbols(symbols, number_of_symbols); #endif /* USE_V850_RELOCS */ q = *p; -#ifdef TARGET_bfin - if ((q->sym_ptr_ptr && *q->sym_ptr_ptr) && - (!is_reloc_stack_empty() && strstr((*(q->sym_ptr_ptr))->name, "operator"))){ - /* must be an arith reloc ... get the value from the stack */ - sym_name = (*(q->sym_ptr_ptr))->name; - sym_section = reloc_stack_get_section(); - section_name = reloc_stack_get_section_name(); - } - else -#endif if (q->sym_ptr_ptr && *q->sym_ptr_ptr) { sym_name = (*(q->sym_ptr_ptr))->name; sym_section = (*(q->sym_ptr_ptr))->section; @@ -705,7 +586,7 @@ dump_symbols(symbols, number_of_symbols); /* 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 @@ -793,7 +674,7 @@ dump_symbols(symbols, number_of_symbols); + lo; } } else - goto bad_v850_reloc_err; + goto bad_resolved_reloc; break; case R_V850_LO16: @@ -807,16 +688,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 @@ -825,6 +727,9 @@ dump_symbols(symbols, number_of_symbols); give an error by default, and require `safe' relocations to be enumberated explicitly?). */ + goto good_32bit_resolve_reloc; +#endif + good_32bit_resolved_reloc: if (bfd_big_endian (abs_bfd)) sym_addr = (r_mem[0] << 24) @@ -838,12 +743,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) && !defined(TARGET_bfin) +#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); @@ -861,6 +773,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; @@ -1278,14 +1191,12 @@ NIOS2_RELOC_ERR: 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: - if (is_reloc_stack_empty ()) - { - sym_addr += q->addend; - } else { - sym_addr = reloc_stack_pop (); - } + sym_addr += q->addend; if(weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr)))) continue; if(0xFFFF0000 & sym_addr){ @@ -1315,11 +1226,8 @@ NIOS2_RELOC_ERR: else hi_lo = FLAT_RELOC_PART_HI; - if (is_reloc_stack_empty ()) - sym_addr += q->addend; - else - sym_addr = reloc_stack_pop (); - + sym_addr += q->addend; + flat_relocs = (uint32_t *) (realloc (flat_relocs, (flat_reloc_count + 2) * sizeof (uint32_t))); reloc_count_incr = 1; @@ -1356,10 +1264,8 @@ NIOS2_RELOC_ERR: break; } case R_byte4_data: - if (is_reloc_stack_empty ()) - sym_addr += q->addend; - else - sym_addr = reloc_stack_pop (); + sym_addr += q->addend; + if (weak_und_symbol (sym_section->name, *q->sym_ptr_ptr)) continue; @@ -1375,22 +1281,6 @@ NIOS2_RELOC_ERR: flat_reloc_count++; break; - case 0xE0: - /* push */ - sym_addr += q->addend; - reloc_stack_push(sym_addr); - reloc_stack_set_section(sym_section, section_name); - break; - - case 0xE1: - /* const */ - reloc_stack_push(q->addend); - break; - - case 0xE2 ... 0xF2: - reloc_stack_operate((*p)->howto->type); - break; - #endif //TARGET_bfin #ifdef TARGET_sh @@ -1622,17 +1512,20 @@ 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); @@ -1734,6 +1627,18 @@ DIS29_RELOCATION: 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 @@ -1867,7 +1772,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); @@ -2157,7 +2062,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<reloc_len; i++) reloc[i] = htonl(reloc[i]); @@ -2194,7 +2099,7 @@ int main(int argc, char *argv[]) pclose(gf); \ else \ fclose(gf); \ - if (!(gf = popen(cmd, "wb"))) { \ + if (!(gf = popen(cmd, "w" BINARY_FILE_OPTS))) { \ fprintf(stderr, "Can't run cmd %s\n", cmd); \ exit(4); \ } \ |