X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=elf2flt.c;h=546305f6b95835a5eade341aca1883800c9ed5d6;hb=6a93642380b57bb272b96df6a350e50a4c984015;hp=0afe1242bbbef8fbfbdd4d3006dca7c87db1bb3f;hpb=56394e90f8bdd207f3c239d8fb9c64b28cffffc7;p=uclinux-h8%2Felf2flt.git diff --git a/elf2flt.c b/elf2flt.c index 0afe124..546305f 100644 --- a/elf2flt.c +++ b/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 * (c) 2004, Nios II support, Wentao Xu * (c) 2003, H8 support, ktrace * (c) 2003-2004, MicroBlaze support, John Williams @@ -52,6 +54,7 @@ /* from $(INSTALLDIR)/include */ #include /* Main header file for the BFD library */ +#include #if defined(TARGET_h8300) #include /* TARGET_* ELF support for the BFD library */ @@ -71,6 +74,7 @@ /* from uClinux-x.x.x/include/linux */ #include "flat.h" /* Binary flat header description */ +#include "compress.h" #ifdef TARGET_e1 #include @@ -140,7 +144,7 @@ int verbose = 0; /* extra output when running */ int pic_with_got = 0; /* do elf/got processing with PIC code */ int load_to_ram = 0; /* instruct loader to allocate everything into RAM */ int ktrace = 0; /* instruct loader output kernel trace on load */ -int compress = 0; /* 1 = compress everything, 2 = compress data only */ +int docompress = 0; /* 1 = compress everything, 2 = compress data only */ 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 */ @@ -233,7 +237,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); @@ -308,119 +312,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. */ @@ -536,7 +427,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++; @@ -603,7 +494,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) @@ -684,16 +576,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; @@ -707,7 +589,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 @@ -795,7 +677,7 @@ dump_symbols(symbols, number_of_symbols); + lo; } } else - goto bad_v850_reloc_err; + goto bad_resolved_reloc; break; case R_V850_LO16: @@ -809,16 +691,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; -#endif /* TARGET_V850 */ - + case R_ARM_REL32: + case R_ARM_THM_PC11: + case R_ARM_THM_PC22: + 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 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 @@ -827,6 +730,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) @@ -840,6 +746,13 @@ 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. */ @@ -1069,8 +982,6 @@ dump_symbols(symbols, number_of_symbols); #ifdef TARGET_nios2 #define htoniosl(x) (x) #define niostohl(x) (x) - switch ((*p)->howto->type) - { case R_NIOS2_BFD_RELOC_32: relocation_needed = 1; pflags = (FLAT_NIOS2_R_32 << 28); @@ -1223,7 +1134,6 @@ 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 @@ -1284,14 +1194,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){ @@ -1321,11 +1229,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; @@ -1362,10 +1267,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; @@ -1381,22 +1284,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 @@ -1628,17 +1515,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); @@ -1879,19 +1769,19 @@ static void usage(void) /* Write NUM zeroes to STREAM. */ -static void write_zeroes (unsigned long num, FILE *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 to work for stdio output files. */ - bzero(zeroes, 1024); + memset(zeroes, 0x00, 1024); while (num > sizeof(zeroes)) { - fwrite(zeroes, sizeof(zeroes), 1, stream); + fwrite_stream(zeroes, sizeof(zeroes), 1, stream); num -= sizeof(zeroes); } if (num > 0) - fwrite(zeroes, num, 1, stream); + fwrite_stream(zeroes, num, 1, stream); } } @@ -1906,8 +1796,7 @@ int main(int argc, char *argv[]) int opt; int i; int stack; - char cmd[1024]; - FILE *gf = NULL; + stream gf; asymbol **symbol_table; long number_of_symbols; @@ -1929,10 +1818,9 @@ int main(int argc, char *argv[]) struct flat_hdr hdr; - int gf_is_pipe = 0; - program = argv[0]; progname = argv[0]; + xmalloc_set_program_name(program); if (argc < 2) usage(); @@ -1963,10 +1851,10 @@ int main(int argc, char *argv[]) ktrace++; break; case 'z': - compress = 1; + docompress = 1; break; case 'd': - compress = 2; + docompress = 2; break; case 'p': pfile = optarg; @@ -1978,7 +1866,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; @@ -2084,7 +1975,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); @@ -2104,7 +1995,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); @@ -2172,10 +2063,10 @@ int main(int argc, char *argv[]) | (load_to_ram ? FLAT_FLAG_RAM : 0) | (ktrace ? FLAT_FLAG_KTRACE : 0) | (pic_with_got ? FLAT_FLAG_GOTPIC : 0) - | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0) + | (docompress ? (docompress == 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) \ - 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, "ab"); /* Add 'b' to support non-posix (ie windows) */ - if (!gf) { - fprintf(stderr, "Can't open file %s for writing\n", ofile); \ - exit(4); + if (fopen_stream_u(&gf, ofile, "a" BINARY_FILE_OPTS)) { + fprintf(stderr, "Can't open file %s for writing\n", ofile); + exit(4); } - if (compress == 1) - START_COMPRESSOR; + 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); + printf("ZERO before text len=0x%x\n", text_offs); + write_zeroes(text_offs, &gf); /* Write the text segment. */ - fwrite(text, text_len, 1, gf); + fwrite_stream(text, text_len, 1, &gf); - if (compress == 2) - START_COMPRESSOR; + if (docompress == 2) + reopen_stream_compressed(&gf); /* Write the data segment. */ - fwrite(data, data_len, 1, gf); + fwrite_stream(data, data_len, 1, &gf); if (reloc) - fwrite(reloc, reloc_len * 4, 1, gf); + fwrite_stream(reloc, reloc_len * 4, 1, &gf); - if(gf_is_pipe) - pclose(gf); - else - fclose(gf); + fclose_stream(&gf); exit(0); }