X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=elf2flt.c;h=2fea9b547e5a7015908c8a3e8074e0a211da4beb;hb=21c6a41885ad544763ccd19883c1353f3b0b7a47;hp=c42a93b798c437927a3f0b49329f236f6a43ff5e;hpb=ca468dce3a10dfa5a7b00acf07eecf5d577da683;p=uclinux-h8%2Felf2flt.git diff --git a/elf2flt.c b/elf2flt.c index c42a93b..2fea9b5 100644 --- a/elf2flt.c +++ b/elf2flt.c @@ -6,6 +6,9 @@ * 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 @@ -41,27 +44,38 @@ #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 */ -#else -#include -#endif /* from $(INSTALLDIR)/include */ #include /* Main header file for the BFD library */ +#include + +#include "stubs.h" +const char *elf2flt_progname; #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 */ #else #include /* 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 +#endif + /* from uClinux-x.x.x/include/linux */ #include "flat.h" /* Binary flat header description */ +#include "compress.h" #ifdef TARGET_e1 #include @@ -87,11 +101,17 @@ #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 -#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. @@ -118,7 +138,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 */ @@ -126,80 +146,14 @@ int use_resolved = 0; /* If true, get the value of symbol references from */ /* versions of GNU ld will give you a fully resolved */ /* output file with relocation entries). */ -const char *progname, *filename; -int lineno; - -int nerrors = 0; -int nwarnings = 0; - -static char where[200]; - -enum { - /* Use exactly one of these: */ - E_NOFILE = 0, /* "progname: " */ - E_FILE = 1, /* "filename: " */ - E_FILELINE = 2, /* "filename:lineno: " */ - E_FILEWHERE = 3, /* "filename:%s: " -- set %s with ewhere() */ - - /* Add in any of these with |': */ - E_WARNING = 0x10, - E_PERROR = 0x20 -}; - -void ewhere (const char *format, ...); -void einfo (int type, const char *format, ...); - - -void -ewhere (const char *format, ...) { - va_list args; - va_start (args, format); - vsprintf (where, format, args); - va_end (args); -} - - -void -einfo (int type, const char *format, ...) { - va_list args; - - switch (type & 0x0f) { - case E_NOFILE: - fprintf (stderr, "%s: ", progname); - break; - case E_FILE: - fprintf (stderr, "%s: ", filename); - break; - case E_FILELINE: - ewhere ("%d", lineno); - /* fall-through */ - case E_FILEWHERE: - fprintf (stderr, "%s:%s: ", filename, where); - break; - } - - if (type & E_WARNING) { - fprintf (stderr, "warning: "); - nwarnings++; - } else { - nerrors++; - } - - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); - - if (type & E_PERROR) - perror (""); - else - fprintf (stderr, "\n"); -} - +/* Set if the text section contains any relocations. If it does, we must + set the load_to_ram flag. */ +int text_has_relocs = 0; asymbol** get_symbols (bfd *abfd, long *num) { - long storage_needed; + int32_t storage_needed; asymbol **symbol_table; long number_of_symbols; @@ -211,7 +165,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); @@ -246,7 +200,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; } } } @@ -255,11 +209,26 @@ get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number +#ifdef TARGET_nios2 long -add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len) +get_gp_value(asymbol **symbol_table, long number_of_symbols) { - long i, comsize; - long offset; + long i; + for (i=0; iname, "_gp")) + return symbol_table[i]->value; + } + return -1; +} +#endif + + + +int32_t +add_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; iflags & 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, 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 int +compare_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; +} +#endif -unsigned long * +uint32_t * output_relocs ( bfd *abs_bfd, asymbol **symbols, int number_of_symbols, - unsigned long *n_relocs, - unsigned char *text, int text_len, unsigned long text_vma, - unsigned char *data, int data_len, unsigned long data_vma, + 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) { - unsigned long *flat_relocs; + 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]; - long sym_addr, sym_vma, section_vma; + uint32_t sym_addr, sym_vma, section_vma; int relsize, relcount; int flat_reloc_count; int sym_reloc_size, rc; @@ -299,6 +335,9 @@ output_relocs ( int bad_relocs = 0; asymbol **symb; long nsymb; +#ifdef TARGET_bfin + unsigned long persistent_data = 0; +#endif #if 0 printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d" @@ -322,20 +361,18 @@ 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) { - unsigned long *lp = (unsigned long *)data; + 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(unsigned long), got_size); + got_size/sizeof(uint32_t), got_size); #ifdef TARGET_m68k - if (got_size > GOT_LIMIT) { - fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n", - got_size, GOT_LIMIT); - exit(1); - } + if (got_size > GOT_LIMIT) + fatal("GOT too large: %d bytes (limit = %d bytes)", + got_size, GOT_LIMIT); #endif } @@ -359,7 +396,7 @@ dump_symbols(symbols, number_of_symbols); * Only relocate things in the data sections if we are PIC/GOT. * otherwise do text as well */ - if (!pic_with_got && (a->flags & SEC_CODE)) + 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); @@ -389,7 +426,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) @@ -397,6 +435,10 @@ dump_symbols(symbols, number_of_symbols); __FILE__, __LINE__, r->name); continue; } else { +#ifdef TARGET_bfin + compare_relocs_bfd = abs_bfd; + qsort (relpp, relcount, sizeof *relpp, compare_relocs); +#endif for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) { unsigned char *r_mem; int relocation_needed = 0; @@ -410,10 +452,11 @@ dump_symbols(symbols, number_of_symbols); { 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 (we do this early, before doing any other @@ -479,12 +522,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; @@ -493,7 +538,7 @@ dump_symbols(symbols, number_of_symbols); * Fixup offset in the actual section. */ addstr[0] = 0; -#ifndef TARGET_e1 +#if !defined TARGET_e1 && !defined TARGET_bfin if ((sym_addr = get_symbol_offset((char *) sym_name, sym_section, symbols, number_of_symbols)) == -1) { sym_addr = 0; @@ -569,7 +614,7 @@ dump_symbols(symbols, number_of_symbols); + lo; } } else - goto bad_v850_reloc_err; + goto bad_resolved_reloc; break; case R_V850_LO16: @@ -583,16 +628,96 @@ 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: + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_GOTPC: + case R_ARM_GOT32: + 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; +#elif defined TARGET_bfin + case 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; +#else default: /* The default is to assume that the relocation is relative and has @@ -601,6 +726,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) @@ -614,12 +742,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); @@ -637,6 +772,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; @@ -655,7 +791,7 @@ dump_symbols(symbols, number_of_symbols); sym_vma, (*(q->sym_ptr_ptr))->value, q->address, sym_addr, (*p)->howto->rightshift, - *(unsigned long *)r_mem); + *(uint32_t *)r_mem); sym_vma = bfd_section_vma(abs_bfd, sym_section); sym_addr += sym_vma + q->addend; break; @@ -672,7 +808,7 @@ dump_symbols(symbols, number_of_symbols); sym_vma, (*(q->sym_ptr_ptr))->value, q->address, sym_addr, (*p)->howto->rightshift, - *(unsigned long *)r_mem); + *(uint32_t *)r_mem); case R_ARM_PC24: sym_vma = 0; sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift; @@ -763,15 +899,11 @@ dump_symbols(symbols, number_of_symbols); the relocation symbol. */ { unsigned char *p = r_mem; - unsigned long offset; pflags=0x80000000; /* work out the relocation */ sym_vma = bfd_section_vma(abs_bfd, sym_section); - /* grab any offset from the text */ - offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]); - /* Update the address */ - sym_addr += offset + sym_vma + q->addend; + sym_addr += sym_vma + q->addend; /* Write relocated pointer back */ p[2] = (sym_addr >> 24) & 0xff; p[3] = (sym_addr >> 16) & 0xff; @@ -780,7 +912,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; @@ -803,42 +935,184 @@ dump_symbols(symbols, number_of_symbols); case R_MICROBLAZE_32: { unsigned char *p = r_mem; - unsigned long offset; - /* grab any offset from the text */ - offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]); sym_vma = bfd_section_vma(abs_bfd, sym_section); - /* This is a horrible kludge. For some - reason, *sometimes* the offset is in - both addend and the code. Detect - it, and cancel the effect. Otherwise - the offset gets added twice - ouch. - There should be a better test - for this condition, based on the - BFD data structures */ - if(offset==q->addend) - offset=0; - - sym_addr += offset + sym_vma + q->addend; + sym_addr += sym_vma + q->addend; relocation_needed = 1; break; } case R_MICROBLAZE_64_PCREL: sym_vma = 0; - //sym_addr = (*(q->sym_ptr_ptr))->value; 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; + * ((unsigned short *) (r_mem+2)) = (sym_addr) & 0xFFFF; /* then 16 LSB */ - * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF; + * ((unsigned short *) (r_mem+6)) = (sym_addr >> 16) & 0xFFFF; /* We've done all the work, so continue to 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; + 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: @@ -855,7 +1129,7 @@ dump_symbols(symbols, number_of_symbols); sym_addr = (((*(q->sym_ptr_ptr))->value- q->address) >> 2) & 0x3fffffff; sym_addr |= ( - ntohl(*(unsigned long *)r_mem) + ntohl(*(uint32_t *)r_mem) & 0xc0000000 ); break; @@ -865,7 +1139,7 @@ dump_symbols(symbols, number_of_symbols); sym_vma = bfd_section_vma(abs_bfd, sym_section); sym_addr += sym_vma + q->addend; sym_addr |= ( - htonl(*(unsigned long *)r_mem) + htonl(*(uint32_t *)r_mem) & 0xffc00000 ); break; @@ -876,12 +1150,13 @@ dump_symbols(symbols, number_of_symbols); sym_addr += sym_vma + q->addend; sym_addr &= 0x000003ff; sym_addr |= ( - htonl(*(unsigned long *)r_mem) + htonl(*(uint32_t *)r_mem) & 0xfffffc00 ); break; #endif /* TARGET_sparc */ + #ifdef TARGET_sh case R_SH_DIR32: relocation_needed = 1; @@ -1089,9 +1364,9 @@ DIS29_RELOCATION: #if defined(TARGET_arm) union { unsigned char c[4]; - unsigned long l; + uint32_t l; } tmp; - long hl; + int32_t hl; int i0, i1, i2, i3; /* @@ -1109,25 +1384,27 @@ DIS29_RELOCATION: i3 = 0; } - tmp.l = *(unsigned long *)r_mem; + tmp.l = *(uint32_t *)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); + *(uint32_t *)r_mem = htonl(hl); else - *(unsigned long *)r_mem = tmp.l; - + *(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) { @@ -1154,7 +1431,17 @@ DIS29_RELOCATION: exit(0); break; } -#else /* ! TARGET_arm && ! TARGET_e1 */ +#elif defined TARGET_bfin + if ((*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_v850 @@ -1172,6 +1459,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 @@ -1197,8 +1506,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); @@ -1232,6 +1542,7 @@ DIS29_RELOCATION: } #endif flat_reloc_count++; +#endif //TARGET_bfin relocation_needed = 0; pflags = 0; } @@ -1259,94 +1570,8 @@ 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, "rb"))) { - 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) -{ +{ fprintf(stderr, "Usage: %s [vrzd] [-p ] [-s stack-size] " "[-o ] \n\n" " -v : verbose operation\n" @@ -1361,26 +1586,26 @@ static void usage(void) " -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", - program); + elf2flt_progname); fprintf(stderr, "Compiled for " ARCH " architecture\n\n"); exit(2); } /* 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); } } @@ -1395,38 +1620,40 @@ 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; - unsigned long data_len = 0; - unsigned long bss_len = 0; - unsigned long text_len = 0; - unsigned long reloc_len; + uint32_t data_len = 0; + uint32_t bss_len = 0; + uint32_t text_len = 0; + uint32_t reloc_len; - unsigned long data_vma = ~0; - unsigned long bss_vma = ~0; - unsigned long text_vma = ~0; + uint32_t data_vma = ~0; + uint32_t bss_vma = ~0; + uint32_t text_vma = ~0; - unsigned long text_offs; + uint32_t text_offs; void *text; void *data; - unsigned long *reloc; - - struct flat_hdr hdr; + uint32_t *reloc; - int gf_is_pipe = 0; + struct flat_hdr hdr; - program = argv[0]; - progname = argv[0]; + elf2flt_progname = argv[0]; + xmalloc_set_program_name(elf2flt_progname); if (argc < 2) usage(); - + + if (sizeof(hdr) != 64) + fatal( + "Potential flat header incompatibility detected\n" + "header size should be 64 but is %d", + sizeof(hdr)); + #ifndef TARGET_e1 stack = 4096; #else /* We need plenty of stack for both of them (Aggregate and Register) */ @@ -1445,10 +1672,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; @@ -1460,7 +1687,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; @@ -1479,7 +1709,7 @@ int main(int argc, char *argv[]) if (!load_to_ram && !pfile) load_to_ram = 1; - filename = fname = argv[argc-1]; + fname = argv[argc-1]; if (pfile) { pic_with_got = 1; @@ -1490,49 +1720,36 @@ int main(int argc, char *argv[]) if (! rel_file) rel_file = fname; - if (!(rel_bfd = bfd_openr(rel_file, 0))) { - fprintf(stderr, "Can't open %s\n", rel_file); - exit(1); - } + 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) { - fprintf(stderr, "File is not an object file\n"); - exit(2); - } + 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))) { - fprintf(stderr, "Can't open %s\n", abs_file); - exit(1); - } + 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) { - fprintf(stderr, "File is not an object file\n"); - exit(2); - } + 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)) { - fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file); - exit (2); - } + 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)) { + if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) /* `Absolute' file is not absolute, so neither are address contained therein. */ - fprintf (stderr, - "%s: `-a' option specified with non-fully-resolved input file\n", + fatal("%s: `-a' option specified with non-fully-resolved input file", bfd_get_filename (abs_bfd)); - exit (2); - } 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) { - unsigned long *vma, *len; + uint32_t *vma, *len; bfd_size_type sec_size; bfd_vma sec_vma; @@ -1561,12 +1778,10 @@ int main(int argc, char *argv[]) *len = sec_vma + sec_size - *vma; } - if (text_len == 0) { - fprintf (stderr, "%s: no .text section", abs_file); - exit (2); - } + if (text_len == 0) + fatal("%s: no .text section", abs_file); - text = malloc(text_len); + text = xmalloc(text_len); if (verbose) printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len); @@ -1578,15 +1793,12 @@ int main(int argc, char *argv[]) text + (s->vma - text_vma), 0, bfd_section_size(abs_bfd, s))) { - fprintf(stderr, "read error section %s\n", s->name); - exit(2); + fatal("read error section %s", s->name); } - if (data_len == 0) { - fprintf (stderr, "%s: no .data section", abs_file); - exit (2); - } - data = malloc(data_len); + 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); @@ -1609,10 +1821,12 @@ int main(int argc, char *argv[]) data + (s->vma - data_vma), 0, bfd_section_size(abs_bfd, s))) { - fprintf(stderr, "read error section %s\n", s->name); - exit(2); + 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); @@ -1631,11 +1845,11 @@ int main(int argc, char *argv[]) data_len = bss_vma - data_vma; } - reloc = (unsigned long *) + 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) + if (reloc == NULL && verbose) printf("No relocations in code!\n"); text_offs = real_address_bits(text_vma); @@ -1643,21 +1857,21 @@ 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) + | (load_to_ram || text_has_relocs ? 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)); + hdr.build_date = htonl((uint32_t)time(NULL)); + 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, "wb"))) { \ - 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)) + fatal_perror("Can't open file %s for writing", ofile); - 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); } + + +/* + * 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 + */