* elflink.c (resolve_symbol): Handle symbols in SEC_MERGE
	sections.  Don't test symbol st_shndx.  Don't bother with
	bfd_link_hash_common symbols.  Print longs rather than ints
	in debug messages.
	(eval_symbol): Replace "sym" and "advanced" params with "symp".
	Replace "addr" and "section_offset" params with "dot".  Don't
	cast bfd_vma values to signed, cast them to bfd_signed_vma.
	(bfd_elf_perform_complex_relocation): Delete "output_bfd", "info",
	"local_syms" and "local_sections" params.  Add "relocation".
	Delete code calculating relocation value.
	(evaluate_complex_relocation_symbols): Delete function.  Fold into..
	(elf_link_input_bfd): ..existing code examining relocs.
	* elf-bfd.h (bfd_elf_perform_complex_relocation): Update prototype.
	* elf32-mep.c (mep_elf_check_relocs): Delete function.
	(mep_elf_gc_sweep_hook, mep_elf_gc_mark_hook): Likewise.
	(mep_elf_object_p): Don't set elf_bad_symtab.
	(elf_backend_check_relocs): Don't define.
	(elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): Likewise.
	(elf_backend_can_gc_sections, USE_RELA): Likwise.
	(mep_elf_relocate_section): Move bfd_elf_perform_complex_relocation
	call after we have calculated reloc value.  Delete local sym
	debug code.  Use RELOC_FOR_GLOBAL_SYMBOL.  Delete addend
	adjusting code..
	(elf_backend_rela_normal): ..instead define this.
ld/testsuite/
	* ld-selective/sel-dump.exp: Add am33, m88k, mep to xfails.
	* ld-selective/selective.exp: Don't run for same target list
	we xfail sel-dump.
This commit is contained in:
Alan Modra 2007-09-30 13:33:04 +00:00
parent c9ccd0dfa0
commit 0f02bbd9f8
7 changed files with 187 additions and 513 deletions

View File

@ -1,3 +1,30 @@
2007-09-29 Alan Modra <amodra@bigpond.net.au>
* elflink.c (resolve_symbol): Handle symbols in SEC_MERGE
sections. Don't test symbol st_shndx. Don't bother with
bfd_link_hash_common symbols. Print longs rather than ints
in debug messages.
(eval_symbol): Replace "sym" and "advanced" params with "symp".
Replace "addr" and "section_offset" params with "dot". Don't
cast bfd_vma values to signed, cast them to bfd_signed_vma.
(bfd_elf_perform_complex_relocation): Delete "output_bfd", "info",
"local_syms" and "local_sections" params. Add "relocation".
Delete code calculating relocation value.
(evaluate_complex_relocation_symbols): Delete function. Fold into..
(elf_link_input_bfd): ..existing code examining relocs.
* elf-bfd.h (bfd_elf_perform_complex_relocation): Update prototype.
* elf32-mep.c (mep_elf_check_relocs): Delete function.
(mep_elf_gc_sweep_hook, mep_elf_gc_mark_hook): Likewise.
(mep_elf_object_p): Don't set elf_bad_symtab.
(elf_backend_check_relocs): Don't define.
(elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): Likewise.
(elf_backend_can_gc_sections, USE_RELA): Likwise.
(mep_elf_relocate_section): Move bfd_elf_perform_complex_relocation
call after we have calculated reloc value. Delete local sym
debug code. Use RELOC_FOR_GLOBAL_SYMBOL. Delete addend
adjusting code..
(elf_backend_rela_normal): ..instead define this.
2007-09-28 Alan Modra <amodra@bigpond.net.au>
* elf-m10300.c (mn10300_elf_check_relocs): Delete dead code.

View File

@ -1814,14 +1814,7 @@ extern bfd_boolean bfd_elf_match_symbols_in_sections
(asection *, asection *, struct bfd_link_info *);
extern 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);
(bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma);
extern bfd_boolean _bfd_elf_setup_sections
(bfd *);

View File

@ -402,48 +402,6 @@ mep_info_to_howto_rela
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;
}
/* Relocate a MEP ELF section.
There is some attempt to make this function usable for many architectures,
@ -513,18 +471,7 @@ mep_elf_relocate_section
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;
@ -539,56 +486,17 @@ mep_elf_relocate_section
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))
@ -603,18 +511,15 @@ mep_elf_relocate_section
}
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);
@ -675,63 +580,6 @@ mep_elf_relocate_section
return TRUE;
}
/* 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;
}
/* Function to set the ELF flag bits. */
@ -899,11 +747,6 @@ elf32_mep_machine (bfd * abfd)
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;
}
@ -940,23 +783,17 @@ mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
#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"

View File

