X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=elf2flt.c;h=5e9c6984c1bed42001d1b8fe53334354e54a78d3;hb=368260c0d5a31b414577a41a0a3e01f4e149ff0a;hp=3f7cede483b0c38199692610145d9d7d6a67c6df;hpb=88adcfcfc7a9221790e96bf1c0f5f89bf69c892e;p=uclinux-h8%2Felf2flt.git diff --git a/elf2flt.c b/elf2flt.c index 3f7cede..5e9c698 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 @@ -41,20 +45,41 @@ #include /* Flag value for file handling functions */ #include -#include /* Consts and structs defined by the internet system */ - /* 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 */ #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 +#endif #ifdef TARGET_v850e #define TARGET_v850 @@ -74,11 +99,19 @@ #define ARCH "h8300" #elif defined(TARGET_microblaze) #define ARCH "microblaze" +#elif defined(TARGET_e1) +#define ARCH "e1-coff" +#elif defined(TARGET_bfin) +#define ARCH "bfin" +#elif defined(TARGET_nios) +#define ARCH "nios" +#elif defined(TARGET_nios2) +#define ARCH "nios2" #else #error "Don't know how to support your CPU architecture??" #endif -#ifdef TARGET_m68k +#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. @@ -105,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 */ @@ -113,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; @@ -198,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); @@ -233,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; } } } @@ -242,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; -unsigned long * +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 + +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; @@ -286,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" @@ -309,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 } @@ -376,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) @@ -384,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; @@ -397,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 @@ -466,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; @@ -480,11 +538,14 @@ dump_symbols(symbols, number_of_symbols); * Fixup offset in the actual section. */ addstr[0] = 0; +#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; } - +#else + sym_addr = (*(q->sym_ptr_ptr))->value; +#endif if (use_resolved) { /* Use the address of the symbol already in the program text. How this is handled may @@ -553,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: @@ -567,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 @@ -585,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) @@ -598,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); -#ifndef TARGET_h8300 +#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); @@ -621,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; @@ -639,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; @@ -656,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; @@ -704,7 +856,8 @@ 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; @@ -746,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; @@ -763,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; @@ -784,28 +933,186 @@ dump_symbols(symbols, number_of_symbols); continue; } case R_MICROBLAZE_32: - relocation_needed = 1; - //sym_addr = (*(q->sym_ptr_ptr))->value; + { + unsigned char *p = r_mem; + sym_vma = bfd_section_vma(abs_bfd, sym_section); sym_addr += sym_vma + q->addend; + relocation_needed = 1; break; - + } case R_MICROBLAZE_64_PCREL: sym_vma = 0; - //sym_addr = (*(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: @@ -822,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; @@ -832,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; @@ -843,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; @@ -862,6 +1170,180 @@ dump_symbols(symbols, number_of_symbols); break; #endif /* TARGET_sh */ +#ifdef TARGET_e1 +#define htoe1l(x) htonl(x) + +#if 0 +#define DEBUG_E1 +#endif + +#ifdef DEBUG_E1 +#define DBG_E1 printf +#else +#define DBG_E1(x, ... ) +#endif + +#define _32BITS_RELOC 0x00000000 +#define _30BITS_RELOC 0x80000000 +#define _28BITS_RELOC 0x40000000 + { + char *p; + unsigned long sec_vma, exist_val, S; + case R_E1_CONST31: + relocation_needed = 1; + DBG_E1("Handling Reloc \n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n", + sec_vma, sym_addr, q->address); + sym_addr = sec_vma + sym_addr; + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val); + sym_addr += exist_val; + pflags = _30BITS_RELOC; + break; + case R_E1_CONST31_PCREL: + relocation_needed = 0; + DBG_E1("Handling Reloc \n"); + DBG_E1("DONT RELOCATE AT LOADING\n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n", + sec_vma, sym_addr, q->address); + sym_addr = sec_vma + sym_addr; + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr ); + + DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address, + section_vma ); + q->address = q->address + section_vma; + DBG_E1("q->address += section_vma : 0x%x\n", q->address ); + + if( (sym_addr = (sym_addr - q->address - 6)) < 0 ) + DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n"); + DBG_E1( "sym_addr := sym_addr - q->address - " + "sizeof(CONST31_PCREL): [0x%x]\n", + sym_addr ); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val); + sym_addr |= exist_val; + DBG_E1("sym_addr |= exist_val) : [0x%x]\n", sym_addr ); + break; + case R_E1_DIS29W_PCREL: + relocation_needed = 0; + DBG_E1("Handling Reloc \n"); + DBG_E1("DONT RELOCATE AT LOADING\n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n", + sec_vma, sym_addr, q->address); + sym_addr = sec_vma + sym_addr; + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr ); + + DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address, + section_vma ); + q->address = q->address + section_vma; + DBG_E1("q->address += section_vma : 0x%x\n", q->address ); + + if( (sym_addr = (sym_addr - q->address - 6)) < 0 ) + DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n"); + DBG_E1( "sym_addr := sym_addr - q->address - " + "sizeof(CONST31_PCREL): [0x%x]\n", + sym_addr ); + DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address ); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Original:exist_val : [0x%08x]\n",exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val); + sym_addr += exist_val; + break; + case R_E1_DIS29W: + DBG_E1("Handling Reloc \n"); + goto DIS29_RELOCATION; + case R_E1_DIS29H: + DBG_E1("Handling Reloc \n"); + goto DIS29_RELOCATION; + case R_E1_DIS29B: + DBG_E1("Handling Reloc \n"); +DIS29_RELOCATION: + relocation_needed = 1; + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n", + sec_vma, sym_addr); + sym_addr = sec_vma + sym_addr; + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%08x]\n", sym_addr); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val); + sym_addr += exist_val; + DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr); + pflags = _28BITS_RELOC; + break; + case R_E1_IMM32_PCREL: + relocation_needed = 0; + DBG_E1("Handling Reloc \n"); + DBG_E1("DONT RELOCATE AT LOADING\n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n", + sec_vma, sym_addr); + sym_addr = sec_vma + sym_addr; + + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr ); + DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address, + section_vma ); + q->address = q->address + section_vma; + DBG_E1("q->address += section_vma : 0x%x\n", q->address ); + + if( (sym_addr = (sym_addr - q->address - 6 )) < 0 ) + DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n"); + DBG_E1( "sym_addr := sym_addr - q->address - " + "sizeof(CONST31_PCREL): [0x%x]\n", + sym_addr ); + DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address ); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Original:exist_val : [0x%08x]\n",exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val); + sym_addr += exist_val; + break; + case R_E1_IMM32: + relocation_needed = 1; + DBG_E1("Handling Reloc \n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n", + sec_vma, sym_addr); + sym_addr = sec_vma + sym_addr; + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr ); + DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address ); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2); + DBG_E1("Original:exist_val : [0x%08x]\n",exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val); + sym_addr += exist_val; + pflags = _32BITS_RELOC; + break; + case R_E1_WORD: + relocation_needed = 1; + DBG_E1("Handling Reloc \n"); + sec_vma = bfd_section_vma(abs_bfd, sym_section); + DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n", + sec_vma, sym_addr); + sym_addr = sec_vma + sym_addr; + DBG_E1("sym_addr = sec_vma + sym_addr : [0x%x]\n", sym_addr ); + exist_val = *(unsigned long*)((unsigned long)sectionp + q->address ); + DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val); + exist_val = htoe1l(exist_val); + DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val); + sym_addr += exist_val; + DBG_E1("sym_addr += exist_val : [0x%08x]\n", sym_addr); + pflags = _32BITS_RELOC; + break; + } +#undef _32BITS_RELOC +#undef _30BITS_RELOC +#undef _28BITS_RELOC +#endif default: /* missing support for other types of relocs */ printf("ERROR: bad reloc type %d\n", (*p)->howto->type); @@ -882,9 +1364,9 @@ dump_symbols(symbols, number_of_symbols); #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; /* @@ -902,26 +1384,64 @@ dump_symbols(symbols, number_of_symbols); 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; - -#else /* ! TARGET_arm */ + *(uint32_t *)r_mem = tmp.l; +#elif defined(TARGET_e1) +#define OPCODE_SIZE 2 /* Add 2 bytes, counting the opcode size*/ + switch ((*p)->howto->type) { + case R_E1_CONST31: + case R_E1_CONST31_PCREL: + case R_E1_DIS29W_PCREL: + case R_E1_DIS29W: + case R_E1_DIS29H: + case R_E1_DIS29B: + case R_E1_IMM32_PCREL: + case R_E1_IMM32: + DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n", + (sectionp + q->address + 2), sym_addr ); + *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) = + htonl(sym_addr); + break; + case R_E1_WORD: + DBG_E1("In addr : [0x%x] <- write [0x%x]\n", + (sectionp + q->address), sym_addr ); + *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr); + break; + default: + printf("ERROR:Unhandled Relocation. Exiting...\n"); + exit(0); + break; + } +#elif defined TARGET_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 @@ -939,6 +1459,28 @@ dump_symbols(symbols, number_of_symbols); 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 @@ -964,15 +1506,43 @@ dump_symbols(symbols, number_of_symbols); * 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); if (verbose) printf("reloc[%d] = 0x%x\n", flat_reloc_count, section_vma + q->address); +#else + switch ((*p)->howto->type) { + case R_E1_CONST31: + case R_E1_CONST31_PCREL: + case R_E1_DIS29W_PCREL: + case R_E1_DIS29W: + case R_E1_DIS29H: + case R_E1_DIS29B: + case R_E1_IMM32_PCREL: + case R_E1_IMM32: + flat_relocs[flat_reloc_count] = pflags | + (section_vma + q->address + OPCODE_SIZE); + if (verbose) + printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count, + flat_relocs[flat_reloc_count] ); + break; + case R_E1_WORD: + flat_relocs[flat_reloc_count] = pflags | + (section_vma + q->address); + if (verbose) + printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count, + flat_relocs[flat_reloc_count] ); + break; + } +#endif flat_reloc_count++; +#endif //TARGET_bfin relocation_needed = 0; pflags = 0; } @@ -1000,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, "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) -{ +{ fprintf(stderr, "Usage: %s [vrzd] [-p ] [-s stack-size] " "[-o ] \n\n" " -v : verbose operation\n" @@ -1102,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); } } @@ -1136,38 +1620,45 @@ 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; + 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) */ + stack = 0x2020; +#endif while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) { switch (opt) { @@ -1181,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; @@ -1196,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; @@ -1215,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; @@ -1226,49 +1720,38 @@ 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; if (s->flags & SEC_CODE) { vma = &text_vma; @@ -1282,22 +1765,23 @@ 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) { - 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); @@ -1305,19 +1789,16 @@ int main(int argc, char *argv[]) /* Read in all text sections. */ for (s = abs_bfd->sections; s != NULL; s = s->next) if (s->flags & SEC_CODE) - if (bfd_get_section_contents(abs_bfd, s, + if (!bfd_get_section_contents(abs_bfd, s, text + (s->vma - text_vma), 0, - s->_raw_size) == false) + 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); @@ -1336,14 +1817,16 @@ int main(int argc, char *argv[]) /* Read in all data sections. */ for (s = abs_bfd->sections; s != NULL; s = s->next) if (s->flags & SEC_DATA) - if (bfd_get_section_contents(abs_bfd, s, + if (!bfd_get_section_contents(abs_bfd, s, data + (s->vma - data_vma), 0, - s->_raw_size) == false) + 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); @@ -1362,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); @@ -1374,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) fclose(gf); \ - if (!(gf = popen(cmd, "w"))) { \ - fprintf(stderr, "Can't run cmd %s\n", cmd); \ - exit(4); \ - } \ - } while (0) - - gf = fopen(ofile, "a"); - if (!gf) { - fprintf(stderr, "Can't opne 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); - 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 + */