/* BFD back-end for HP PA-RISC ELF files.
- Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "obstack.h"
-#include "libelf.h"
+#include "elf-bfd.h"
+/* The internal type of a symbol table extension entry. */
+typedef unsigned long symext_entryS;
+
+/* The external type of a symbol table extension entry. */
+#define ELF32_PARISC_SX_SIZE (4)
+#define ELF32_PARISC_SX_GET(bfd, addr) bfd_h_get_32 ((bfd), (addr))
+#define ELF32_PARISC_SX_PUT(bfd, val, addr) \
+ bfd_h_put_32 ((bfd), (val), (addr))
/* HPPA symbol table extension entry types */
enum elf32_hppa_symextn_types
#define SYMEXTN_SECTION_NAME ".PARISC.symext"
-/* FIXME. Are these external? (For example used by GAS?). If so the
- names need to change to avoid namespace pollution, if not they should
- be moved into elf32-hppa.c. */
-typedef unsigned long symext_entryS;
struct symext_chain
{
symext_entryS entry;
int global_sym_defined;
};
-typedef unsigned int symextn_entry;
-
/* FIXME. */
#define ARGUMENTS 0
#define RETURN_VALUE 1
static bfd_reloc_status_type hppa_elf_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd*, char **));
-static CONST reloc_howto_type * elf_hppa_reloc_type_lookup
+static reloc_howto_type * elf_hppa_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static boolean elf32_hppa_set_section_contents
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
static boolean elf32_hppa_backend_symbol_table_processing
- PARAMS ((bfd *, elf_symbol_type *, int));
+ PARAMS ((bfd *, elf_symbol_type *, unsigned int));
static void elf32_hppa_backend_begin_write_processing
PARAMS ((bfd *, struct bfd_link_info *));
const char **, flagword *, asection **, bfd_vma *));
static bfd_reloc_status_type elf32_hppa_bfd_final_link_relocate
- PARAMS ((const reloc_howto_type *, bfd *, bfd *, asection *,
+ PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *,
bfd_byte *, bfd_vma, bfd_vma, bfd_vma, struct bfd_link_info *,
asection *, const char *, int));
static boolean
elf32_hppa_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
- bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **,
- char *));
+ bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
static boolean
elf32_hppa_stub_hash_table_init
static boolean
elf32_hppa_read_symext_info
PARAMS ((bfd *, Elf_Internal_Shdr *, struct elf32_hppa_args_hash_table *,
- Elf_Internal_Sym *, boolean, boolean));
+ Elf_Internal_Sym *));
static unsigned int elf32_hppa_size_of_stub
PARAMS ((unsigned int, unsigned int, bfd_vma, bfd_vma, const char *));
/* Misc static crud for symbol extension records. */
static symext_chainS *symext_rootP;
static symext_chainS *symext_lastP;
-static int symext_chain_size;
+static bfd_size_type symext_chain_size;
/* FIXME: We should be able to try this static variable! */
-static symext_entryS *symextn_contents;
+static bfd_byte *symextn_contents;
/* For linker stub hash tables. */
bfd_hash_allocate (table,
sizeof (struct elf32_hppa_stub_hash_entry)));
if (ret == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
/* Call the allocation method of the superclass. */
ret = ((struct elf32_hppa_stub_hash_entry *)
bfd_hash_allocate (table,
sizeof (struct elf32_hppa_args_hash_entry)));
if (ret == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
/* Call the allocation method of the superclass. */
ret = ((struct elf32_hppa_args_hash_entry *)
ret = ((struct elf32_hppa_link_hash_table *)
bfd_alloc (abfd, sizeof (struct elf32_hppa_link_hash_table)));
if (ret == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
_bfd_elf_link_hash_newfunc))
{
static boolean
elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections,
- output_names)
+ contents, relocs, local_syms, local_sections)
bfd *output_bfd;
struct bfd_link_info *info;
bfd *input_bfd;
Elf_Internal_Rela *relocs;
Elf_Internal_Sym *local_syms;
asection **local_sections;
- char *output_names;
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
for (; rel < relend; rel++)
{
int r_type;
- const reloc_howto_type *howto;
- long r_symndx;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sym_sec;
indx = r_symndx - symtab_hdr->sh_info;
h = elf_sym_hashes (input_bfd)[indx];
- if (h->root.type == bfd_link_hash_defined)
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
{
sym_sec = h->root.u.def.section;
relocation = (h->root.u.def.value
+ sym_sec->output_offset
+ sym_sec->output_section->vma);
}
- else if (h->root.type == bfd_link_hash_weak)
+ else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
else
{
(info, h->root.root.string, input_bfd,
input_section, rel->r_offset)))
return false;
- relocation = 0;
+ break;
}
}
sym_name = h->root.root.string;
else
{
- sym_name = output_names + sym->st_name;
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
if (sym_name == NULL)
return false;
if (*sym_name == '\0')
{
switch (r)
{
+ /* This can happen for DP relative relocs if $global$ is
+ undefined. This is a panic situation so we don't try
+ to continue. */
+ case bfd_reloc_undefined:
+ case bfd_reloc_notsupported:
+ if (!((*info->callbacks->undefined_symbol)
+ (info, "$global$", input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ return false;
case bfd_reloc_dangerous:
{
/* We use this return value to indicate that we performed
relocation with modifications based on format and field. */
elf32_hppa_reloc_type **
-hppa_elf_gen_reloc_type (abfd, base_type, format, field)
+hppa_elf_gen_reloc_type (abfd, base_type, format, field, ignore)
bfd *abfd;
elf32_hppa_reloc_type base_type;
int format;
int field;
+ int ignore;
{
elf32_hppa_reloc_type *finaltype;
elf32_hppa_reloc_type **final_types;
if (!strcmp (section->name, ".PARISC.symextn") && !symext_chain_size)
return true;
else
- return bfd_elf32_set_section_contents (abfd, section, location,
- offset, count);
+ return _bfd_elf_set_section_contents (abfd, section, location,
+ offset, count);
}
/* Translate from an elf into field into a howto relocation pointer. */
elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
input_section, contents, offset, value,
addend, info, sym_sec, sym_name, is_local)
- const reloc_howto_type *howto;
+ reloc_howto_type *howto;
bfd *input_bfd;
bfd *output_bfd;
asection *input_section;
unsigned long r_type = howto->type;
unsigned long r_format = howto->bitsize;
unsigned long r_field = e_fsel;
- bfd_byte *hit_data = contents + offset + input_section->vma;
+ bfd_byte *hit_data = contents + offset;
boolean r_pcrel = howto->pc_relative;
insn = bfd_get_32 (input_bfd, hit_data);
if (h == NULL)
return bfd_reloc_notsupported;
+ /* If $global$ isn't a defined symbol, then we're still in deep
+ trouble. */
+ if (h->root.type != bfd_link_hash_defined)
+ return bfd_reloc_undefined;
+
sec = h->root.u.def.section;
elf32_hppa_hash_table (info)->global_value = (h->root.u.def.value
- + sec->vma
+ + sec->output_section->vma
+ sec->output_offset);
elf32_hppa_hash_table (info)->global_sym_defined = 1;
}
case R_PARISC_DPREL21L:
r_field = e_lrsel;
if (sym_sec->flags & SEC_CODE)
- insn &= ~0x03e00000;
+ {
+ if ((insn & 0xfc000000) >> 26 == 0xa
+ && (insn & 0x03e00000) >> 21 == 0x1b)
+ insn &= ~0x03e00000;
+ }
else
value -= elf32_hppa_hash_table (info)->global_value;
goto do_basic_type_1;
len = strlen (sym_name) + 1;
if (is_local)
len += 9;
- new_name = malloc (len);
+ new_name = bfd_malloc (len);
if (!new_name)
- {
- bfd_set_error (bfd_error_no_memory);
- return bfd_reloc_notsupported;
- }
+ return bfd_reloc_notsupported;
strcpy (new_name, sym_name);
/* Local symbols have unique IDs. */
len = strlen (new_name);
len += 23;
- stub_name = malloc (len);
+ stub_name = bfd_malloc (len);
if (!stub_name)
- {
- bfd_set_error (bfd_error_no_memory);
- return bfd_reloc_notsupported;
- }
+ return bfd_reloc_notsupported;
elf32_hppa_name_of_stub (caller_args, callee_args,
location, value, stub_name);
strcat (stub_name, new_name);
/* Return the address of the howto table entry to perform the CODE
relocation for an ARCH machine. */
-static CONST reloc_howto_type *
+static reloc_howto_type *
elf_hppa_reloc_type_lookup (abfd, code)
bfd *abfd;
bfd_reloc_code_real_type code;
continue;
/* Yup. This function symbol needs an entry. */
- symext_chain_size += 2 * sizeof (symext_entryS);
+ symext_chain_size += 2 * ELF32_PARISC_SX_SIZE;
}
}
else if (info->relocateable == true)
struct bfd_hash_entry *gen_entry;
PTR in_args;
{
- unsigned int *sizep = (unsigned int *)in_args;
+ bfd_size_type *sizep = (bfd_size_type *)in_args;
- *sizep += 2 * sizeof (symext_entryS);
+ *sizep += 2 * ELF32_PARISC_SX_SIZE;
return true;
}
if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
len += 9;
- new_name = malloc (len);
+ new_name = bfd_malloc (len);
if (new_name == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
strcpy (new_name, name);
if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
boolean linker;
{
asection *symextn_sec;
- unsigned int i, *symtab_map = (unsigned int *) elf_sym_extra (abfd);
+ unsigned int i;
/* Now build the symbol extension section. */
if (symext_chain_size == 0)
/* Add this symbol's information to the chain. */
add_entry_to_symext_chain (abfd, symbol->tc_data.hppa_arg_reloc,
- symtab_map[i], &symext_rootP,
+ symbol->symbol.udata.i, &symext_rootP,
&symext_lastP);
}
}
/* Allocate memory and initialize this entry. */
symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
if (!symextP)
- {
- bfd_set_error (bfd_error_no_memory);
- abort(); /* FIXME */
- }
+ abort(); /* FIXME */
symextP[0].entry = ELF32_PARISC_SX_WORD (PARISC_SXT_SYMNDX, sym_idx);
symextP[0].next = &symextP[1];
/* Grab some memory for the contents of the symbol extension section
itself. */
- symextn_contents = (symext_entryS *) bfd_zalloc (abfd,
- symextn_sec->_raw_size);
+ symextn_contents = (bfd_byte *) bfd_zalloc (abfd,
+ symextn_sec->_raw_size);
if (!symextn_contents)
- {
- bfd_set_error (bfd_error_no_memory);
- abort(); /* FIXME */
- }
+ abort(); /* FIXME */
/* Fill in the contents of the symbol extension chain. */
for (i = 0, symextP = symext_root; symextP; symextP = symextP->next, ++i)
- symextn_contents[i] = symextP->entry;
+ ELF32_PARISC_SX_PUT (abfd, (bfd_vma) symextP->entry,
+ symextn_contents + i * ELF32_PARISC_SX_SIZE);
return;
}
elf32_hppa_backend_symbol_table_processing (abfd, esyms,symcnt)
bfd *abfd;
elf_symbol_type *esyms;
- int symcnt;
+ unsigned int symcnt;
{
Elf32_Internal_Shdr *symextn_hdr =
bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
/* Allocate a buffer of the appropriate size for the symextn section. */
symextn_hdr->contents = bfd_zalloc(abfd,symextn_hdr->sh_size);
if (!symextn_hdr->contents)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- symextn_hdr->size = symextn_hdr->sh_size;
+ return false;
/* Read in the symextn section. */
if (bfd_seek (abfd, symextn_hdr->sh_offset, SEEK_SET) == -1)
return false;
- if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->size, abfd)
- != symextn_hdr->size)
+ if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->sh_size, abfd)
+ != symextn_hdr->sh_size)
return false;
/* Parse entries in the symbol extension section, updating the symtab
entries as we go */
- for (i = 0; i < symextn_hdr->size / sizeof(symext_entryS); i++)
+ for (i = 0; i < symextn_hdr->sh_size / ELF32_PARISC_SX_SIZE; i++)
{
- symext_entryS *seP = ((symext_entryS *)symextn_hdr->contents) + i;
- unsigned int se_value = ELF32_PARISC_SX_VAL (*seP);
- unsigned int se_type = ELF32_PARISC_SX_TYPE (*seP);
+ symext_entryS se =
+ ELF32_PARISC_SX_GET (abfd,
+ (symextn_hdr->contents
+ + i * ELF32_PARISC_SX_SIZE));
+ unsigned int se_value = ELF32_PARISC_SX_VAL (se);
+ unsigned int se_type = ELF32_PARISC_SX_TYPE (se);
switch (se_type)
{
if DO_LOCALS is true; likewise for globals when DO_GLOBALS is true. */
static boolean
-elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
- local_syms, do_locals, do_globals)
+elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table, local_syms)
bfd *input_bfd;
Elf_Internal_Shdr *symtab_hdr;
struct elf32_hppa_args_hash_table *args_hash_table;
Elf_Internal_Sym *local_syms;
- boolean do_locals;
- boolean do_globals;
{
asection *symextn_sec;
- symextn_entry *contents;
+ bfd_byte *contents;
unsigned int i, n_entries, current_index = 0;
/* Get the symbol extension section for this BFD. If no section exists
return true;
}
- contents = (symextn_entry *) malloc (symextn_sec->_raw_size);
+ contents = (bfd_byte *) bfd_malloc ((size_t) symextn_sec->_raw_size);
if (contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* How gross. We turn off SEC_HAS_CONTENTS for the input symbol extension
sections to keep the generic ELF/BFD code from trying to do anything
sections (see above). */
symextn_sec->flags &= ~SEC_HAS_CONTENTS;
- n_entries = symextn_sec->_raw_size / sizeof (symextn_entry);
+ n_entries = symextn_sec->_raw_size / ELF32_PARISC_SX_SIZE;
for (i = 0; i < n_entries; i++)
{
- symextn_entry entry = contents[i];
+ symext_entryS entry =
+ ELF32_PARISC_SX_GET (input_bfd, contents + i * ELF32_PARISC_SX_SIZE);
unsigned int value = ELF32_PARISC_SX_VAL (entry);
unsigned int type = ELF32_PARISC_SX_TYPE (entry);
struct elf32_hppa_args_hash_entry *args_hash;
break;
case PARISC_SXT_ARG_RELOC:
- if (current_index < symtab_hdr->sh_info
- && do_locals)
+ if (current_index < symtab_hdr->sh_info)
{
Elf_Internal_Shdr *hdr;
char *new_name;
hdr = elf_elfsections (input_bfd)[local_syms[current_index].st_shndx];
sym_sec = hdr->bfd_section;
- sym_name = elf_string_from_elf_section (input_bfd,
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
local_syms[current_index].st_name);
len = strlen (sym_name) + 10;
- new_name = malloc (len);
+ new_name = bfd_malloc (len);
if (new_name == NULL)
{
- bfd_set_error (bfd_error_no_memory);
free (contents);
return false;
}
args_hash->arg_bits = value;
break;
}
- else if (current_index >= symtab_hdr->sh_info
- && do_globals)
+ else if (current_index >= symtab_hdr->sh_info)
{
struct elf_link_hash_entry *h;
size = bfd_section_size (stub_bfd, stub_sec);
stub_sec->contents = (unsigned char *) bfd_zalloc (stub_bfd, size);
if (stub_sec->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
table = elf32_hppa_hash_table(info)->stub_hash_table;
table->location = stub_sec->contents;
struct bfd_link_info *link_info;
{
bfd *input_bfd;
- asection *section, *stub_sec;
+ asection *section, *stub_sec = 0;
Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Sym *local_syms, *isym;
+ Elf_Internal_Sym *local_syms, *isym, **all_local_syms;
Elf32_External_Sym *ext_syms, *esym;
+ unsigned int i, index, bfd_count = 0;
struct elf32_hppa_stub_hash_table *stub_hash_table = 0;
struct elf32_hppa_args_hash_table *args_hash_table = 0;
/* Create and initialize the stub hash table. */
stub_hash_table = ((struct elf32_hppa_stub_hash_table *)
- malloc (sizeof (struct elf32_hppa_stub_hash_table)));
+ bfd_malloc (sizeof (struct elf32_hppa_stub_hash_table)));
if (!stub_hash_table)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (!elf32_hppa_stub_hash_table_init (stub_hash_table, stub_bfd,
elf32_hppa_stub_hash_newfunc))
/* Likewise for the argument location hash table. */
args_hash_table = ((struct elf32_hppa_args_hash_table *)
- malloc (sizeof (struct elf32_hppa_args_hash_table)));
+ bfd_malloc (sizeof (struct elf32_hppa_args_hash_table)));
if (!args_hash_table)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (!elf32_hppa_args_hash_table_init (args_hash_table,
elf32_hppa_args_hash_newfunc))
elf32_hppa_hash_table(link_info)->stub_hash_table = stub_hash_table;
elf32_hppa_hash_table(link_info)->args_hash_table = args_hash_table;
- /* Walk over all the input BFDs adding entries to the args hash table
- for all the external functions. */
+ /* Count the number of input BFDs. */
for (input_bfd = link_info->input_bfds;
input_bfd != NULL;
input_bfd = input_bfd->link_next)
- {
- /* We'll need the symbol table in a second. */
- symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- if (symtab_hdr->sh_info == 0)
- continue;
-
- if (elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
- NULL, false, true) == false)
- goto error_return;
- }
-
- /* Magic as we know the stub bfd only has one section. */
- stub_sec = stub_bfd->sections;
+ bfd_count++;
+
+ /* We want to read in symbol extension records only once. To do this
+ we need to read in the local symbols in parallel and save them for
+ later use; so hold pointers to the local symbols in an array. */
+ all_local_syms
+ = (Elf_Internal_Sym **) bfd_malloc (sizeof (Elf_Internal_Sym *)
+ * bfd_count);
+ if (all_local_syms == NULL)
+ goto error_return;
+ memset (all_local_syms, 0, sizeof (Elf_Internal_Sym *) * bfd_count);
- /* Now that we have argument location information for all the global
- functions we can start looking for stubs. */
- for (input_bfd = link_info->input_bfds;
+ /* Walk over all the input BFDs adding entries to the args hash table
+ for all the external functions. */
+ for (input_bfd = link_info->input_bfds, index = 0;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link_next, index++)
{
- unsigned int i;
-
/* We'll need the symbol table in a second. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
if (symtab_hdr->sh_info == 0)
/* We need an array of the local symbols attached to the input bfd.
Unfortunately, we're going to have to read & swap them in. */
local_syms
- = (Elf_Internal_Sym *)malloc (symtab_hdr->sh_info
- * sizeof (Elf_Internal_Sym));
+ = (Elf_Internal_Sym *) bfd_malloc (symtab_hdr->sh_info
+ * sizeof (Elf_Internal_Sym));
if (local_syms == NULL)
{
- bfd_set_error (bfd_error_no_memory);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
+ all_local_syms[index] = local_syms;
ext_syms
- = (Elf32_External_Sym *)malloc (symtab_hdr->sh_info
- * sizeof (Elf32_External_Sym));
+ = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_info
+ * sizeof (Elf32_External_Sym));
if (ext_syms == NULL)
{
- bfd_set_error (bfd_error_no_memory);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
* sizeof (Elf32_External_Sym)), input_bfd)
!= (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))
{
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
free (ext_syms);
goto error_return;
}
free (ext_syms);
if (elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
- local_syms, true, false) == false)
+ local_syms) == false)
{
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
+ }
- /* If generating a relocateable output file, then we don't
- have to examine the relocs. */
- if (link_info->relocateable)
- {
- free (local_syms);
- return true;
- }
+ /* Magic as we know the stub bfd only has one section. */
+ stub_sec = stub_bfd->sections;
+
+ /* If generating a relocateable output file, then we don't
+ have to examine the relocs. */
+ if (link_info->relocateable)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ return true;
+ }
+
+ /* Now that we have argument location information for all the global
+ functions we can start looking for stubs. */
+ for (input_bfd = link_info->input_bfds, index = 0;
+ input_bfd != NULL;
+ input_bfd = input_bfd->link_next, index++)
+ {
+ /* We'll need the symbol table in a second. */
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (symtab_hdr->sh_info == 0)
+ continue;
+
+ local_syms = all_local_syms[index];
/* Walk over each section attached to the input bfd. */
for (section = input_bfd->sections;
/* Allocate space for the external relocations. */
external_relocs
- = (Elf32_External_Rela *) malloc (section->reloc_count * sizeof (Elf32_External_Rela));
+ = ((Elf32_External_Rela *)
+ bfd_malloc (section->reloc_count
+ * sizeof (Elf32_External_Rela)));
if (external_relocs == NULL)
{
- bfd_set_error (bfd_error_no_memory);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
/* Likewise for the internal relocations. */
internal_relocs
- = (Elf_Internal_Rela *) malloc (section->reloc_count * sizeof (Elf_Internal_Rela));
+ = ((Elf_Internal_Rela *)
+ bfd_malloc (section->reloc_count * sizeof (Elf_Internal_Rela)));
if (internal_relocs == NULL)
{
- bfd_set_error (bfd_error_no_memory);
free (external_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
{
free (external_relocs);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
irelaend = irela + section->reloc_count;
for (; irela < irelaend; irela++)
{
- long r_type, callee_args, caller_args, r_index, size_of_stub;
+ long r_type, callee_args, caller_args, size_of_stub;
+ unsigned long r_index;
struct elf_link_hash_entry *hash;
struct elf32_hppa_stub_hash_entry *stub_hash;
struct elf32_hppa_args_hash_entry *args_hash;
{
bfd_set_error (bfd_error_bad_value);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
sym = local_syms + r_index;
hdr = elf_elfsections (input_bfd)[sym->st_shndx];
sym_sec = hdr->bfd_section;
- sym_name = elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
sym_value = (ELF_ST_TYPE (sym->st_info) == STT_SECTION
? 0 : sym->st_value);
destination = (sym_value
/* Tack on an ID so we can uniquely identify this local
symbol in the stub or arg info hash tables. */
- new_name = malloc (strlen (sym_name) + 10);
+ new_name = bfd_malloc (strlen (sym_name) + 10);
if (new_name == 0)
{
- bfd_set_error (bfd_error_bad_value);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
index = r_index - symtab_hdr->sh_info;
hash = elf_sym_hashes (input_bfd)[index];
- if (hash->root.type == bfd_link_hash_defined)
+ if (hash->root.type == bfd_link_hash_defined
+ || hash->root.type == bfd_link_hash_defweak)
{
sym_sec = hash->root.u.def.section;
sym_name = hash->root.root.string;
{
bfd_set_error (bfd_error_bad_value);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
}
len = strlen (sym_name);
len += 23;
- stub_name = malloc (len);
+ stub_name = bfd_malloc (len);
if (!stub_name)
{
- bfd_set_error (bfd_error_no_memory);
-
/* Because sym_name was mallocd above for local
symbols. */
if (r_index < symtab_hdr->sh_info)
free (new_name);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
elf32_hppa_name_of_stub (caller_args, callee_args,
stub_name, true, true);
if (stub_hash == NULL)
{
- bfd_set_error (bfd_error_no_memory);
free (stub_name);
free (internal_relocs);
- free (local_syms);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
goto error_return;
}
/* We're done with the internal relocs, free them. */
free (internal_relocs);
}
- /* We're done with the local symbols, free them. */
- free (local_syms);
}
+ /* We're done with the local symbols, free them. */
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
return true;
error_return:
elf32_hppa_hash_table(link_info)->args_hash_table = NULL;
free (args_hash_table);
}
+ /* Set the size of the stub section to zero since we're never going
+ to create them. Avoids losing when we try to get its contents
+ too. */
+ bfd_set_section_size (stub_bfd, stub_sec, 0);
return false;
}