@ -7281,7 +7281,6 @@ resolve_symbol (const char * name,
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;
@ -7289,7 +7288,6 @@ resolve_symbol (const char * name,
for (i = 0; i < locsymcount; ++ i)
{
sym = isymbuf + i;
sec = finfo->sections [i];
if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
continue;
@ -7298,26 +7296,18 @@ resolve_symbol (const char * name,
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)
{
*result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0);
*result += sec->output_offset + sec->output_section->vma;
#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;
}
#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;
}
@ -7335,24 +7325,12 @@ resolve_symbol (const char * name,
+ 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;
}
@ -7402,12 +7380,10 @@ undefined_reference (const char * reftype,
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)
@ -7418,6 +7394,7 @@ eval_symbol (bfd_vma * result,
bfd_vma b;
const int bufsz = 4096;
char symbuf [bufsz];
const char *sym = *symp;
const char * symend;
bfd_boolean symbol_is_section = FALSE;
@ -7433,21 +7410,21 @@ eval_symbol (bfd_vma * result,
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))
{
@ -7457,7 +7434,7 @@ eval_symbol (bfd_vma * result,
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
@ -7496,15 +7473,14 @@ eval_symbol (bfd_vma * result,
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; \
}
@ -7514,20 +7490,18 @@ eval_symbol (bfd_vma * result,
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; \
}
@ -7561,141 +7535,6 @@ eval_symbol (bfd_vma * result,
}
}
/* 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,
@ -7791,84 +7630,20 @@ decode_complex_addend
}
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)
bfd_elf_perform_complex_relocation (bfd *input_bfd,
asection *input_section,
bfd_byte *contents,
Elf_Internal_Rela *rel,
bfd_vma relocation)
{
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_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,
@ -9213,10 +8988,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
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)
@ -9258,8 +9029,10 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
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. */
@ -9281,76 +9054,107 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
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++)
if (r_symndx == STN_UNDEF)
continue;
if (r_symndx >= locsymcount
|| (elf_bad_symtab (input_bfd)
&& finfo->sections[r_symndx] == NULL))
{
unsigned long r_symndx = rel->r_info >> r_sym_shift;
asection **ps, *sec;
struct elf_link_hash_entry *h = NULL;
const char *sym_name;
h = sym_hashes[r_symndx - extsymoff];
if (r_symndx == STN_UNDEF)
continue;
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;
}
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)
continue;
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);
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;
s_type = h->type;
ps = NULL;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
ps = &h->root.u.def.section;
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"),
@ -9362,7 +9166,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
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;

View File

@ -1,3 +1,9 @@
2007-09-29 Alan Modra <amodra@bigpond.net.au>
* ld-selective/sel-dump.exp: Add am33, m88k, mep to xfails.
* ld-selective/selective.exp: Don't run for same target list
we xfail sel-dump.
2007-09-29 Mike Frysinger <vapier@gentoo.org>
* ld-alpha/tlsbin.rd: Use [0-9]+ to match section header count and

View File

@ -28,8 +28,8 @@ set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
for { set i 0 } { $i < [llength $test_list] } { incr i } {
# We need to strip the ".d", but can leave the dirname.
verbose [file rootname [lindex $test_list $i]]
setup_xfail "alpha*-*" "arc*-*" "d30v*-*" "dlx*-*" "hppa64-*-*"
setup_xfail "i370*-*" "i860*-*" "i960*-*" "ia64*-*" "mn10200-*"
setup_xfail "or32-*" "pj-*"
setup_xfail "alpha*-*" "am33*-*" "arc*-*" "d30v*-*" "dlx*-*"
setup_xfail "hppa*64-*-*" "i370*-*" "i860*-*" "i960*-*" "ia64*-*"
setup_xfail "m88*-*" "mn10200-*" "mep-*" "or32-*" "pj-*"
run_dump_test [file rootname [lindex $test_list $i]]
}

View File

@ -27,8 +27,15 @@ if ![is_elf_format] {
return
}
# Alpha and IA64 do not support selective linking
if {[istarget "alpha*-*-*"] || [istarget "ia64-*-*"]} {
# These targets do not support selective linking
if {[istarget "alpha*-*-*"] || [istarget "am33*-*-*"] ||
[istarget "arc-*-*"] || [istarget "d30v-*-*"] ||
[istarget "dlx-*-*"] || [istarget "hppa*64*-*-*"] ||
[istarget "i370-*-*"] || [istarget "i860-*-*"] ||
[istarget "i960-*-*"] || [istarget "ia64-*-*"] ||
[istarget "m88*-*-*"] || [istarget "mn10200-*-*"] ||
[istarget "mep-*-*"] || [istarget "or32-*-*"] ||
[istarget "pj*-*-*"]} {
return
}