* ELF format file handling. Extended relocation support for all of
* text and data.
*
+ * (c) 2006 Support the -a (use_resolved) option for TARGET_arm.
+ * Shaun Jackman <sjackman@gmail.com>
* (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>
* (c) 2003, H8 support, ktrace <davidm@snapgear.com>
* (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
#include <unistd.h> /* Userland prototypes of the Unix std system calls */
#include <fcntl.h> /* Flag value for file handling functions */
#include <time.h>
-#ifndef WIN32
-#include <netinet/in.h> /* Consts and structs defined by the internet system */
-#else
-#include <winsock2.h>
-#endif
/* from $(INSTALLDIR)/include */
#include <bfd.h> /* Main header file for the BFD library */
+#include <libiberty.h>
+
+#include "stubs.h"
+const char *elf2flt_progname;
#if defined(TARGET_h8300)
#include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
#include "cygwin-elf.h" /* Cygwin uses a local copy */
#elif defined(TARGET_microblaze)
#include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
-#elif defined(TARGET_bfin)
-#include "elf/bfin.h"
#else
#include <elf.h> /* 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 <getopt.h>
#endif
/* from uClinux-x.x.x/include/linux */
#include "flat.h" /* Binary flat header description */
+#include "compress.h"
#ifdef TARGET_e1
#include <e1.h>
#define ARCH "e1-coff"
#elif defined(TARGET_bfin)
#define ARCH "bfin"
-#define FLAT_RELOC_TYPE_TEXT 0
-#define FLAT_RELOC_TYPE_DATA 1
-#define FLAT_RELOC_TYPE_BSS 2
-#define FLAT_RELOC_TYPE_STACK 3
-#define FLAT_RELOC_PART_LO 0
-#define FLAT_RELOC_PART_HI 1
-#define PCREL24_MAGIC_OFFSET -1
#elif defined(TARGET_nios)
#define ARCH "nios"
#elif defined(TARGET_nios2)
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 */
/* 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;
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);
+#ifdef TARGET_nios2
long
get_gp_value(asymbol **symbol_table, long number_of_symbols)
{
}
return -1;
}
-
+#endif
-long
-add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
+
+int32_t
+add_com_to_bss(asymbol **symbol_table, int32_t number_of_symbols, int32_t bss_len)
{
- long i, comsize;
- long offset;
+ int32_t i, comsize;
+ int32_t offset;
comsize = 0;
for (i=0; i<number_of_symbols; i++) {
}
#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.
*/
}
static int
-bfin_set_reloc (uint32_t *reloc,
- const char *reloc_section_name,
+bfin_set_reloc (uint32_t *reloc,
+ const char *reloc_section_name,
const char *sym_name,
struct bfd_symbol *symbol,
- int sp, int hilo, int32_t offset)
+ int sp, int32_t offset)
{
- unsigned int type;
+ unsigned int type = 0;
uint32_t val;
- if (strstr (reloc_section_name, "text"))
- type = FLAT_RELOC_TYPE_TEXT;
- else if (strstr (reloc_section_name, "data"))
- type = FLAT_RELOC_TYPE_DATA;
- else if (strstr (reloc_section_name, "bss"))
- type = FLAT_RELOC_TYPE_BSS;
- else if (strstr (reloc_section_name, "stack"))
- type = FLAT_RELOC_TYPE_STACK;
- else if (symbol->flags & BSF_WEAK){
- /* weak symbol support ... if a weak symbol is undefined at the
- end of a final link, it should return 0 rather than error
- We will assume text section for the moment.
- */
- type = FLAT_RELOC_TYPE_TEXT;
- } else if (strstr (reloc_section_name, "*ABS*")){
- /* (A data section initialization of something in the shared libc's text section
- does not resolve - i.e. a global pointer to function initialized with
- a libc function).
- The text section here is appropriate as the section information
- of the shared library is lost. The loader will do some calcs.
- */
- type = FLAT_RELOC_TYPE_TEXT;
- } else {
- printf ("Unknown Type - relocation for %s in bad section - %s\n", sym_name, reloc_section_name);
- return 1;
+ 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)) << 6;
- val |= (sp & (1 << 3) - 1) << 3;
- val |= (hilo & 1) << 2;
- val |= (type & (1 << 2) - 1);
+ val = (offset & ((1 << 26) - 1));
+ val |= (sp & (1 << 3) - 1) << 26;
+ val |= type << 29;
*reloc = val;
return 0;
}
-#endif
+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
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)
{
uint32_t *flat_relocs;
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;
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"
* 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
}
}
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)
__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;
{
case R_MICROBLAZE_NONE:
case R_MICROBLAZE_64_NONE:
+ case R_MICROBLAZE_32_PCREL_LO:
continue;
}
#endif /* TARGET_microblaze */
-#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);
- 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_v850
/* Skip this relocation entirely if possible (we
do this early, before doing any other
#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;
/* 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
* 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;
+ lo;
}
} else
- goto bad_v850_reloc_err;
+ goto bad_resolved_reloc;
break;
case R_V850_LO16:
&& (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
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)
+ (r_mem[2] << 16)
+ (r_mem[3] << 24);
relocation_needed = 1;
+ break;
+
+ bad_resolved_reloc:
+ printf("ERROR: reloc type %s unsupported in this context\n",
+ q->howto->name);
+ bad_relocs++;
+ break;
}
} else {
/* Calculate the sym address ourselves. */
sym_reloc_size = bfd_get_reloc_size(q->howto);
-#if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin)
+#if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin) && !defined(TARGET_m68k)
if (sym_reloc_size != 4) {
printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
(*p)->howto->type, sym_reloc_size, sym_name);
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;
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;
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;
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;
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:
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;
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;
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_bfin
- case R_pcrel12_jump:
- case R_pcrel12_jump_s:
- case R_pcrel24:
- case R_pcrel24_jump_l:
- case R_pcrel24_jump_x:
- case R_pcrel24_call_x:
- case R_pcrel10:
- case R_pcrel11:
- case R_pcrel5m2:
- sym_addr += q->addend;// get the symbol addr
- sym_vma = bfd_section_vma(abs_bfd, sym_section);
- sym_addr -= q->address; // make it PC relative
- // implicitly assumes code section and symbol section are same
- break;
-
- case R_rimm16:
- if (is_reloc_stack_empty ())
- {
- sym_addr += q->addend;
- } else {
- sym_addr = reloc_stack_pop ();
- }
- if(weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))
- continue;
- if(0xFFFF0000 & sym_addr){
- fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name);
- bad_relocs++;
- }
- flat_relocs = (uint32_t *)
- (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
- if (bfin_set_reloc (flat_relocs + flat_reloc_count,
- sym_section->name, sym_name,
- (*(q->sym_ptr_ptr)),
- 0, FLAT_RELOC_PART_LO,
- section_vma + q->address))
- bad_relocs++;
- flat_reloc_count++;
- break;
-
- case R_luimm16:
- case R_huimm16:
- {
- unsigned int sp;
- unsigned int reloc_count_incr;
- unsigned int hi_lo;
-
- if (q->howto->type == R_luimm16)
- hi_lo = FLAT_RELOC_PART_LO;
- else
- hi_lo = FLAT_RELOC_PART_HI;
-
- if (is_reloc_stack_empty ())
- sym_addr += q->addend;
- else
- sym_addr = reloc_stack_pop ();
-
- flat_relocs = (uint32_t *)
- (realloc (flat_relocs, (flat_reloc_count + 2) * sizeof (uint32_t)));
- reloc_count_incr = 1;
- if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))
- continue;
- if (0xFFFF0000 & sym_addr) {
- /* value is > 16 bits - use an extra field */
- /* see if we have already output that symbol */
- /* reloc may be addend from symbol and */
- /* we can only store 16 bit offsets */
- sp = 1;
- if ((*(q->sym_ptr_ptr))->udata.i == 0
- || flat_relocs[(*(q->sym_ptr_ptr))->udata.i] != sym_addr
- || ((*(q->sym_ptr_ptr))->udata.i & 0xFFFF0000))
- {
- reloc_count_incr = 2;
- flat_relocs[flat_reloc_count + 1] = sym_addr;
- (*(q->sym_ptr_ptr))->udata.i = flat_reloc_count + 1;
- sym_addr = 0; // indication to loader to read next
- } else{
- sym_addr = (*(q->sym_ptr_ptr))->udata.i;
- }
- } else {
- sp = 0;
- }
-
- if (bfin_set_reloc (flat_relocs + flat_reloc_count,
- sym_section->name, sym_name,
- (*(q->sym_ptr_ptr)),
- sp, hi_lo,
- section_vma + q->address))
- bad_relocs++;
- flat_reloc_count += reloc_count_incr;
- break;
- }
- case R_byte4_data:
- if (is_reloc_stack_empty ())
- sym_addr += q->addend;
- else
- sym_addr = reloc_stack_pop ();
- if (weak_und_symbol (sym_section->name, *q->sym_ptr_ptr))
- continue;
-
- flat_relocs = (uint32_t *)
- (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
- if (bfin_set_reloc (flat_relocs + flat_reloc_count,
- sym_section->name, sym_name,
- (*(q->sym_ptr_ptr)),
- 2, FLAT_RELOC_PART_LO,
- section_vma + q->address))
- bad_relocs++;
-
- flat_reloc_count++;
- break;
-
- 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
case R_SH_DIR32:
#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;
/*
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;
-
-#elif defined(TARGET_bfin)
- if ((*p)->howto->type == R_pcrel24
- || (*p)->howto->type == R_pcrel24_jump_l
- || (*p)->howto->type == R_pcrel24_jump_x
- || (*p)->howto->type == R_pcrel24_call_x)
- {
- sym_addr += 2*-1*PCREL24_MAGIC_OFFSET;
- *((unsigned short *)(sectionp + q->address) + 1 + PCREL24_MAGIC_OFFSET)
- = (sym_addr >> 1) & 0xffff;
- *((unsigned short *)(sectionp + q->address) + PCREL24_MAGIC_OFFSET)
- = (0xff00 & *((unsigned short *) (sectionp + q->address) + PCREL24_MAGIC_OFFSET)
- | ((sym_addr >> 17) & 0xff));
- } else if ((*p)->howto->type == R_byte4_data) {
- *((uint32_t *)(sectionp + q->address)) = sym_addr;
- } else if ((*p)->howto->type == R_pcrel12_jump
- || (*p)->howto->type == R_pcrel12_jump_s) {
- *((unsigned short *)(sectionp + q->address))
- = (0xf000 & *((unsigned short *)(sectionp + q->address))
- | ((sym_addr >> 1) & 0xfff));
- } else if ((*p)->howto->type == R_pcrel10) {
- *((unsigned short *)(sectionp + q->address))
- = (~0x3ff & *((unsigned short *)(sectionp + q->address))
- | ((sym_addr >> 1) & 0x3ff));
- } else if ((*p)->howto->type == R_rimm16
- || (*p)->howto->type == R_huimm16
- || (*p)->howto->type == R_luimm16) {
- /* for l and h we set the lower 16 bits which is only when it will be used */
- *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr;
- } else if ((*p)->howto->type == R_pcrel5m2) {
- *((unsigned short *)(sectionp + q->address))
- = (0xfff0 & *((unsigned short *)(sectionp + q->address))
- | ((sym_addr >> 1) & 0xf));
- } else if ((*p)->howto->type == R_pcrel11){
- *((unsigned short *)(sectionp + q->address))
- = (0xfc00 & *((unsigned short *)(sectionp + q->address))
- | ((sym_addr >> 1) & 0x3ff));
- } else if (0xE0 <= (*p)->howto->type && 0xF3 >= (*p)->howto->type) {
- //arith relocs dont generate a real relocation
- } else {
- printf("Blackfin relocation fail for reloc type: 0x%x\n", (*p)->howto->type);
- }
+ *(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) {
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
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
#endif /* !TARGET_arm */
}
-#ifdef TARGET_bfin
- else {
- if ((*p)->howto->type == R_rimm16
- || (*p)->howto->type == R_huimm16
- || (*p)->howto->type == R_luimm16)
- {
- /* for l and h we set the lower 16 bits which is only when it will be used */
- *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr;
- } else if ((*p)->howto->type == R_byte4_data) {
- *((uint32_t *)(sectionp + q->address)) = sym_addr;
- }
- }
-#endif
if (verbose)
printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
"section=%s size=%d "
}
#endif
flat_reloc_count++;
-#endif
+#endif //TARGET_bfin
relocation_needed = 0;
pflags = 0;
}
-static char * program;
-
static void usage(void)
-{
+{
fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
"[-o <output-file>] <elf-file>\n\n"
" -v : verbose operation\n"
" -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);
}
}
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;
uint32_t *reloc;
-
- struct flat_hdr hdr;
- 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) {
- fprintf(stderr,
+
+ if (sizeof(hdr) != 64)
+ fatal(
"Potential flat header incompatibility detected\n"
- "header size should be 64 but is %d\n",
+ "header size should be 64 but is %d",
sizeof(hdr));
- exit(64);
- }
#ifndef TARGET_e1
stack = 4096;
ktrace++;
break;
case 'z':
- compress = 1;
+ docompress = 1;
break;
case 'd':
- compress = 2;
+ docompress = 2;
break;
case 'p':
pfile = optarg;
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;
if (!load_to_ram && !pfile)
load_to_ram = 1;
- filename = fname = argv[argc-1];
+ fname = argv[argc-1];
if (pfile) {
pic_with_got = 1;
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;
*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);
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);
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);
data_len = bss_vma - data_vma;
}
- reloc = output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
- text, text_len, text_vma, data, data_len, data_vma,
- rel_bfd);
+ 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);
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<reloc_len; i++) reloc[i] = htonl(reloc[i]);
}
if (!ofile) {
- ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
+ ofile = xmalloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
strcpy(ofile, fname);
strcat(ofile, ".bflt");
}
- if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
- fprintf (stderr, "Can't open output file %s\n", ofile);
- exit(4);
- }
+ if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0)
+ fatal_perror("Can't open output file %s", ofile);
write(fd, &hdr, sizeof(hdr));
close(fd);
- /*
- * get the compression command ready
- */
- sprintf(cmd, "gzip -f -9 >> %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);
}