#include "sysdep.h"
#include "libbfd.h"
#include "obstack.h"
-#include "coff-i960.h"
-#include "internalcoff.h"
+#include "coff/i960.h"
+#include "coff/internal.h"
#include "libcoff.h" /* to allow easier abstraction-breaking */
#define BAL_MASK 0x00ffffff
static bfd_reloc_status_type
-optcall_callback(abfd, reloc_entry, symbol_in, data, ignore_input_section)
-bfd *abfd;
-arelent *reloc_entry;
-asymbol *symbol_in;
-unsigned char *data;
-asection *ignore_input_section;
+DEFUN (optcall_callback, (abfd, reloc_entry, symbol_in, data, ignore_input_section),
+ bfd *abfd AND
+ arelent *reloc_entry AND
+ asymbol *symbol_in AND
+ PTR data AND
+ asection *ignore_input_section)
{
/* This item has already been relocated correctly, but we may be
* able to patch in yet better code - done by digging out the
to the correct location */
{
union internal_auxent *aux = &((cs->native+2)->u.auxent);
- int word = bfd_get_32(abfd, data + reloc_entry->address);
+ int word = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address);
int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
BFD_ASSERT(cs->native->u.syment.n_numaux==2);
/* We replace the original call instruction with a bal to */
/* offset of the bal entry point */
word = ((word + olf) & BAL_MASK) | BAL;
- bfd_put_32(abfd, word, data+reloc_entry->address);
+ bfd_put_32(abfd, word, (bfd_byte *) data + reloc_entry->address);
}
result = bfd_reloc_ok;
break;
return result;
}
-
-
-static reloc_howto_type howto_table[] =
-{
- {0},
- {1},
- {2},
- {3},
- {4},
- {5},
- {6},
- {7},
- {8},
- {9},
- {10},
- {11},
- {12},
- {13},
- {14},
- {15},
- {16},
-
+static reloc_howto_type howto_rellong =
{ (unsigned int) R_RELLONG, 0, 2, 32,false, 0, true, true,
- 0,"rellong", true, 0xffffffff, 0xffffffff},
- {18},
- {19},
- {20},
- {21},
- {22},
- {23},
- {24},
-
+ 0,"rellong", true, 0xffffffff, 0xffffffff};
+static reloc_howto_type howto_iprmed =
{ R_IPRMED, 0, 2, 24,true,0, true, true,0,"iprmed ", true,
- 0x00ffffff, 0x00ffffff},
- {26},
-
+ 0x00ffffff, 0x00ffffff};
+static reloc_howto_type howto_optcall =
{ R_OPTCALL, 0,2,24,true,0, true, true, optcall_callback,
- "optcall", true, 0x00ffffff, 0x00ffffff},
+ "optcall", true, 0x00ffffff, 0x00ffffff};
-};
+static reloc_howto_type *
+DEFUN (coff_i960_reloc_type_lookup, (abfd, code),
+ bfd *abfd AND
+ bfd_reloc_code_type code)
+{
+ switch (code)
+ {
+ default:
+ return 0;
+ case BFD_RELOC_I960_CALLJ:
+ return &howto_optcall;
+ case BFD_RELOC_32:
+ return &howto_rellong;
+ case BFD_RELOC_24_PCREL:
+ return &howto_iprmed;
+ }
+}
/* The real code is in coffcode.h */
#define RTYPE2HOWTO(cache_ptr, dst) \
- cache_ptr->howto = howto_table + dst.r_type;
+{ \
+ reloc_howto_type *howto_ptr; \
+ switch ((dst)->r_type) { \
+ case 17: howto_ptr = &howto_rellong; break; \
+ case 25: howto_ptr = &howto_iprmed; break; \
+ case 27: howto_ptr = &howto_optcall; break; \
+ default: howto_ptr = 0; break; \
+ } \
+ cache_ptr->howto = howto_ptr; \
+ }
#include "coffcode.h"
_bfd_generic_mkarchive, bfd_false},
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
- JUMP_TABLE(coff)
- };
+ JUMP_TABLE(coff),
+ COFF_SWAP_TABLE,
+ coff_i960_reloc_type_lookup,
+ coff_make_debug_symbol,
+};
bfd_target icoff_big_vec =
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
_bfd_write_archive_contents, bfd_false},
JUMP_TABLE(coff),
-COFF_SWAP_TABLE
+ COFF_SWAP_TABLE,
+ coff_i960_reloc_type_lookup,
+ coff_make_debug_symbol,
};
Most of this hacked by Steve Chamberlain,
sac@cygnus.com
*/
+
+#include <assert.h>
+#include <stdio.h>
+
/*
SECTION
DEFUN(styp_to_sec_flags, (styp_flags),
long styp_flags)
{
- flagword sec_flags=0;
-
- if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_DATA))
- sec_flags = (SEC_LOAD | SEC_ALLOC);
- else if (styp_flags & STYP_BSS)
- sec_flags = SEC_ALLOC;
+ flagword sec_flags=0;
-#ifdef STYP_LIT /* A29k readonly text/data section type */
- if ((styp_flags & STYP_LIT) == STYP_LIT)
- sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY);
-#endif /* STYP_LIT */
-#ifdef STYP_OTHER_LOAD /* Other loaded sections */
- if (styp_flags & STYP_OTHER_LOAD)
- sec_flags = (SEC_LOAD | SEC_ALLOC);
-#endif /* STYP_SDATA */
+ if ((styp_flags & STYP_TEXT) || (styp_flags & STYP_DATA))
+ {
+ sec_flags = SEC_LOAD | SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_BSS)
+ {
+ sec_flags = SEC_ALLOC;
+ }
+ else
+ {
+ sec_flags = SEC_ALLOC | SEC_LOAD;
+ }
+#ifdef STYP_LIT /* A29k readonly text/data section type */
+ if ((styp_flags & STYP_LIT) == STYP_LIT)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY);
+ }
+#endif /* STYP_LIT */
+#ifdef STYP_OTHER_LOAD /* Other loaded sections */
+ if (styp_flags & STYP_OTHER_LOAD)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC);
+ }
+#endif /* STYP_SDATA */
- return(sec_flags);
+ return(sec_flags);
}
#define get_index(symbol) ((int) (symbol)->udata)
*/
static boolean
-DEFUN(coff_new_section_hook,(abfd_ignore, section),
- bfd *abfd_ignore AND
+DEFUN(coff_new_section_hook,(abfd, section),
+ bfd *abfd AND
asection *section)
{
- section->alignment_power = abfd_ignore->xvec->align_power_min;
+ section->alignment_power = abfd->xvec->align_power_min;
+ /* Allocate aux records for section symbols, to store size and
+ related info.
+
+ @@ Shouldn't use constant multiplier here! */
+ coffsymbol (section->symbol)->native =
+ (combined_entry_type *) bfd_zalloc (abfd,
+ sizeof (combined_entry_type) * 10);
return true;
}
-static asection bfd_debug_section =
-{ "*DEBUG*" };
-
-
-
-static void
-DEFUN(make_abs_section,(abfd),
- bfd *abfd)
-{
-
-
-
-}
+static asection bfd_debug_section = { "*DEBUG*" };
/* Take a section header read from a coff file (in HOST byte order),
and make a BFD "section" out of it. */
unsigned int native_index = 0;
struct internal_syment *last_file = (struct internal_syment *)NULL;
unsigned int symbol_index;
+
+ /* COFF demands that undefined symbols come after all other symbols.
+ Since we don't need to impose this extra knowledge on all our client
+ programs, deal with that here. Sort the symbol table; just move the
+ undefined symbols to the end, leaving the rest alone. */
+ /* @@ Do we have some condition we could test for, so we don't always
+ have to do this? I don't think relocatability is quite right, but
+ I'm not certain. [raeburn:19920508.1711EST] */
+ {
+ asymbol **newsyms;
+ int i;
+
+ newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr,
+ sizeof (asymbol *) * symbol_count);
+ bfd_ptr->outsymbols = newsyms;
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section != &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section == &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ symbol_ptr_ptr = bfd_ptr->outsymbols;
+ }
+
for (symbol_index = 0; symbol_index < symbol_count; symbol_index++)
{
coff_symbol_type *coff_symbol_ptr = coff_symbol_from(bfd_ptr, symbol_ptr_ptr[symbol_index]);
native_index++;
}
}
+ obj_conv_table_size (bfd_ptr) = native_index;
}
int class = native->u.syment.n_sclass;
SYMENT buf;
unsigned int j;
+
+ /* @@ bfd_debug_section isn't accessible outside this file, but we know
+ that C_FILE symbols belong there. So move them. */
+ if (native->u.syment.n_sclass == C_FILE)
+ symbol->section = &bfd_debug_section;
+
if (symbol->section == &bfd_abs_section)
{
native->u.syment.n_scnum = N_ABS;
unsigned int written)
{
/*
- Does this symbol have an ascociated line number - if so then
+ Does this symbol have an associated line number - if so then
make it remember this symbol index. Also tag the auxent of
this symbol to point to the right place in the lineno table
*/
struct internal_reloc n;
arelent *q = p[i];
memset((PTR)&n, 0, sizeof(n));
+
+ /* @@FIXME COFF relocs don't support addends. Code should probably be
+ in the target-independent code, using a target flag to decide whether
+ to fold the addend into the section contents. */
+ if (q->addend != 0)
+ abort ();
+
n.r_vaddr = q->address + s->vma;
if (q->sym_ptr_ptr) {
n.r_symndx = get_index((*(q->sym_ptr_ptr)));
+ /* Take notice if the symbol reloc points to a symbol we don't have
+ in our symbol table. What should we do for this?? */
+ if (n.r_symndx > obj_conv_table_size (abfd))
+ abort ();
}
#ifdef SELECT_RELOC
/* Work out reloc type from what is required */
bfd_error = no_memory;
return (NULL);
} /* on error */
+ new->symbol.section = 0;
new->native = 0;
new->lineno = (alent *) NULL;
new->done_lineno = false;
#ifndef NO_COFF_SYMBOLS
+static asymbol *
+DEFUN (coff_make_debug_symbol, (abfd, ptr, sz),
+ bfd *abfd AND
+ PTR ptr AND
+ unsigned long sz)
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type));
+ if (new == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ } /* on error */
+ /* @@ This shouldn't be using a constant multiplier. */
+ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
+ new->symbol.section = &bfd_debug_section;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
static void
DEFUN(coff_print_symbol,(ignore_abfd, filep, symbol, how),
bfd *ignore_abfd AND
obj_relocbase(abfd) = sofar;
}
+#ifndef NO_COFF_SYMBOLS
+static asymbol *
+coff_section_symbol (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ asection *sec = bfd_get_section_by_name (abfd, name);
+ asymbol *sym;
+ combined_entry_type *csym;
+
+ if (!sec)
+ {
+ /* create empty symbol */
+ abort ();
+ }
+ sym = sec->symbol;
+ if (coff_symbol_from (abfd, sym))
+ csym = coff_symbol_from (abfd, sym)->native;
+ else
+ csym = 0;
+ /* Make sure back-end COFF stuff is there. */
+ if (csym == 0)
+ {
+ struct foo {
+ coff_symbol_type sym;
+ /* @@FIXME This shouldn't use a fixed size!! */
+ combined_entry_type e[10];
+ };
+ struct foo *f;
+ f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f));
+ bzero ((char *) f, sizeof (*f));
+ coff_symbol_from (abfd, sym)->native = csym = f->e;
+ }
+ csym[0].u.syment.n_sclass = C_STAT;
+ csym[0].u.syment.n_numaux = 1;
+/* SF_SET_STATICS (sym); @@ ??? */
+ if (sec)
+ {
+ csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size;
+ csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count;
+ csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count;
+ }
+ else
+ {
+ csym[1].u.auxent.x_scn.x_scnlen = 0;
+ csym[1].u.auxent.x_scn.x_nreloc = 0;
+ csym[1].u.auxent.x_scn.x_nlinno = 0;
+ }
+ return sym;
+}
+/* If .file, .text, .data, .bss symbols are missing, add them. */
+/* @@ Should we only be adding missing symbols, or overriding the aux
+ values for existing section symbols? */
+static void
+coff_add_missing_symbols (abfd)
+ bfd *abfd;
+{
+ unsigned int nsyms = bfd_get_symcount (abfd);
+ asymbol **sympp = abfd->outsymbols;
+ asymbol **sympp2;
+ unsigned int i;
+ int need_text = 1, need_data = 1, need_bss = 1, need_file = 1;
+ coff_data_type *cdata = coff_data (abfd);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ coff_symbol_type *csym = coff_symbol_from (abfd, sympp[i]);
+ CONST char *name;
+ if (csym->native->u.syment.n_sclass == C_FILE)
+ {
+ need_file = 0;
+ continue;
+ }
+ name = csym->symbol.name;
+ if (!name)
+ continue;
+ if (!strcmp (name, _TEXT))
+ need_text = 0;
+ else if (!strcmp (name, _DATA))
+ need_data = 0;
+ else if (!strcmp (name, _BSS))
+ need_bss = 0;
+ }
+ /* Now i == bfd_get_symcount (abfd). */
+ /* @@ For now, don't deal with .file symbol. */
+ need_file = 0;
+
+ if (!need_text && !need_data && !need_bss && !need_file)
+ return;
+ nsyms += need_text + need_data + need_bss + need_file;
+ sympp2 = (asymbol**) bfd_alloc_by_size_t (abfd, nsyms * sizeof (asymbol *));
+ memcpy (sympp2, sympp, i * sizeof (asymbol *));
+ if (need_file)
+ {
+ /* @@ Generate fake .file symbol, in sympp2[i], and increment i. */
+ abort ();
+ }
+ if (need_text)
+ sympp2[i++] = coff_section_symbol (abfd, _TEXT);
+ if (need_data)
+ sympp2[i++] = coff_section_symbol (abfd, _DATA);
+ if (need_bss)
+ sympp2[i++] = coff_section_symbol (abfd, _BSS);
+ assert (i == nsyms);
+ bfd_set_symtab (abfd, sympp2, nsyms);
+}
+#endif /* NO_COFF_SYMBOLS */
/* SUPPRESS 558 */
/* SUPPRESS 529 */
bfd_error = system_call_error;
/* Number the output sections, starting from one on the first section
- with a name which doesn't start with a * */
+ with a name which doesn't start with a *.
+ @@ The code doesn't make this check. Is it supposed to be done,
+ or isn't it?? */
count = 1;
for (current = abfd->sections; current != (asection *)NULL;
current = current->next)
{
current->target_index = count;
+ count++;
}
#ifndef NO_COFF_SYMBOLS
if (bfd_get_symcount(abfd) != 0) {
+ coff_add_missing_symbols (abfd);
coff_renumber_symbols(abfd);
coff_mangle_symbols(abfd);
coff_write_symbols(abfd);
obj_symbols(abfd) = cached_area;
obj_raw_syments(abfd) = native_symbols;
+ obj_conv_table_size (abfd) = bfd_get_symcount (abfd);
bfd_get_symcount(abfd) = number_of_symbols;
obj_convert(abfd) = table_ptr;
/* Slurp the line tables for each section too */
cache_ptr->address = dst.r_vaddr;
if (dst.r_symndx != -1)
- {
+ {
+ /* @@ Should never be greater than count of symbols! */
+ if (dst.r_symndx >= obj_conv_table_size (abfd))
+ abort ();
cache_ptr->sym_ptr_ptr = symbols + obj_convert(abfd)[dst.r_symndx];
ptr = *(cache_ptr->sym_ptr_ptr);
- }
+ }
else
- {
- cache_ptr->sym_ptr_ptr= bfd_abs_section.symbol_ptr_ptr;
- ptr = 0;
-
- }
+ {
+ cache_ptr->sym_ptr_ptr= bfd_abs_section.symbol_ptr_ptr;
+ ptr = 0;
+ }
/*
The symbols definitions that we have read in have been
}
static bfd_byte *
-DEFUN(bfd_coff_get_relocated_section_contents,(in_abfd, seclet),
+DEFUN(bfd_coff_get_relocated_section_contents,(in_abfd, seclet, data),
bfd *in_abfd AND
- bfd_seclet_type *seclet)
+ bfd_seclet_type *seclet AND
+ bfd_byte *data)
{
/* Get enough memory to hold the stuff */
bfd *input_bfd = seclet->u.indirect.section->owner;
asection *input_section = seclet->u.indirect.section;
- bfd_byte *data = (bfd_byte *)malloc(input_section->_raw_size);
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
input_section);
arelent **reloc_vector = (arelent **)bfd_xmalloc(reloc_size);
. arelent *reloc_entry,
. struct symbol_cache_entry *symbol,
. PTR data,
-. asection *input_section));
+. asection *input_section,
+. bfd *output_bfd ));
.
. {* The textual name of the relocation type. *}
. char *name;
flag = bfd_reloc_undefined;
}
- if (howto->special_function){
+ if (howto->special_function) {
bfd_reloc_status_type cont;
cont = howto->special_function(abfd,
reloc_entry,
symbol,
data,
- input_section);
+ input_section,
+ output_bfd);
if (cont != bfd_reloc_continue) return cont;
}
. moment probably a 32 bit wide abs address, but the cpu can
. choose. *}
.
-. BFD_RELOC_CTOR
+. BFD_RELOC_CTOR,
+.
+. {* 32 bits wide, simple reloc *}
+. BFD_RELOC_32,
+. {* 32 bits, PC-relative *}
+. BFD_RELOC_32_PCREL,
+.
+. {* High 22 bits of 32-bit value; simple reloc. *}
+. BFD_RELOC_HI22,
+. {* Low 10 bits. *}
+. BFD_RELOC_LO10,
+.
+. {* Reloc types used for i960/b.out. *}
+. BFD_RELOC_24_PCREL,
+. BFD_RELOC_I960_CALLJ,
+.
+. BFD_RELOC_16_PCREL,
+. {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
+. word displacement, e.g. for SPARC) *}
+. BFD_RELOC_32_PCREL_S2,
+.
+. {* now for the sparc/elf codes *}
+. BFD_RELOC_NONE, {* actually used *}
+. BFD_RELOC_SPARC_WDISP22,
+. BFD_RELOC_SPARC22,
+. BFD_RELOC_SPARC13,
+. BFD_RELOC_SPARC_BASE13,
+. BFD_RELOC_SPARC_GOT10,
+. BFD_RELOC_SPARC_GOT13,
+. BFD_RELOC_SPARC_GOT22,
+. BFD_RELOC_SPARC_PC10,
+. BFD_RELOC_SPARC_PC22,
+. BFD_RELOC_SPARC_WPLT30,
+. BFD_RELOC_SPARC_COPY,
+. BFD_RELOC_SPARC_GLOB_DAT,
+. BFD_RELOC_SPARC_JMP_SLOT,
+. BFD_RELOC_SPARC_RELATIVE,
+. BFD_RELOC_SPARC_UA32,
+.
+. {* this one is a.out specific? *}
+. BFD_RELOC_SPARC_BASE22,
+.
+. {* this must be the highest numeric value *}
+. BFD_RELOC_UNUSED
. } bfd_reloc_code_real_type;
*/
SYNOPSIS
CONST struct reloc_howto_struct *
- bfd_reloc_type_lookup
- (CONST bfd_arch_info_type *arch, bfd_reloc_code_type code);
+ bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_type code);
DESCRIPTION
This routine returns a pointer to a howto struct which when
CONST struct reloc_howto_struct *
DEFUN(bfd_reloc_type_lookup,(arch, code),
- CONST bfd_arch_info_type *arch AND
- bfd_reloc_code_type code)
+ bfd *abfd AND
+ bfd_reloc_code_type code)
{
- return arch->reloc_type_lookup(arch, code);
+ return BFD_SEND (abfd, reloc_type_lookup, (abfd, code));
}
static reloc_howto_type bfd_howto_32 =
DESCRIPTION
Provides default handling for relaxing for back ends which
- don't do relaxing - ie does nothing
+ don't do relaxing -- i.e., does nothing.
*/
boolean
SYNOPSIS
bfd_byte *
bfd_generic_get_relocated_section_contents(bfd *abfd,
- struct bfd_seclet_struct *seclet)
+ struct bfd_seclet_struct *seclet,
+ bfd_byte *data)
DESCRIPTION
Provides default handling of relocation effort for back ends
*/
bfd_byte *
-DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet),
+DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet, data),
bfd *abfd AND
- struct bfd_seclet_struct *seclet)
+ struct bfd_seclet_struct *seclet AND
+ bfd_byte *data)
{
extern bfd_error_vector_type bfd_error_vector;
bfd *input_bfd = seclet->u.indirect.section->owner;
asection *input_section = seclet->u.indirect.section;
- bfd_byte *data = (bfd_byte *) bfd_xmalloc(input_section->_raw_size);
+
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
input_section);
- arelent **reloc_vector = (arelent **) bfd_xmalloc(reloc_size);
+ arelent **reloc_vector = (arelent **) alloca(reloc_size);
/* read in the section */
bfd_get_section_contents(input_bfd,
}
}
- free((char *)reloc_vector);
+
return data;