* libbfd-in.h (generic_link_hash_newfunc): Add declaration.
* libbfd.h: Rebuilt. * linker.c (generic_link_hash_newfunc): No longer static. * coffcode.h (coff_bfd_link_hash_create): Allow specific targets to override. * coff-h8300.c: Add two derived hash tables and their associated funtions and #defines for use by the h8300 linker. (h8300_reloc16_extra_cases, case R_MEM_INDIRECT): Create entries in the function vector as needed. Place the address of the function vector entry in the location specified by the R_MEM_INDIRECT reloc. Rewrite the vectors section contents as necessary. (h8300_bfd_link_add_symbols): New function for the h8300 linker. (coff_bfd_link_add_symbols): Define to use h8300 specific version. (coff_bfd_link_hash_table_create): Likewise. Linker changes for function vectors. HMSE.
This commit is contained in:
parent
3197da91f9
commit
39f2796643
445
bfd/coff-h8300.c
445
bfd/coff-h8300.c
|
@ -30,6 +30,166 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
||||
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
|
||||
|
||||
/* We derive a hash table from the basic BFD hash table to
|
||||
hold entries in the function vector. Aside from the
|
||||
info stored by the basic hash table, we need the offset
|
||||
of a particular entry within the hash table as well as
|
||||
the offset where we'll add the next entry. */
|
||||
|
||||
struct funcvec_hash_entry
|
||||
{
|
||||
/* The basic hash table entry. */
|
||||
struct bfd_hash_entry root;
|
||||
|
||||
/* The offset within the vectors section where
|
||||
this entry lives. */
|
||||
bfd_vma offset;
|
||||
};
|
||||
|
||||
struct funcvec_hash_table
|
||||
{
|
||||
/* The basic hash table. */
|
||||
struct bfd_hash_table root;
|
||||
|
||||
bfd *abfd;
|
||||
|
||||
/* Offset at which we'll add the next entry. */
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
static struct bfd_hash_entry *
|
||||
funcvec_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
|
||||
|
||||
static boolean
|
||||
funcvec_hash_table_init
|
||||
PARAMS ((struct funcvec_hash_table *, bfd *,
|
||||
struct bfd_hash_entry *(*) PARAMS ((struct bfd_hash_entry *,
|
||||
struct bfd_hash_table *,
|
||||
const char *))));
|
||||
|
||||
/* To lookup a value in the function vector hash table. */
|
||||
#define funcvec_hash_lookup(table, string, create, copy) \
|
||||
((struct funcvec_hash_entry *) \
|
||||
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
|
||||
|
||||
/* The derived h8300 COFF linker table. Note it's derived from
|
||||
the generic linker hash table, not the COFF backend linker hash
|
||||
table! We use this to attach additional data structures we
|
||||
need while linking on the h8300. */
|
||||
struct h8300_coff_link_hash_table
|
||||
{
|
||||
/* The main hash table. */
|
||||
struct generic_link_hash_table root;
|
||||
|
||||
/* Section for the vectors table. This gets attached to a
|
||||
random input bfd, we keep it here for easy access. */
|
||||
asection *vectors_sec;
|
||||
|
||||
/* Hash table of the functions we need to enter into the function
|
||||
vector. */
|
||||
struct funcvec_hash_table *funcvec_hash_table;
|
||||
};
|
||||
|
||||
static struct bfd_link_hash_table *h8300_coff_link_hash_table_create
|
||||
PARAMS ((bfd *));
|
||||
|
||||
/* Get the H8/300 COFF linker hash table from a link_info structure. */
|
||||
|
||||
#define h8300_coff_hash_table(p) \
|
||||
((struct h8300_coff_link_hash_table *) ((coff_hash_table (p))))
|
||||
|
||||
/* Initialize fields within a funcvec hash table entry. Called whenever
|
||||
a new entry is added to the funcvec hash table. */
|
||||
|
||||
static struct bfd_hash_entry *
|
||||
funcvec_hash_newfunc (entry, gen_table, string)
|
||||
struct bfd_hash_entry *entry;
|
||||
struct bfd_hash_table *gen_table;
|
||||
const char *string;
|
||||
{
|
||||
struct funcvec_hash_entry *ret;
|
||||
struct funcvec_hash_table *table;
|
||||
|
||||
ret = (struct funcvec_hash_entry *) entry;
|
||||
table = (struct funcvec_hash_table *) gen_table;
|
||||
|
||||
/* Allocate the structure if it has not already been allocated by a
|
||||
subclass. */
|
||||
if (ret == NULL)
|
||||
ret = ((struct funcvec_hash_entry *)
|
||||
bfd_hash_allocate (gen_table,
|
||||
sizeof (struct funcvec_hash_entry)));
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Call the allocation method of the superclass. */
|
||||
ret = ((struct funcvec_hash_entry *)
|
||||
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, gen_table, string));
|
||||
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Note where this entry will reside in the function vector table. */
|
||||
ret->offset = table->offset;
|
||||
|
||||
/* Bump the offset at which we store entries in the function
|
||||
vector. We'd like to bump up the size of the vectors section,
|
||||
but it's not easily available here. */
|
||||
if (bfd_get_mach (table->abfd) == bfd_mach_h8300)
|
||||
table->offset += 2;
|
||||
else if (bfd_get_mach (table->abfd) == bfd_mach_h8300h)
|
||||
table->offset += 4;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
/* Everything went OK. */
|
||||
return (struct bfd_hash_entry *) ret;
|
||||
}
|
||||
|
||||
/* Initialize the function vector hash table. */
|
||||
|
||||
static boolean
|
||||
funcvec_hash_table_init (table, abfd, newfunc)
|
||||
struct funcvec_hash_table *table;
|
||||
bfd *abfd;
|
||||
struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
|
||||
struct bfd_hash_table *,
|
||||
const char *));
|
||||
{
|
||||
/* Initialize our local fields, then call the generic initialization
|
||||
routine. */
|
||||
table->offset = 0;
|
||||
table->abfd = abfd;
|
||||
return (bfd_hash_table_init (&table->root, newfunc));
|
||||
}
|
||||
|
||||
/* Create the derived linker hash table. We use a derived hash table
|
||||
basically to hold "static" information during an h8/300 coff link
|
||||
without using static variables. */
|
||||
|
||||
static struct bfd_link_hash_table *
|
||||
h8300_coff_link_hash_table_create (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct h8300_coff_link_hash_table *ret;
|
||||
ret = ((struct h8300_coff_link_hash_table *)
|
||||
bfd_alloc (abfd, sizeof (struct h8300_coff_link_hash_table)));
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
if (!_bfd_link_hash_table_init (&ret->root.root, abfd, generic_link_hash_newfunc))
|
||||
{
|
||||
bfd_release (abfd, ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize our data. */
|
||||
ret->vectors_sec = NULL;
|
||||
ret->funcvec_hash_table = NULL;
|
||||
|
||||
/* OK. Everything's intialized, return the base pointer. */
|
||||
return &ret->root.root;
|
||||
}
|
||||
|
||||
/* special handling for H8/300 relocs.
|
||||
We only come here for pcrel stuff and return normally if not an -r link.
|
||||
|
@ -333,6 +493,7 @@ h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
|
|||
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
|
||||
dst_ptr)
|
||||
|
@ -397,7 +558,6 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
|
|||
break;
|
||||
}
|
||||
|
||||
case R_MEM_INDIRECT: /* Temporary */
|
||||
case R_RELBYTE:
|
||||
{
|
||||
unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
|
@ -582,19 +742,300 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
|
|||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
/* An 8bit memory indirect instruction (jmp/jsr).
|
||||
|
||||
There's several things that need to be done to handle
|
||||
this relocation.
|
||||
|
||||
If this is a reloc against the absolute symbol, then
|
||||
we should handle it just R_RELBYTE. Likewise if it's
|
||||
for a symbol with a value ge 0 and le 0xff.
|
||||
|
||||
Otherwise it's a jump/call through the function vector,
|
||||
and the linker is expected to set up the function vector
|
||||
and put the right value into the jump/call instruction. */
|
||||
case R_MEM_INDIRECT:
|
||||
{
|
||||
/* We need to find the symbol so we can determine it's
|
||||
address in the function vector table. */
|
||||
asymbol *symbol;
|
||||
bfd_vma value;
|
||||
char *name;
|
||||
struct funcvec_hash_entry *h;
|
||||
asection *vectors_sec = h8300_coff_hash_table (link_info)->vectors_sec;
|
||||
|
||||
/* First see if this is a reloc against the absolute symbol
|
||||
or against a symbol with a nonnegative value <= 0xff. */
|
||||
symbol = *(reloc->sym_ptr_ptr);
|
||||
value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
|
||||
if (symbol == bfd_abs_section_ptr->symbol
|
||||
|| (value >= 0 && value <= 0xff))
|
||||
{
|
||||
/* This should be handled in a manner very similar to
|
||||
R_RELBYTES. If the value is in range, then just slam
|
||||
the value into the right location. Else trigger a
|
||||
reloc overflow callback. */
|
||||
if (value >= 0 && value <= 0xff)
|
||||
{
|
||||
bfd_put_8 (abfd, value, data + dst_address);
|
||||
dst_address += 1;
|
||||
src_address += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! ((*link_info->callbacks->reloc_overflow)
|
||||
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
|
||||
reloc->howto->name, reloc->addend, input_section->owner,
|
||||
input_section, reloc->address)))
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is a jump/call through a function vector, and we're
|
||||
expected to create the function vector ourselves.
|
||||
|
||||
First look up this symbol in the linker hash table -- we need
|
||||
the derived linker symbol which holds this symbol's index
|
||||
in the function vector. */
|
||||
name = symbol->name;
|
||||
if (symbol->flags & BSF_LOCAL)
|
||||
{
|
||||
char *new_name = bfd_malloc (strlen (name) + 9);
|
||||
if (new_name == NULL)
|
||||
abort ();
|
||||
|
||||
strcpy (new_name, name);
|
||||
sprintf (new_name + strlen (name), "_%08x",
|
||||
(int)symbol->section);
|
||||
name = new_name;
|
||||
}
|
||||
|
||||
h = funcvec_hash_lookup (h8300_coff_hash_table (link_info)->funcvec_hash_table,
|
||||
name, false, false);
|
||||
|
||||
/* This shouldn't ever happen. If it does that means we've got
|
||||
data corruption of some kind. Aborting seems like a reasonable
|
||||
think to do here. */
|
||||
if (h == NULL || vectors_sec == NULL)
|
||||
abort ();
|
||||
|
||||
/* Place the address of the function vector entry into the
|
||||
reloc's address. */
|
||||
bfd_put_8 (abfd,
|
||||
vectors_sec->output_offset + h->offset,
|
||||
data + dst_address);
|
||||
|
||||
dst_address++;
|
||||
src_address++;
|
||||
|
||||
/* Now create an entry in the function vector itself. */
|
||||
if (bfd_get_mach (input_section->owner) == bfd_mach_h8300)
|
||||
bfd_put_16 (abfd,
|
||||
bfd_coff_reloc16_get_value (reloc,
|
||||
link_info,
|
||||
input_section),
|
||||
vectors_sec->contents + h->offset);
|
||||
else if (bfd_get_mach (input_section->owner) == bfd_mach_h8300h)
|
||||
bfd_put_32 (abfd,
|
||||
bfd_coff_reloc16_get_value (reloc,
|
||||
link_info,
|
||||
input_section),
|
||||
vectors_sec->contents + h->offset);
|
||||
else
|
||||
abort ();
|
||||
|
||||
/* Gross. We've already written the contents of the vector section
|
||||
before we get here... So we write it again with the new data. */
|
||||
bfd_set_section_contents (vectors_sec->output_section->owner,
|
||||
vectors_sec->output_section,
|
||||
vectors_sec->contents,
|
||||
vectors_sec->output_offset,
|
||||
vectors_sec->_raw_size);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
*src_ptr = src_address;
|
||||
*dst_ptr = dst_address;
|
||||
}
|
||||
|
||||
|
||||
/* Routine for the h8300 linker.
|
||||
|
||||
This routine is necessary to handle the special R_MEM_INDIRECT
|
||||
relocs on the h8300. It's responsible for generating a vectors
|
||||
section and attaching it to an input bfd as well as sizing
|
||||
the vectors section. It also creates our vectors hash table.
|
||||
|
||||
It uses the generic linker routines to actually add the symbols.
|
||||
from this BFD to the bfd linker hash table. It may add a few
|
||||
selected static symbols to the bfd linker hash table. */
|
||||
|
||||
static boolean
|
||||
h8300_bfd_link_add_symbols(abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
asection *sec;
|
||||
struct funcvec_hash_table *funcvec_hash_table;
|
||||
|
||||
/* If we haven't created a vectors section, do so now. */
|
||||
if (!h8300_coff_hash_table (info)->vectors_sec)
|
||||
{
|
||||
flagword flags;
|
||||
|
||||
/* Make sure the appropriate flags are set, including SEC_IN_MEMORY. */
|
||||
flags = (SEC_ALLOC | SEC_LOAD
|
||||
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY);
|
||||
h8300_coff_hash_table (info)->vectors_sec = bfd_make_section (abfd,
|
||||
".vectors");
|
||||
|
||||
/* If the section wasn't created, or we couldn't set the flags,
|
||||
quit quickly now, rather than dieing a painful death later. */
|
||||
if (! h8300_coff_hash_table (info)->vectors_sec
|
||||
|| ! bfd_set_section_flags (abfd,
|
||||
h8300_coff_hash_table(info)->vectors_sec,
|
||||
flags))
|
||||
return false;
|
||||
|
||||
/* Also create the vector hash table. */
|
||||
funcvec_hash_table = ((struct funcvec_hash_table *)
|
||||
bfd_alloc (abfd, sizeof (struct funcvec_hash_table)));
|
||||
|
||||
if (!funcvec_hash_table)
|
||||
return false;
|
||||
|
||||
/* And initialize the funcvec hash table. */
|
||||
if (!funcvec_hash_table_init (funcvec_hash_table, abfd,
|
||||
funcvec_hash_newfunc))
|
||||
{
|
||||
bfd_release (abfd, funcvec_hash_table);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Store away a pointer to the funcvec hash table. */
|
||||
h8300_coff_hash_table (info)->funcvec_hash_table = funcvec_hash_table;
|
||||
}
|
||||
|
||||
/* Load up the function vector hash table. */
|
||||
funcvec_hash_table = h8300_coff_hash_table (info)->funcvec_hash_table;
|
||||
|
||||
/* Add the symbols using the generic code. */
|
||||
_bfd_generic_link_add_symbols (abfd, info);
|
||||
|
||||
/* Now scan the relocs for all the sections in this bfd; create
|
||||
additional space in the .vectors section as needed. */
|
||||
for (sec = abfd->sections; sec; sec = sec->next)
|
||||
{
|
||||
unsigned long reloc_size, reloc_count, i;
|
||||
asymbol **symbols;
|
||||
arelent **relocs;
|
||||
|
||||
/* Suck in the relocs, symbols & canonicalize them. */
|
||||
reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
|
||||
if (reloc_size <= 0)
|
||||
continue;
|
||||
|
||||
relocs = (arelent **)bfd_malloc ((size_t)reloc_size);
|
||||
if (!relocs)
|
||||
return false;
|
||||
|
||||
/* The symbols should have been read in by _bfd_generic link_add_symbols
|
||||
call abovec, so we can cheat and use the pointer to them that was
|
||||
saved in the above call. */
|
||||
symbols = _bfd_generic_link_get_symbols(abfd);
|
||||
reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, symbols);
|
||||
|
||||
/* Now walk through all the relocations in this section. */
|
||||
for (i = 0; i < reloc_count; i++)
|
||||
{
|
||||
arelent *reloc = relocs[i];
|
||||
asymbol *symbol = *(reloc->sym_ptr_ptr);
|
||||
char *name;
|
||||
|
||||
/* We've got an indirect reloc. See if we need to add it
|
||||
to the function vector table. At this point, we have
|
||||
to add a new entry for each unique symbol referenced
|
||||
by an R_MEM_INDIRECT relocation except for a reloc
|
||||
against the absolute section symbol. */
|
||||
if (reloc->howto->type == R_MEM_INDIRECT
|
||||
&& symbol != bfd_abs_section_ptr->symbol)
|
||||
|
||||
{
|
||||
struct funcvec_hash_entry *h;
|
||||
|
||||
name = symbol->name;
|
||||
if (symbol->flags & BSF_LOCAL)
|
||||
{
|
||||
char *new_name = bfd_malloc (strlen (name) + 9);
|
||||
|
||||
if (new_name == NULL)
|
||||
abort ();
|
||||
|
||||
strcpy (new_name, name);
|
||||
sprintf (new_name + strlen (name), "_%08x",
|
||||
(int)symbol->section);
|
||||
name = new_name;
|
||||
}
|
||||
|
||||
/* Look this symbol up in the function vector hash table. */
|
||||
h = funcvec_hash_lookup (h8300_coff_hash_table (info)->funcvec_hash_table,
|
||||
name, false, false);
|
||||
|
||||
|
||||
/* If this symbol isn't already in the hash table, add
|
||||
it and bump up the size of the hash table. */
|
||||
if (h == NULL)
|
||||
{
|
||||
h = funcvec_hash_lookup (h8300_coff_hash_table (info)->funcvec_hash_table,
|
||||
name, true, true);
|
||||
if (h == NULL)
|
||||
{
|
||||
free (relocs);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Bump the size of the vectors section. Each vector
|
||||
takes 2 bytes on the h8300 and 4 bytes on the h8300h. */
|
||||
if (bfd_get_mach (abfd) == bfd_mach_h8300)
|
||||
h8300_coff_hash_table (info)->vectors_sec->_raw_size += 2;
|
||||
else if (bfd_get_mach (abfd) == bfd_mach_h8300h)
|
||||
h8300_coff_hash_table (info)->vectors_sec->_raw_size += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We're done with the relocations, release them. */
|
||||
free (relocs);
|
||||
}
|
||||
|
||||
/* Now actually allocate some space for the function vector. It's
|
||||
wasteful to do this more than once, but this is easier. */
|
||||
if (h8300_coff_hash_table (info)->vectors_sec->_raw_size != 0)
|
||||
{
|
||||
/* Free the old contents. */
|
||||
if (h8300_coff_hash_table (info)->vectors_sec->contents)
|
||||
free (h8300_coff_hash_table (info)->vectors_sec->contents);
|
||||
|
||||
/* Allocate new contents. */
|
||||
h8300_coff_hash_table (info)->vectors_sec->contents
|
||||
= bfd_malloc (h8300_coff_hash_table (info)->vectors_sec->_raw_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define coff_reloc16_extra_cases h8300_reloc16_extra_cases
|
||||
#define coff_reloc16_estimate h8300_reloc16_estimate
|
||||
#define coff_bfd_link_add_symbols h8300_bfd_link_add_symbols
|
||||
#define coff_bfd_link_hash_table_create h8300_coff_link_hash_table_create
|
||||
|
||||
#define COFF_LONG_FILENAMES
|
||||
#include "coffcode.h"
|
||||
|
|
|
@ -3530,7 +3530,9 @@ dummy_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
|
|||
#endif
|
||||
#else /* ! defined (coff_relocate_section) */
|
||||
#define coff_relocate_section NULL
|
||||
#ifndef coff_bfd_link_hash_table_create
|
||||
#define coff_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
|
||||
#endif
|
||||
#ifndef coff_bfd_link_add_symbols
|
||||
#define coff_bfd_link_add_symbols _bfd_generic_link_add_symbols
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* libbfd.h -- Declarations used by bfd library *implementation*.
|
||||
(This include file is not for users of the library.)
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
Written by Cygnus Support.
|
||||
|
||||
** NOTE: libbfd.h is a GENERATED file. Don't change it; instead,
|
||||
|
@ -347,6 +347,11 @@ extern long _bfd_generic_read_minisymbols
|
|||
extern asymbol *_bfd_generic_minisymbol_to_symbol
|
||||
PARAMS ((bfd *, boolean, const PTR, asymbol *));
|
||||
|
||||
/* Find the nearest line using .stab/.stabstr sections. */
|
||||
extern boolean _bfd_stab_section_find_nearest_line
|
||||
PARAMS ((bfd *, asymbol **, asection *, bfd_vma, boolean *, const char **,
|
||||
const char **, unsigned int *, PTR *));
|
||||
|
||||
/* A routine to create entries for a bfd_link_hash_table. */
|
||||
extern struct bfd_hash_entry *_bfd_link_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *entry,
|
||||
|
@ -364,6 +369,11 @@ extern boolean _bfd_link_hash_table_init
|
|||
extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
|
||||
PARAMS ((bfd *));
|
||||
|
||||
/* Generic link hash table entry creation routine. */
|
||||
struct bfd_hash_entry *generic_link_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
|
||||
const char *));
|
||||
|
||||
/* Generic add symbol routine. */
|
||||
extern boolean _bfd_generic_link_add_symbols
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
@ -379,6 +389,8 @@ extern boolean _bfd_generic_link_add_archive_symbols
|
|||
PARAMS ((bfd *, struct bfd_link_info *,
|
||||
boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *)));
|
||||
|
||||
|
||||
|
||||
/* Forward declaration to avoid prototype errors. */
|
||||
typedef struct bfd_link_hash_entry _bfd_link_hash_entry;
|
||||
|
||||
|
@ -491,5 +503,8 @@ extern boolean _bfd_ecoff_get_accumulated_pdr PARAMS ((PTR, bfd_byte *));
|
|||
extern boolean _bfd_ecoff_get_accumulated_sym PARAMS ((PTR, bfd_byte *));
|
||||
extern boolean _bfd_ecoff_get_accumulated_ss PARAMS ((PTR, bfd_byte *));
|
||||
|
||||
extern bfd_vma _bfd_get_gp_value PARAMS ((bfd *));
|
||||
extern void _bfd_set_gp_value PARAMS ((bfd *, bfd_vma));
|
||||
|
||||
/* And more follows */
|
||||
|
||||
|
|
10
bfd/libbfd.h
10
bfd/libbfd.h
|
@ -369,6 +369,11 @@ extern boolean _bfd_link_hash_table_init
|
|||
extern struct bfd_link_hash_table *_bfd_generic_link_hash_table_create
|
||||
PARAMS ((bfd *));
|
||||
|
||||
/* Generic link hash table entry creation routine. */
|
||||
struct bfd_hash_entry *generic_link_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
|
||||
const char *));
|
||||
|
||||
/* Generic add symbol routine. */
|
||||
extern boolean _bfd_generic_link_add_symbols
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
@ -384,6 +389,8 @@ extern boolean _bfd_generic_link_add_archive_symbols
|
|||
PARAMS ((bfd *, struct bfd_link_info *,
|
||||
boolean (*checkfn) (bfd *, struct bfd_link_info *, boolean *)));
|
||||
|
||||
|
||||
|
||||
/* Forward declaration to avoid prototype errors. */
|
||||
typedef struct bfd_link_hash_entry _bfd_link_hash_entry;
|
||||
|
||||
|
@ -496,6 +503,9 @@ extern boolean _bfd_ecoff_get_accumulated_pdr PARAMS ((PTR, bfd_byte *));
|
|||
extern boolean _bfd_ecoff_get_accumulated_sym PARAMS ((PTR, bfd_byte *));
|
||||
extern boolean _bfd_ecoff_get_accumulated_ss PARAMS ((PTR, bfd_byte *));
|
||||
|
||||
extern bfd_vma _bfd_get_gp_value PARAMS ((bfd *));
|
||||
extern void _bfd_set_gp_value PARAMS ((bfd *, bfd_vma));
|
||||
|
||||
/* And more follows */
|
||||
|
||||
void
|
||||
|
|
153
bfd/linker.c
153
bfd/linker.c
|
@ -406,9 +406,6 @@ SUBSUBSECTION
|
|||
file at the end of <<NAME(aout,final_link)>>.
|
||||
*/
|
||||
|
||||
static struct bfd_hash_entry *generic_link_hash_newfunc
|
||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
|
||||
const char *));
|
||||
static boolean generic_link_read_symbols
|
||||
PARAMS ((bfd *));
|
||||
static boolean generic_link_add_symbols
|
||||
|
@ -516,6 +513,88 @@ bfd_link_hash_lookup (table, string, create, copy, follow)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Look up a symbol in the main linker hash table if the symbol might
|
||||
be wrapped. This should only be used for references to an
|
||||
undefined symbol, not for definitions of a symbol. */
|
||||
|
||||
struct bfd_link_hash_entry *
|
||||
bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
const char *string;
|
||||
boolean create;
|
||||
boolean copy;
|
||||
boolean follow;
|
||||
{
|
||||
if (info->wrap_hash != NULL)
|
||||
{
|
||||
const char *l;
|
||||
|
||||
l = string;
|
||||
if (*l == bfd_get_symbol_leading_char (abfd))
|
||||
++l;
|
||||
|
||||
#undef WRAP
|
||||
#define WRAP "__wrap_"
|
||||
|
||||
if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL)
|
||||
{
|
||||
char *n;
|
||||
struct bfd_link_hash_entry *h;
|
||||
|
||||
/* This symbol is being wrapped. We want to replace all
|
||||
references to SYM with references to __wrap_SYM. */
|
||||
|
||||
n = (char *) bfd_malloc (strlen (l) + sizeof WRAP + 1);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Note that symbol_leading_char may be '\0'. */
|
||||
n[0] = bfd_get_symbol_leading_char (abfd);
|
||||
n[1] = '\0';
|
||||
strcat (n, WRAP);
|
||||
strcat (n, l);
|
||||
h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
|
||||
free (n);
|
||||
return h;
|
||||
}
|
||||
|
||||
#undef WRAP
|
||||
|
||||
#undef REAL
|
||||
#define REAL "__real_"
|
||||
|
||||
if (*l == '_'
|
||||
&& strncmp (l, REAL, sizeof REAL - 1) == 0
|
||||
&& bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1,
|
||||
false, false) != NULL)
|
||||
{
|
||||
char *n;
|
||||
struct bfd_link_hash_entry *h;
|
||||
|
||||
/* This is a reference to __real_SYM, where SYM is being
|
||||
wrapped. We want to replace all references to __real_SYM
|
||||
with references to SYM. */
|
||||
|
||||
n = (char *) bfd_malloc (strlen (l + sizeof REAL - 1) + 2);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Note that symbol_leading_char may be '\0'. */
|
||||
n[0] = bfd_get_symbol_leading_char (abfd);
|
||||
n[1] = '\0';
|
||||
strcat (n, l + sizeof REAL - 1);
|
||||
h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
|
||||
free (n);
|
||||
return h;
|
||||
}
|
||||
|
||||
#undef REAL
|
||||
}
|
||||
|
||||
return bfd_link_hash_lookup (info->hash, string, create, copy, follow);
|
||||
}
|
||||
|
||||
/* Traverse a generic link hash table. The only reason this is not a
|
||||
macro is to do better type checking. This code presumes that an
|
||||
argument passed as a struct bfd_hash_entry * may be caught as a
|
||||
|
@ -551,7 +630,7 @@ bfd_link_add_undef (table, h)
|
|||
|
||||
/* Routine to create an entry in an generic link hash table. */
|
||||
|
||||
static struct bfd_hash_entry *
|
||||
struct bfd_hash_entry *
|
||||
generic_link_hash_newfunc (entry, table, string)
|
||||
struct bfd_hash_entry *entry;
|
||||
struct bfd_hash_table *table;
|
||||
|
@ -1427,13 +1506,13 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
|
|||
row = DEF_ROW;
|
||||
|
||||
if (hashp != NULL && *hashp != NULL)
|
||||
{
|
||||
h = *hashp;
|
||||
BFD_ASSERT (strcmp (h->root.string, name) == 0);
|
||||
}
|
||||
h = *hashp;
|
||||
else
|
||||
{
|
||||
h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
|
||||
if (row == UNDEF_ROW || row == UNDEFW_ROW)
|
||||
h = bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false);
|
||||
else
|
||||
h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
|
||||
if (h == NULL)
|
||||
{
|
||||
if (hashp != NULL)
|
||||
|
@ -1716,8 +1795,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
|
|||
|
||||
/* STRING is the name of the symbol we want to indirect
|
||||
to. */
|
||||
inh = bfd_link_hash_lookup (info->hash, string, true, copy,
|
||||
false);
|
||||
inh = bfd_wrapped_link_hash_lookup (abfd, info, string, true,
|
||||
copy, false);
|
||||
if (inh == (struct bfd_link_hash_entry *) NULL)
|
||||
return false;
|
||||
if (inh->type == bfd_link_hash_new)
|
||||
|
@ -1901,12 +1980,9 @@ _bfd_generic_final_link (abfd, info)
|
|||
input_section);
|
||||
if (relsize < 0)
|
||||
return false;
|
||||
relocs = (arelent **) malloc ((size_t) relsize);
|
||||
relocs = (arelent **) bfd_malloc ((size_t) relsize);
|
||||
if (!relocs && relsize != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
symbols = _bfd_generic_link_get_symbols (input_bfd);
|
||||
reloc_count = bfd_canonicalize_reloc (input_bfd,
|
||||
input_section,
|
||||
|
@ -1983,16 +2059,10 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
|
|||
*psymalloc = 124;
|
||||
else
|
||||
*psymalloc *= 2;
|
||||
if (output_bfd->outsymbols == (asymbol **) NULL)
|
||||
newsyms = (asymbol **) malloc (*psymalloc * sizeof (asymbol *));
|
||||
else
|
||||
newsyms = (asymbol **) realloc (output_bfd->outsymbols,
|
||||
*psymalloc * sizeof (asymbol *));
|
||||
newsyms = (asymbol **) bfd_realloc (output_bfd->outsymbols,
|
||||
*psymalloc * sizeof (asymbol *));
|
||||
if (newsyms == (asymbol **) NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
output_bfd->outsymbols = newsyms;
|
||||
}
|
||||
|
||||
|
@ -2082,6 +2152,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
|
|||
the relocs in the output format being used. */
|
||||
h = NULL;
|
||||
}
|
||||
else if (bfd_is_und_section (bfd_get_section (sym)))
|
||||
h = ((struct generic_link_hash_entry *)
|
||||
bfd_wrapped_link_hash_lookup (output_bfd, info,
|
||||
bfd_asymbol_name (sym),
|
||||
false, false, true));
|
||||
else
|
||||
h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
|
||||
bfd_asymbol_name (sym),
|
||||
|
@ -2311,10 +2386,7 @@ _bfd_generic_link_write_global_symbol (h, data)
|
|||
return true;
|
||||
|
||||
if (h->sym != (asymbol *) NULL)
|
||||
{
|
||||
sym = h->sym;
|
||||
BFD_ASSERT (strcmp (bfd_asymbol_name (sym), h->root.root.string) == 0);
|
||||
}
|
||||
sym = h->sym;
|
||||
else
|
||||
{
|
||||
sym = bfd_make_empty_symbol (wginfo->output_bfd);
|
||||
|
@ -2373,9 +2445,10 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
|
|||
{
|
||||
struct generic_link_hash_entry *h;
|
||||
|
||||
h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
|
||||
h = ((struct generic_link_hash_entry *)
|
||||
bfd_wrapped_link_hash_lookup (abfd, info,
|
||||
link_order->u.reloc.p->u.name,
|
||||
false, false, true);
|
||||
false, false, true));
|
||||
if (h == (struct generic_link_hash_entry *) NULL
|
||||
|| ! h->written)
|
||||
{
|
||||
|
@ -2520,12 +2593,9 @@ default_fill_link_order (abfd, info, sec, link_order)
|
|||
BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0);
|
||||
|
||||
size = (size_t) link_order->size;
|
||||
space = (char *) malloc (size);
|
||||
space = (char *) bfd_malloc (size);
|
||||
if (space == NULL && size != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
fill = link_order->u.fill.value;
|
||||
for (i = 0; i < size; i += 2)
|
||||
|
@ -2618,6 +2688,10 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
|
|||
generic_link_add_symbol_list. */
|
||||
if (sym->udata.p != NULL)
|
||||
h = (struct bfd_link_hash_entry *) sym->udata.p;
|
||||
else if (bfd_is_und_section (bfd_get_section (sym)))
|
||||
h = bfd_wrapped_link_hash_lookup (output_bfd, info,
|
||||
bfd_asymbol_name (sym),
|
||||
false, false, true);
|
||||
else
|
||||
h = bfd_link_hash_lookup (info->hash,
|
||||
bfd_asymbol_name (sym),
|
||||
|
@ -2630,12 +2704,9 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
|
|||
|
||||
/* Get and relocate the section contents. */
|
||||
contents = ((bfd_byte *)
|
||||
malloc ((size_t) bfd_section_size (input_bfd, input_section)));
|
||||
bfd_malloc (bfd_section_size (input_bfd, input_section)));
|
||||
if (contents == NULL && bfd_section_size (input_bfd, input_section) != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
goto error_return;
|
||||
}
|
||||
goto error_return;
|
||||
new_contents = (bfd_get_relocated_section_contents
|
||||
(output_bfd, info, link_order, contents, info->relocateable,
|
||||
_bfd_generic_link_get_symbols (input_bfd)));
|
||||
|
|
Loading…
Reference in New Issue