aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1996-03-29 06:56:02 +0000
committerJeff Law <law@redhat.com>1996-03-29 06:56:02 +0000
commit39f27966436499da318f99c3ad922a2ba2d9208b (patch)
tree62ed70815ab57538301fa7613b4adf03655ae7e7
parent3197da91f90da028652216b219de00c81eeb0914 (diff)
downloadgdb-39f27966436499da318f99c3ad922a2ba2d9208b.zip
gdb-39f27966436499da318f99c3ad922a2ba2d9208b.tar.gz
gdb-39f27966436499da318f99c3ad922a2ba2d9208b.tar.bz2
* 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.
-rw-r--r--bfd/coff-h8300.c445
-rw-r--r--bfd/coffcode.h2
-rw-r--r--bfd/libbfd-in.h17
-rw-r--r--bfd/libbfd.h10
-rw-r--r--bfd/linker.c153
5 files changed, 583 insertions, 44 deletions
diff --git a/bfd/coff-h8300.c b/bfd/coff-h8300.c
index 1de570f..dc9385f 100644
--- a/bfd/coff-h8300.c
+++ b/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"
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index e703167..0a7c730 100644
--- a/bfd/coffcode.h
+++ b/bfd/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
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 2a35b5b..310e839 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -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 */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 296a8b7..300f985 100644
--- a/bfd/libbfd.h
+++ b/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
diff --git a/bfd/linker.c b/bfd/linker.c
index d8d9f6b..c359c92 100644
--- a/bfd/linker.c
+++ b/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)));