r_type = ELF32_R_TYPE (dst->r_info);
cache_ptr->howto = & mep_elf_howto_table [r_type];
}
-
-/* Look through the relocs for a section during the first phase.
- Since we don't do .gots or .plts, we just need to consider the
- virtual table relocs for gc. */
-
-static bfd_boolean
-mep_elf_check_relocs
- (bfd * abfd,
- struct bfd_link_info * info,
- asection * sec,
- const Elf_Internal_Rela * relocs)
-{
- Elf_Internal_Shdr * symtab_hdr;
- struct elf_link_hash_entry ** sym_hashes;
- struct elf_link_hash_entry ** sym_hashes_end;
- const Elf_Internal_Rela * rel;
- const Elf_Internal_Rela * rel_end;
-
- if (info->relocatable)
- return TRUE;
-
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
- if (!elf_bad_symtab (abfd))
- sym_hashes_end -= symtab_hdr->sh_info;
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- struct elf_link_hash_entry *h;
- unsigned long r_symndx;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- if (r_symndx < symtab_hdr->sh_info)
- h = NULL;
- else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- }
- return TRUE;
-}
-
\f
/* Relocate a MEP ELF section.
There is some attempt to make this function usable for many architectures,
int r_type;
r_type = ELF32_R_TYPE (rel->r_info);
-
r_symndx = ELF32_R_SYM (rel->r_info);
-
- /* Is this a complex relocation? */
- if (!info->relocatable && ELF32_R_TYPE (rel->r_info) == R_RELC)
- {
- bfd_elf_perform_complex_relocation (output_bfd, info,
- input_bfd, input_section, contents,
- rel, local_syms, local_sections);
- continue;
- }
-
howto = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
h = NULL;
sym = NULL;
name = bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name);
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
-#if 0
- fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
- sec->name, name, sym->st_name,
- sec->output_section->vma, sec->output_offset,
- sym->st_value, rel->r_addend);
-#endif
}
else
{
- relocation = 0;
- h = sym_hashes [r_symndx];
+ bfd_boolean warned, unresolved_reloc;
- 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;
+ RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
name = h->root.root.string;
-
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- sec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
-#if 0
- fprintf (stderr,
- "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
- sec->name, name, h->root.u.def.value,
- sec->output_section->vma, sec->output_offset, relocation);
-#endif
- }
- else if (h->root.type == bfd_link_hash_undefweak)
- {
-#if 0
- fprintf (stderr, "undefined: sec: %s, name: %s\n",
- sec->name, name);
-#endif
- }
- else if (!info->relocatable)
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section, rel->r_offset,
- (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
- return FALSE;
-#if 0
- fprintf (stderr, "unknown: name: %s\n", name);
-#endif
- }
}
if (sec != NULL && elf_discarded_section (sec))
}
if (info->relocatable)
- {
- /* This is a relocatable link. We don't have to change
- anything, unless the reloc is against a section symbol,
- in which case we have to adjust according to where the
- section symbol winds up in the output section. */
- if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- rel->r_addend += sec->output_offset;
- continue;
- }
+ continue;
switch (r_type)
{
+ case R_RELC:
+ bfd_elf_perform_complex_relocation (input_bfd, input_section,
+ contents, rel, relocation);
+ continue;
+
default:
r = mep_final_link_relocate (howto, input_bfd, input_section,
contents, rel, relocation);
return TRUE;
}
-\f
-
-/* Update the got entry reference counts for the section being
- removed. */
-
-static bfd_boolean
-mep_elf_gc_sweep_hook
- (bfd * abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info * info ATTRIBUTE_UNUSED,
- asection * sec ATTRIBUTE_UNUSED,
- const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
-{
- return TRUE;
-}
-
-/* Return the section that should be marked against GC for a given
- relocation. */
-
-static asection *
-mep_elf_gc_mark_hook
- (asection * sec,
- struct bfd_link_info * info ATTRIBUTE_UNUSED,
- Elf_Internal_Rela * rel,
- struct elf_link_hash_entry * h,
- Elf_Internal_Sym * sym)
-{
- if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- {
- if (!(elf_bad_symtab (sec->owner)
- && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
- && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
- && sym->st_shndx != SHN_COMMON))
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
- }
-
- return NULL;
-}
-
\f
/* Function to set the ELF flag bits. */
static bfd_boolean
mep_elf_object_p (bfd * abfd)
{
- /* Irix 5 and 6 is broken. Object file symbol tables are not always
- sorted correctly such that local symbols preceed global symbols,
- and the sh_info field in the symbol table is not always right. */
- /* This is needed for the RELC support code. */
- elf_bad_symtab (abfd) = TRUE;
bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
return TRUE;
}
#define elf_info_to_howto_rel NULL
#define elf_info_to_howto mep_info_to_howto_rela
#define elf_backend_relocate_section mep_elf_relocate_section
-#define elf_backend_gc_mark_hook mep_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook mep_elf_gc_sweep_hook
-#define elf_backend_check_relocs mep_elf_check_relocs
#define elf_backend_object_p mep_elf_object_p
#define elf_backend_section_flags mep_elf_section_flags
#define elf_backend_fake_sections mep_elf_fake_sections
-#define elf_backend_can_gc_sections 1
-
#define bfd_elf32_bfd_reloc_type_lookup mep_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup
#define bfd_elf32_bfd_set_private_flags mep_elf_set_private_flags
#define bfd_elf32_bfd_copy_private_bfd_data mep_elf_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data mep_elf_merge_private_bfd_data
#define bfd_elf32_bfd_print_private_bfd_data mep_elf_print_private_bfd_data
-/* We use only the RELA entries. */
-#define USE_RELA
+#define elf_backend_rela_normal 1
#include "elf32-target.h"
struct bfd_link_hash_entry * global_entry;
const char * candidate = NULL;
Elf_Internal_Shdr * symtab_hdr;
- asection * sec = NULL;
size_t i;
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
for (i = 0; i < locsymcount; ++ i)
{
sym = isymbuf + i;
- sec = finfo->sections [i];
if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
continue;
symtab_hdr->sh_link,
sym->st_name);
#ifdef DEBUG
- printf ("Comparing string: '%s' vs. '%s' = 0x%x\n",
- name, candidate, (unsigned int)sym->st_value);
+ printf ("Comparing string: '%s' vs. '%s' = 0x%lx\n",
+ name, candidate, (unsigned long) sym->st_value);
#endif
if (candidate && strcmp (candidate, name) == 0)
{
- * result = sym->st_value;
+ asection *sec = finfo->sections [i];
- if (sym->st_shndx > SHN_UNDEF &&
- sym->st_shndx < SHN_LORESERVE)
- {
-#ifdef DEBUG
- printf ("adjusting for sec '%s' @ 0x%x + 0x%x\n",
- sec->output_section->name,
- (unsigned int)sec->output_section->vma,
- (unsigned int)sec->output_offset);
-#endif
- * result += sec->output_offset + sec->output_section->vma;
- }
+ *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0);
+ *result += sec->output_offset + sec->output_section->vma;
#ifdef DEBUG
- printf ("Found symbol with effective value %8.8x\n", (unsigned int)* result);
+ printf ("Found symbol with value %8.8lx\n",
+ (unsigned long) *result);
#endif
return TRUE;
}
+ global_entry->u.def.section->output_section->vma
+ global_entry->u.def.section->output_offset;
#ifdef DEBUG
- printf ("Found GLOBAL symbol '%s' with value %8.8x\n",
- global_entry->root.string, (unsigned int)*result);
+ printf ("Found GLOBAL symbol '%s' with value %8.8lx\n",
+ global_entry->root.string, (unsigned long) *result);
#endif
return TRUE;
}
- if (global_entry->type == bfd_link_hash_common)
- {
- *result = global_entry->u.def.value +
- bfd_com_section_ptr->output_section->vma +
- bfd_com_section_ptr->output_offset;
-#ifdef DEBUG
- printf ("Found COMMON symbol '%s' with value %8.8x\n",
- global_entry->root.string, (unsigned int)*result);
-#endif
- return TRUE;
- }
-
return FALSE;
}
static bfd_boolean
eval_symbol (bfd_vma * result,
- char * sym,
- char ** advanced,
+ const char ** symp,
bfd * input_bfd,
struct elf_final_link_info * finfo,
- bfd_vma addr,
- bfd_vma section_offset,
+ bfd_vma dot,
Elf_Internal_Sym * isymbuf,
size_t locsymcount,
int signed_p)
bfd_vma b;
const int bufsz = 4096;
char symbuf [bufsz];
+ const char *sym = *symp;
const char * symend;
bfd_boolean symbol_is_section = FALSE;
switch (* sym)
{
case '.':
- * result = addr + section_offset;
- * advanced = sym + 1;
+ *result = dot;
+ *symp = sym + 1;
return TRUE;
case '#':
- ++ sym;
- * result = strtoul (sym, advanced, 16);
+ ++sym;
+ *result = strtoul (sym, (char **) symp, 16);
return TRUE;
case 'S':
symbol_is_section = TRUE;
case 's':
- ++ sym;
- symlen = strtol (sym, &sym, 10);
- ++ sym; /* Skip the trailing ':'. */
+ ++sym;
+ symlen = strtol (sym, (char **) symp, 10);
+ sym = *symp + 1; /* Skip the trailing ':'. */
if ((symend < sym) || ((symlen + 1) > bufsz))
{
memcpy (symbuf, sym, symlen);
symbuf [symlen] = '\0';
- * advanced = sym + symlen;
+ *symp = sym + symlen;
/* Is it always possible, with complex symbols, that gas "mis-guessed"
the symbol as a section, or vice-versa. so we're pretty liberal in our
sym += strlen (#op); \
if (* sym == ':') \
++ sym; \
- if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
- section_offset, isymbuf, locsymcount, \
- signed_p)) \
+ *symp = sym; \
+ if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \
+ isymbuf, locsymcount, signed_p)) \
return FALSE; \
if (signed_p) \
- * result = op ((signed)a); \
+ *result = op ((bfd_signed_vma) a); \
else \
* result = op a; \
- * advanced = sym; \
return TRUE; \
}
sym += strlen (#op); \
if (* sym == ':') \
++ sym; \
- if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
- section_offset, isymbuf, locsymcount, \
- signed_p)) \
+ *symp = sym; \
+ if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \
+ isymbuf, locsymcount, signed_p)) \
return FALSE; \
- ++ sym; \
- if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr, \
- section_offset, isymbuf, locsymcount, \
- signed_p)) \
+ ++*symp; \
+ if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \
+ isymbuf, locsymcount, signed_p)) \
return FALSE; \
if (signed_p) \
- * result = ((signed) a) op ((signed) b); \
+ *result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b); \
else \
* result = a op b; \
- * advanced = sym; \
return TRUE; \
}
}
}
-/* Entry point to evaluator, called from elf_link_input_bfd. */
-
-static bfd_boolean
-evaluate_complex_relocation_symbols (bfd *input_bfd,
- struct elf_final_link_info *finfo,
- Elf_Internal_Sym *isymbuf,
- size_t locsymcount)
-{
- const struct elf_backend_data * bed;
- Elf_Internal_Shdr * symtab_hdr;
- struct elf_link_hash_entry ** sym_hashes;
- asection * reloc_sec;
- bfd_boolean result = TRUE;
-
- /* For each section, we're going to check and see if it has any
- complex relocations, and we're going to evaluate any of them
- we can. */
-
- if (finfo->info->relocatable)
- return TRUE;
-
- symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
- sym_hashes = elf_sym_hashes (input_bfd);
- bed = get_elf_backend_data (input_bfd);
-
- for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next)
- {
- Elf_Internal_Rela * internal_relocs;
- unsigned long i;
-
- /* This section was omitted from the link. */
- if (! reloc_sec->linker_mark)
- continue;
-
- /* Only process sections containing relocs. */
- if ((reloc_sec->flags & SEC_RELOC) == 0)
- continue;
-
- if (reloc_sec->reloc_count == 0)
- continue;
-
- /* Read in the relocs for this section. */
- internal_relocs
- = _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL,
- (Elf_Internal_Rela *) NULL,
- FALSE);
- if (internal_relocs == NULL)
- continue;
-
- for (i = reloc_sec->reloc_count; i--;)
- {
- Elf_Internal_Rela * rel;
- char * sym_name;
- bfd_vma index;
- Elf_Internal_Sym * sym;
- bfd_vma result;
- bfd_vma section_offset;
- bfd_vma addr;
- int signed_p = 0;
-
- rel = internal_relocs + i;
- section_offset = reloc_sec->output_section->vma
- + reloc_sec->output_offset;
- addr = rel->r_offset;
-
- index = ELF32_R_SYM (rel->r_info);
- if (bed->s->arch_size == 64)
- index >>= 24;
-
- if (index == STN_UNDEF)
- continue;
-
- if (index < locsymcount)
- {
- /* The symbol is local. */
- sym = isymbuf + index;
-
- /* We're only processing STT_RELC or STT_SRELC type symbols. */
- if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
- (ELF_ST_TYPE (sym->st_info) != STT_SRELC))
- continue;
-
- sym_name = bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name);
-
- signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC);
- }
- else
- {
- /* The symbol is global. */
- struct elf_link_hash_entry * h;
-
- if (elf_bad_symtab (input_bfd))
- continue;
-
- h = sym_hashes [index - locsymcount];
- 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->type != STT_RELC && h->type != STT_SRELC)
- continue;
-
- signed_p = (h->type == STT_SRELC);
- sym_name = (char *) h->root.root.string;
- }
-#ifdef DEBUG
- printf ("Encountered a complex symbol!");
- printf (" (input_bfd %s, section %s, reloc %ld\n",
- input_bfd->filename, reloc_sec->name, i);
- printf (" symbol: idx %8.8lx, name %s\n",
- index, sym_name);
- printf (" reloc : info %8.8lx, addr %8.8lx\n",
- rel->r_info, addr);
- printf (" Evaluating '%s' ...\n ", sym_name);
-#endif
- if (eval_symbol (& result, sym_name, & sym_name, input_bfd,
- finfo, addr, section_offset, isymbuf, locsymcount,
- signed_p))
- /* Symbol evaluated OK. Update to absolute value. */
- set_symbol_value (input_bfd, isymbuf, locsymcount, index, result);
-
- else
- result = FALSE;
- }
-
- if (internal_relocs != elf_section_data (reloc_sec)->relocs)
- free (internal_relocs);
- }
-
- /* If nothing went wrong, then we adjusted
- everything we wanted to adjust. */
- return result;
-}
-
static void
put_value (bfd_vma size,
unsigned long chunksz,
}
void
-bfd_elf_perform_complex_relocation
- (bfd * output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info * info,
- bfd * input_bfd,
- asection * input_section,
- bfd_byte * contents,
- Elf_Internal_Rela * rel,
- Elf_Internal_Sym * local_syms,
- asection ** local_sections)
-{
- const struct elf_backend_data * bed;
- Elf_Internal_Shdr * symtab_hdr;
- asection * sec;
- bfd_vma relocation = 0, shift, x;
- bfd_vma r_symndx;
- bfd_vma mask;
- unsigned long start, oplen, len, wordsz,
- chunksz, lsb0_p, signed_p, trunc_p;
+bfd_elf_perform_complex_relocation (bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ Elf_Internal_Rela *rel,
+ bfd_vma relocation)
+{
+ bfd_vma shift, x, mask;
+ unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p;
/* Perform this reloc, since it is complex.
(this is not to say that it necessarily refers to a complex
symbol; merely that it is a self-describing CGEN based reloc.
i.e. the addend has the complete reloc information (bit start, end,
word size, etc) encoded within it.). */
- r_symndx = ELF32_R_SYM (rel->r_info);
- bed = get_elf_backend_data (input_bfd);
- if (bed->s->arch_size == 64)
- r_symndx >>= 24;
-
-#ifdef DEBUG
- printf ("Performing complex relocation %ld...\n", r_symndx);
-#endif
-
- symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
- if (r_symndx < symtab_hdr->sh_info)
- {
- /* The symbol is local. */
- Elf_Internal_Sym * sym;
-
- sym = local_syms + r_symndx;
- sec = local_sections [r_symndx];
- relocation = sym->st_value;
- if (sym->st_shndx > SHN_UNDEF &&
- sym->st_shndx < SHN_LORESERVE)
- relocation += (sec->output_offset +
- sec->output_section->vma);
- }
- else
- {
- /* The symbol is global. */
- struct elf_link_hash_entry **sym_hashes;
- struct elf_link_hash_entry * h;
-
- sym_hashes = elf_sym_hashes (input_bfd);
- h = sym_hashes [r_symndx];
-
- 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)
- {
- sec = h->root.u.def.section;
- relocation = h->root.u.def.value;
-
- if (! bfd_is_abs_section (sec))
- relocation += (sec->output_section->vma
- + sec->output_offset);
- }
- if (h->root.type == bfd_link_hash_undefined
- && !((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section, rel->r_offset,
- info->unresolved_syms_in_objects == RM_GENERATE_ERROR
- || ELF_ST_VISIBILITY (h->other))))
- return;
- }
decode_complex_addend (& start, & oplen, & len, & wordsz,
& chunksz, & lsb0_p, & signed_p,
return FALSE;
}
- if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf,
- locsymcount))
- return FALSE;
-
/* Relocate the contents of each section. */
sym_hashes = elf_sym_hashes (input_bfd);
for (o = input_bfd->sections; o != NULL; o = o->next)
if ((o->flags & SEC_RELOC) != 0)
{
Elf_Internal_Rela *internal_relocs;
+ Elf_Internal_Rela *rel, *relend;
bfd_vma r_type_mask;
int r_sym_shift;
+ int action_discarded;
int ret;
/* Get the swapped relocs. */
r_sym_shift = 32;
}
- /* Run through the relocs looking for any against symbols
- from discarded sections and section symbols from
- removed link-once sections. Complain about relocs
- against discarded sections. Zero relocs against removed
- link-once sections. */
+ action_discarded = -1;
if (!elf_section_ignore_discarded_relocs (o))
+ action_discarded = (*bed->action_discarded) (o);
+
+ /* Run through the relocs evaluating complex reloc symbols and
+ looking for relocs against symbols from discarded sections
+ or section symbols from removed link-once sections.
+ Complain about relocs against discarded sections. Zero
+ relocs against removed link-once sections. */
+
+ rel = internal_relocs;
+ relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+ for ( ; rel < relend; rel++)
{
- Elf_Internal_Rela *rel, *relend;
- unsigned int action = (*bed->action_discarded) (o);
+ unsigned long r_symndx = rel->r_info >> r_sym_shift;
+ unsigned int s_type;
+ asection **ps, *sec;
+ struct elf_link_hash_entry *h = NULL;
+ const char *sym_name;
- rel = internal_relocs;
- relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
- for ( ; rel < relend; rel++)
- {
- unsigned long r_symndx = rel->r_info >> r_sym_shift;
- asection **ps, *sec;
- struct elf_link_hash_entry *h = NULL;
- const char *sym_name;
+ if (r_symndx == STN_UNDEF)
+ continue;
- if (r_symndx == STN_UNDEF)
- continue;
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
+ {
+ h = sym_hashes[r_symndx - extsymoff];
- if (r_symndx >= locsymcount
- || (elf_bad_symtab (input_bfd)
- && finfo->sections[r_symndx] == NULL))
+ /* Badly formatted input files can contain relocs that
+ reference non-existant symbols. Check here so that
+ we do not seg fault. */
+ if (h == NULL)
{
- h = sym_hashes[r_symndx - extsymoff];
+ char buffer [32];
- /* Badly formatted input files can contain relocs that
- reference non-existant symbols. Check here so that
- we do not seg fault. */
- if (h == NULL)
- {
- char buffer [32];
+ sprintf_vma (buffer, rel->r_info);
+ (*_bfd_error_handler)
+ (_("error: %B contains a reloc (0x%s) for section %A "
+ "that references a non-existent global symbol"),
+ input_bfd, o, buffer);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
- sprintf_vma (buffer, rel->r_info);
- (*_bfd_error_handler)
- (_("error: %B contains a reloc (0x%s) for section %A "
- "that references a non-existent global symbol"),
- input_bfd, o, buffer);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
+ 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;
- 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;
+ s_type = h->type;
- if (h->root.type != bfd_link_hash_defined
- && h->root.type != bfd_link_hash_defweak)
- continue;
+ ps = NULL;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ ps = &h->root.u.def.section;
- ps = &h->root.u.def.section;
- sym_name = h->root.root.string;
- }
- else
- {
- Elf_Internal_Sym *sym = isymbuf + r_symndx;
- ps = &finfo->sections[r_symndx];
- sym_name = bfd_elf_sym_name (input_bfd,
- symtab_hdr,
- sym, *ps);
- }
+ sym_name = h->root.root.string;
+ }
+ else
+ {
+ Elf_Internal_Sym *sym = isymbuf + r_symndx;
+ s_type = ELF_ST_TYPE (sym->st_info);
+ ps = &finfo->sections[r_symndx];
+ sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr,
+ sym, *ps);
+ }
+
+ if (s_type == STT_RELC || s_type == STT_SRELC)
+ {
+ bfd_vma val;
+ bfd_vma dot = (rel->r_offset
+ + o->output_offset + o->output_section->vma);
+#ifdef DEBUG
+ printf ("Encountered a complex symbol!");
+ printf (" (input_bfd %s, section %s, reloc %ld\n",
+ input_bfd->filename, o->name, rel - internal_relocs);
+ printf (" symbol: idx %8.8lx, name %s\n",
+ r_symndx, sym_name);
+ printf (" reloc : info %8.8lx, addr %8.8lx\n",
+ (unsigned long) rel->r_info,
+ (unsigned long) rel->r_offset);
+#endif
+ if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot,
+ isymbuf, locsymcount, s_type == STT_SRELC))
+ return FALSE;
+
+ /* Symbol evaluated OK. Update to absolute value. */
+ set_symbol_value (input_bfd, isymbuf, locsymcount,
+ r_symndx, val);
+ continue;
+ }
+
+ if (action_discarded != -1 && ps != NULL)
+ {
/* Complain if the definition comes from a
discarded section. */
if ((sec = *ps) != NULL && elf_discarded_section (sec))
{
BFD_ASSERT (r_symndx != 0);
- if (action & COMPLAIN)
+ if (action_discarded & COMPLAIN)
(*finfo->info->callbacks->einfo)
(_("%X`%s' referenced in section `%A' of %B: "
"defined in discarded section `%A' of %B\n"),
FIXME: This is quite broken. Modifying the
symbol here means we will be changing all later
uses of the symbol, not just in this section. */
- if (action & PRETEND)
+ if (action_discarded & PRETEND)
{
asection *kept;