/* BFD back-end for Intel 960 b.out binaries.
- Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
- bfd_seek (abfd, 0L, SEEK_SET);
+ bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd);
/* Now write out reloc info, followed by syms and strings */
if (bfd_get_symcount (abfd) != 0)
{
- bfd_seek (abfd,
- (long)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET);
+ bfd_seek (abfd, (file_ptr)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET);
aout_32_write_syms (abfd);
- bfd_seek (abfd, (long)(N_TROFF(*exec_hdr(abfd))), SEEK_SET);
+ bfd_seek (abfd, (file_ptr)(N_TROFF(*exec_hdr(abfd))), SEEK_SET);
if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
- bfd_seek (abfd, (long)(N_DROFF(*exec_hdr(abfd))), SEEK_SET);
+ bfd_seek (abfd, (file_ptr)(N_DROFF(*exec_hdr(abfd))), SEEK_SET);
if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
}
#define PCREL13_MASK 0x1fff
/* Magic to turn callx into calljx */
static bfd_reloc_status_type
-DEFUN (calljx_callback, (abfd, reloc_entry, src, dst, input_section),
+DEFUN (calljx_callback, (abfd, reloc_entry, src, dst, input_section, seclet),
bfd *abfd AND
arelent *reloc_entry AND
PTR src AND
PTR dst AND
-
- asection *input_section)
+ asection *input_section AND
+ bfd_seclet_type *seclet)
{
int word = bfd_get_32(abfd, src);
asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
aout_symbol_type *symbol = aout_symbol(symbol_in);
+ if (symbol_in->section == &bfd_und_section)
+ {
+ bfd_error_vector.undefined_symbol(reloc_entry, seclet);
+ }
+
if (IS_CALLNAME(symbol->other))
{
/* Magic to turn call into callj */
static bfd_reloc_status_type
-DEFUN (callj_callback, (abfd, reloc_entry, data, srcidx,dstidx, input_section),
+DEFUN (callj_callback, (abfd, reloc_entry, data, srcidx,dstidx,
+ input_section, seclet),
bfd *abfd AND
arelent *reloc_entry AND
PTR data AND
unsigned int srcidx AND
unsigned int dstidx AND
- asection *input_section )
+ asection *input_section AND
+ bfd_seclet_type *seclet)
{
int word = bfd_get_32(abfd, (bfd_byte *) data + srcidx);
asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
aout_symbol_type *symbol = aout_symbol(symbol_in);
+ if (symbol_in->section == &bfd_und_section)
+ {
+ bfd_error_vector.undefined_symbol(reloc_entry, seclet);
+ }
+
if (IS_OTHER(symbol->other))
{
/* Call to a system procedure - replace code with system
#define ABS32_MAYBE_RELAXABLE 1
#define ABS32_WAS_RELAXABLE 2
+#define ALIGNER 10
+#define ALIGNDONE 11
static reloc_howto_type howto_reloc_callj =
HOWTO(CALLJ, 0, 2, 24, true, 0, true, true, 0,"callj", true, 0x00ffffff, 0x00ffffff,false);
static reloc_howto_type howto_reloc_abs32 =
static reloc_howto_type howto_reloc_abs32code =
HOWTO(ABS32CODE, 0, 2, 32, false, 0, true, true,0,"callx", true, 0xffffffff,0xffffffff,false);
+static reloc_howto_type howto_align_table[] = {
+ HOWTO (ALIGNER, 0, 0x1, 0, false, 0, false, false, 0, "align16", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0x3, 0, false, 0, false, false, 0, "align32", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0x7, 0, false, 0, false, false, 0, "align64", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0xf, 0, false, 0, false, false, 0, "align128", false, 0, 0, false),
+};
+
+static reloc_howto_type howto_done_align_table[] = {
+ HOWTO (ALIGNDONE, 0x1, 0x1, 0, false, 0, false, false, 0, "donealign16", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0x3, 0x3, 0, false, 0, false, false, 0, "donealign32", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0x7, 0x7, 0, false, 0, false, false, 0, "donealign64", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0xf, 0xf, 0, false, 0, false, false, 0, "donealign128", false, 0, 0, false),
+};
+
static reloc_howto_type *
b_out_reloc_type_lookup (abfd, code)
bfd *abfd;
register struct relocation_info *rptr;
unsigned int counter ;
arelent *cache_ptr ;
- int extern_mask, pcrel_mask, callj_mask;
+ int extern_mask, pcrel_mask, callj_mask, length_shift;
int incode_mask;
int size_mask;
bfd_vma prev_addr = 0;
return false;
doit:
- bfd_seek (abfd, (long)(asect->rel_filepos), SEEK_SET);
+ bfd_seek (abfd, (file_ptr)(asect->rel_filepos), SEEK_SET);
count = reloc_size / sizeof (struct relocation_info);
relocs = (struct relocation_info *) bfd_xmalloc (reloc_size);
incode_mask = 0x08;
callj_mask = 0x02;
size_mask = 0x20;
+ length_shift = 5;
} else {
/* little-endian bit field allocation order */
pcrel_mask = 0x01;
incode_mask = 0x10;
callj_mask = 0x40;
size_mask = 0x02;
+ length_shift = 1;
}
for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;
unsigned char *raw = (unsigned char *)rptr;
unsigned int symnum;
cache_ptr->address = bfd_h_get_32 (abfd, raw + 0);
+ cache_ptr->howto = 0;
if (abfd->xvec->header_byteorder_big_p)
{
symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];
* the reloc entry addend has added to it the offset into the
* file of the data, so subtract the base to make the reloc
* section relative */
+ int s;
+ {
+ /* sign-extend symnum from 24 bits to whatever host uses */
+ s = symnum;
+ if (s & (1 << 23))
+ s |= (~0) << 24;
+ }
cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
- switch (symnum)
+ switch (s)
{
case N_TEXT:
case N_TEXT | N_EXT:
cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;
cache_ptr->addend = 0;
break;
+ case -2: /* .align */
+ if (raw[7] & pcrel_mask)
+ {
+ cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];
+ cache_ptr->sym_ptr_ptr = &bfd_abs_symbol;
+ }
+ else
+ {
+ /* .org? */
+ abort ();
+ }
+ cache_ptr->addend = 0;
+ break;
default:
BFD_ASSERT(0);
break;
/* the i960 only has a few relocation types:
abs 32-bit and pcrel 24bit. except for callj's! */
- if (raw[7] & callj_mask)
+ if (cache_ptr->howto != 0)
+ ;
+ else if (raw[7] & callj_mask)
{
cache_ptr->howto = &howto_reloc_callj;
}
*/
arelent tmp;
arelent *cursor = cache_ptr-1;
- unsigned int where = counter;
bfd_vma stop = cache_ptr->address;
tmp = *cache_ptr;
- while (cursor->address > stop)
+ while (cursor->address > stop && cursor >= reloc_cache)
{
cursor[1] = cursor[0];
cursor--;
arelent **generic;
int r_extern;
int r_idx;
- int r_addend;
int incode_mask;
int len_1;
unsigned int count = section->reloc_count;
struct relocation_info *native, *natptr;
size_t natsize = count * sizeof (struct relocation_info);
int extern_mask, pcrel_mask, len_2, callj_mask;
- int len1;
if (count == 0) return true;
generic = section->orelocation;
native = ((struct relocation_info *) bfd_xmalloc (natsize));
if (!native) {
- bfd_error = no_memory;
- return false;
- }
+ bfd_error = no_memory;
+ return false;
+ }
if (abfd->xvec->header_byteorder_big_p)
{
callj_mask = 0x02;
incode_mask = 0x08;
}
-else
+ else
{
/* Little-endian bit field allocation order */
pcrel_mask = 0x01;
arelent *g = *generic;
unsigned char *raw = (unsigned char *)natptr;
asymbol *sym = *(g->sym_ptr_ptr);
-
+
asection *output_section = sym->section->output_section;
+
bfd_h_put_32(abfd, g->address, raw);
/* Find a type in the output format which matches the input howto -
* at the moment we assume input format == output format FIXME!!
*/
+ r_idx = 0;
/* FIXME: Need callj stuff here, and to check the howto entries to
be sure they are real for this architecture. */
if (g->howto== &howto_reloc_callj)
{
raw[7] = len_2 + incode_mask;
}
- else {
- raw[7] = len_2;
+ else if (g->howto >= howto_align_table
+ && g->howto <= (howto_align_table
+ + sizeof (howto_align_table) / sizeof (howto_align_table[0])
+ - 1))
+ {
+ /* symnum == -2; extern_mask not set, pcrel_mask set */
+ r_idx = -2;
+ r_extern = 0;
+ raw[7] = (pcrel_mask
+ | ((g->howto - howto_align_table) << 1));
}
- if (output_section == &bfd_com_section
- || output_section == &bfd_abs_section
- || output_section == &bfd_und_section)
+ else {
+ raw[7] = len_2;
+ }
+
+ if (r_idx != 0)
+ /* already mucked with r_extern, r_idx */;
+ else if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
{
- /* Fill in symbol */
- r_extern = 1;
- r_idx = stoi((*(g->sym_ptr_ptr))->flags);
+
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_idx = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+
+ r_extern = 1;
+ r_idx = stoi((*(g->sym_ptr_ptr))->flags);
+ }
}
else
{
}
if (abfd->xvec->header_byteorder_big_p) {
- raw[4] = (unsigned char) (r_idx >> 16);
- raw[5] = (unsigned char) (r_idx >> 8);
- raw[6] = (unsigned char) (r_idx );
- } else {
- raw[6] = (unsigned char) (r_idx >> 16);
- raw[5] = (unsigned char) (r_idx>> 8);
- raw[4] = (unsigned char) (r_idx );
- }
-if (r_extern)
- raw[7] |= extern_mask;
+ raw[4] = (unsigned char) (r_idx >> 16);
+ raw[5] = (unsigned char) (r_idx >> 8);
+ raw[6] = (unsigned char) (r_idx );
+ } else {
+ raw[6] = (unsigned char) (r_idx >> 16);
+ raw[5] = (unsigned char) (r_idx>> 8);
+ raw[4] = (unsigned char) (r_idx );
+ }
+ if (r_extern)
+ raw[7] |= extern_mask;
}
if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
- free((PTR)native);
- return false;
- }
+ free((PTR)native);
+ return false;
+ }
free ((PTR)native);
return true;
{
bfd_vma value;
asymbol *symbol = *(reloc->sym_ptr_ptr);
+
/* A symbol holds a pointer to a section, and an offset from the
base of the section. To relocate, we find where the section will
live in the output and add that in */
symbol->section->output_offset +
symbol->section->output_section->vma;
}
-
-
+
/* Add the value contained in the relocation */
- value += (short)((reloc->addend) & 0xffff);
+ value += reloc->addend;
return value;
}
}
}
-
+#if 1
/* This routine works out if the thing we want to get to can be
reached with a 24bit offset instead of a 32 bit one.
If it can, then it changes the amode */
unsigned int shrink)
{
bfd_vma value = get_value(r,0);
-
-
bfd_vma dot = input_section->output_section->vma + input_section->output_offset + r->address;
bfd_vma gap;
if (-1<<23 < (long)gap && (long)gap < 1<<23 )
{
-
/* Change the reloc type from 32bitcode possible 24, to 24bit
possible 32 */
/* This will be four bytes smaller in the long run */
shrink += 4 ;
perform_slip(symbols, 4, input_section, r->address-shrink +4);
+ }
+ return shrink;
+}
-
+static int
+DEFUN(aligncode,(input_section, symbols, r, shrink),
+ asection *input_section AND
+ asymbol **symbols AND
+ arelent *r AND
+ unsigned int shrink)
+{
+ bfd_vma dot = input_section->output_section->vma + input_section->output_offset + r->address;
+ bfd_vma gap;
+ bfd_vma old_end;
+ bfd_vma new_end;
+ int shrink_delta;
+ int size = r->howto->size;
+
+ /* Reduce the size of the alignment so that it's still aligned but
+ smaller - the current size is already the same size as or bigger
+ than the alignment required. */
+
+ /* calculate the first byte following the padding before we optimize */
+ old_end = ((dot + size ) & ~size) + size+1;
+ /* work out where the new end will be - remember that we're smaller
+ than we used to be */
+ new_end = ((dot - shrink + size) & ~size);
+
+ /* This is the new end */
+ gap = old_end - ((dot + size) & ~size);
+
+ shrink_delta = (old_end - new_end) - shrink;
+
+ if (shrink_delta)
+ {
+ /* Change the reloc so that it knows how far to align to */
+ r->howto = howto_done_align_table + (r->howto - howto_align_table);
+
+ /* Encode the stuff into the addend - for future use we need to
+ know how big the reloc used to be */
+ r->addend = old_end ;
+
+ /* This will be N bytes smaller in the long run, adjust all the symbols */
+ perform_slip(symbols, shrink_delta, input_section, r->address - shrink );
+ shrink += shrink_delta;
}
return shrink;
}
{
arelent *r = *parent;
switch (r->howto->type) {
+ case ALIGNER:
+ /* An alignment reloc */
+ shrink = aligncode(input_section, symbols, r,shrink);
+ new=true;
+ break;
case ABS32CODE:
/* A 32bit reloc in an addressing mode */
shrink = abs32code(input_section, symbols, r,shrink);
return new;
}
+#endif
static bfd_byte *
-DEFUN(b_out_get_relocated_section_contents,(in_abfd, seclet, data),
+DEFUN(b_out_get_relocated_section_contents,(in_abfd,
+ seclet,
+ data,
+ relocateable),
bfd *in_abfd AND
bfd_seclet_type *seclet AND
- bfd_byte *data)
-
+ bfd_byte *data AND
+ boolean relocateable)
{
/* Get enough memory to hold the stuff */
bfd *input_bfd = seclet->u.indirect.section->owner;
input_section);
arelent **reloc_vector = (arelent **)alloca(reloc_size);
+ /* If producing relocateable output, don't bother to relax. */
+ if (relocateable)
+ return bfd_generic_get_relocated_section_contents (in_abfd, seclet,
+ data, relocateable);
+
/* read in the section */
bfd_get_section_contents(input_bfd,
input_section,
switch (reloc->howto->type)
{
case ABS32CODE:
- calljx_callback(in_abfd, reloc, src_address + data, dst_address+data, input_section);
+ calljx_callback(in_abfd, reloc, src_address + data, dst_address+data,
+ input_section, seclet);
src_address+=4;
dst_address+=4;
break;
case ABS32:
- bfd_put_32(in_abfd, get_value(reloc, seclet), data+dst_address);
+ bfd_put_32(in_abfd,
+ (bfd_get_32 (in_abfd, data+src_address)
+ + get_value(reloc, seclet)),
+ data+dst_address);
src_address+=4;
dst_address+=4;
break;
case CALLJ:
- callj_callback(in_abfd, reloc ,data,src_address,dst_address,input_section);
+ callj_callback(in_abfd, reloc ,data,src_address,dst_address,
+ input_section, seclet);
src_address+=4;
dst_address+=4;
break;
+ case ALIGNDONE:
+ src_address = reloc->addend;
+ dst_address = (dst_address + reloc->howto->size) & ~reloc->howto->size;
+ break;
case ABS32CODE_SHRUNK:
/* This used to be a callx, but we've found out that a
callj will reach, so do the right thing */
- callj_callback(in_abfd, reloc,data,src_address+4, dst_address,input_section);
+ callj_callback(in_abfd, reloc,data,src_address+4, dst_address,
+ input_section, seclet);
dst_address+=4;
src_address+=8;
{
long int word = bfd_get_32(in_abfd, data+src_address);
asymbol *symbol = *(reloc->sym_ptr_ptr);
- word = (word & ~BAL_MASK) |
- (((word & BAL_MASK) +
- symbol->section->output_offset +
- symbol->section->output_section->vma+
- symbol->value + reloc->addend - dst_address -
- ( input_section->output_section->vma + input_section->output_offset))
- & BAL_MASK);
+ if (symbol->section == &bfd_und_section)
+ {
+ bfd_error_vector.undefined_symbol(reloc, seclet);
+ }
+ word = ((word & ~BAL_MASK)
+ | (((word & BAL_MASK)
+ /* value of symbol */
+ + symbol->value
+ /* how far it's moving in this relocation */
+ + (symbol->section->output_offset
+ + symbol->section->output_section->vma)
+ - (input_section->output_section->vma
+ + input_section->output_offset)
+ /* addend, of course */
+ + reloc->addend)
+ & BAL_MASK));
bfd_put_32(in_abfd,word, data+dst_address);
- dst_address+=4;
- src_address+=4;
+ dst_address+=4;
+ src_address+=4;
}
-break;
+ break;
case PCREL13:
{
long int word = bfd_get_32(in_abfd, data+src_address);
asymbol *symbol = *(reloc->sym_ptr_ptr);
- word = (word & ~PCREL13_MASK) |
- (((word & PCREL13_MASK) +
- symbol->section->output_offset +
- symbol->section->output_section->vma+
- symbol->value + reloc->addend - dst_address -
- ( input_section->output_section->vma + input_section->output_offset))
- & PCREL13_MASK);
+ if (symbol->section == &bfd_und_section)
+ {
+ bfd_error_vector.undefined_symbol(reloc, seclet);
+ }
+ word = ((word & ~PCREL13_MASK)
+ | (((word & PCREL13_MASK)
+ + (symbol->section->output_offset
+ + symbol->section->output_section->vma)
+ + symbol->value
+ + reloc->addend
+ - (input_section->output_section->vma
+ + input_section->output_offset))
+ & PCREL13_MASK));
bfd_put_32(in_abfd,word, data+dst_address);
- dst_address+=4;
- src_address+=4;
+ dst_address+=4;
+ src_address+=4;
}
-break;
+ break;
- default:
+ default:
abort();
}
#define aout_32_bfd_get_relocated_section_contents b_out_get_relocated_section_contents
#define aout_32_bfd_relax_section b_out_relax_section
+#define aout_32_bfd_seclet_link bfd_generic_seclet_link
+#define aout_32_bfd_reloc_type_lookup b_out_reloc_type_lookup
+#define aout_32_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
bfd_target b_out_vec_big_host =
{
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT ),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* symbol leading char */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
- 2, /* minumum alignment power */
+ 2, /* minumum alignment power */
-_do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */
-_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
- {_bfd_dummy_target, b_out_object_p, /* bfd_check_format */
- bfd_generic_archive_p, _bfd_dummy_target},
- {bfd_false, b_out_mkobject, /* bfd_set_format */
- _bfd_generic_mkarchive, bfd_false},
- {bfd_false, b_out_write_object_contents, /* bfd_write_contents */
- _bfd_write_archive_contents, bfd_false},
+ _do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16, /* data */
+ _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
+ {_bfd_dummy_target, b_out_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, b_out_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, b_out_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
JUMP_TABLE(aout_32),
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* COFF stuff?! */
- b_out_reloc_type_lookup,
+ (PTR) 0,
};
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT ),
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* symbol leading char */
' ', /* ar_pad_char */
16, /* ar_max_namelen */
2, /* minum align */
{bfd_false, b_out_write_object_contents, /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
JUMP_TABLE(aout_32),
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* COFF stuff?! */
- b_out_reloc_type_lookup,
+ (PTR) 0
};