/* AVR-specific support for 32-bit ELF
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
Free Software Foundation, Inc.
Contributed by Denis Chertykov <denisc@overta.ru>
/* Various hash macros and functions. */
#define avr_link_hash_table(p) \
- ((struct elf32_avr_link_hash_table *) ((p)->hash))
+ /* PR 3874: Check that we have an AVR style hash table before using it. */\
+ ((p)->hash->table.newfunc != elf32_avr_link_hash_newfunc ? NULL : \
+ ((struct elf32_avr_link_hash_table *) ((p)->hash)))
#define avr_stub_hash_entry(ent) \
((struct elf32_avr_stub_hash_entry *)(ent))
return entry;
}
+/* This function is just a straight passthrough to the real
+ function in linker.c. Its prupose is so that its address
+ can be compared inside the avr_link_hash_table macro. */
+
+static struct bfd_hash_entry *
+elf32_avr_link_hash_newfunc (struct bfd_hash_entry * entry,
+ struct bfd_hash_table * table,
+ const char * string)
+{
+ return _bfd_elf_link_hash_newfunc (entry, table, string);
+}
+
/* Create the derived linker hash table. The AVR ELF port uses the derived
hash table to keep information specific to the AVR ELF linker (without
using static variables). */
return NULL;
if (!_bfd_elf_link_hash_table_init (&htab->etab, abfd,
- _bfd_elf_link_hash_newfunc,
+ elf32_avr_link_hash_newfunc,
sizeof (struct elf_link_hash_entry)))
{
free (htab);
Elf_Internal_Rela * relend;
struct elf32_avr_link_hash_table * htab = avr_link_hash_table (info);
- if (info->relocatable)
+ if (info == NULL || info->relocatable)
return TRUE;
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
struct elf32_avr_link_hash_table *htab;
htab = avr_link_hash_table (link_info);
+ if (htab == NULL)
+ return FALSE;
/* Assume nothing changes. */
*again = FALSE;
info = (struct bfd_link_info *) in_arg;
htab = avr_link_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
target = hsh->target_value;
bfd_vma pc_wrap_around,
bfd_boolean call_ret_replacement)
{
- struct elf32_avr_link_hash_table *htab = avr_link_hash_table(info);
+ struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);
+ if (htab == NULL)
+ return;
htab->stub_sec = avr_stub_section;
htab->stub_bfd = avr_stub_bfd;
htab->no_stubs = no_stubs;
bfd_size_type amt;
struct elf32_avr_link_hash_table *htab = avr_link_hash_table(info);
- if (htab->no_stubs)
+ if (htab == NULL || htab->no_stubs)
return 0;
/* Count the number of input BFDs and find the top input section id. */
Elf_Internal_Sym *local_syms, **all_local_syms;
struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);
+ if (htab == NULL)
+ return -1;
+
/* 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. */
struct bfd_link_info *info,
bfd_boolean is_prealloc_run)
{
- struct elf32_avr_link_hash_table *htab;
- int stub_changed = 0;
+ struct elf32_avr_link_hash_table *htab;
+ int stub_changed = 0;
- htab = avr_link_hash_table (info);
+ htab = avr_link_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
- /* At this point we initialize htab->vector_base
- To the start of the text output section. */
- htab->vector_base = htab->stub_sec->output_section->vma;
+ /* At this point we initialize htab->vector_base
+ To the start of the text output section. */
+ htab->vector_base = htab->stub_sec->output_section->vma;
- if (get_local_syms (info->input_bfds, info))
- {
- if (htab->all_local_syms)
- goto error_ret_free_local;
- return FALSE;
- }
+ if (get_local_syms (info->input_bfds, info))
+ {
+ if (htab->all_local_syms)
+ goto error_ret_free_local;
+ return FALSE;
+ }
if (ADD_DUMMY_STUBS_FOR_DEBUGGING)
{
bfd_size_type total_size = 0;
htab = avr_link_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* In case that there were several stub sections: */
for (stub_sec = htab->stub_bfd->sections;