* 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> 2007-09-28 Alan Modra <amodra@bigpond.net.au>
* elf-m10300.c (mn10300_elf_check_relocs): Delete dead code. * 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 *); (asection *, asection *, struct bfd_link_info *);
extern void bfd_elf_perform_complex_relocation extern void bfd_elf_perform_complex_relocation
(bfd * output_bfd ATTRIBUTE_UNUSED, (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma);
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);
extern bfd_boolean _bfd_elf_setup_sections extern bfd_boolean _bfd_elf_setup_sections
(bfd *); (bfd *);

View File

@ -402,48 +402,6 @@ mep_info_to_howto_rela
r_type = ELF32_R_TYPE (dst->r_info); r_type = ELF32_R_TYPE (dst->r_info);
cache_ptr->howto = & mep_elf_howto_table [r_type]; 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. /* Relocate a MEP ELF section.
There is some attempt to make this function usable for many architectures, There is some attempt to make this function usable for many architectures,
@ -513,18 +471,7 @@ mep_elf_relocate_section
int r_type; int r_type;
r_type = ELF32_R_TYPE (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info);
r_symndx = ELF32_R_SYM (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); howto = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
h = NULL; h = NULL;
sym = NULL; sym = NULL;
@ -539,56 +486,17 @@ mep_elf_relocate_section
name = bfd_elf_string_from_elf_section name = bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name); (input_bfd, symtab_hdr->sh_link, sym->st_name);
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : 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 else
{ {
relocation = 0; bfd_boolean warned, unresolved_reloc;
h = sym_hashes [r_symndx];
while (h->root.type == bfd_link_hash_indirect RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
|| h->root.type == bfd_link_hash_warning) r_symndx, symtab_hdr, sym_hashes,
h = (struct elf_link_hash_entry *) h->root.u.i.link; h, sec, relocation,
unresolved_reloc, warned);
name = h->root.root.string; 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 (sec != NULL && elf_discarded_section (sec))
@ -603,18 +511,15 @@ mep_elf_relocate_section
} }
if (info->relocatable) 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) switch (r_type)
{ {
case R_RELC:
bfd_elf_perform_complex_relocation (input_bfd, input_section,
contents, rel, relocation);
continue;
default: default:
r = mep_final_link_relocate (howto, input_bfd, input_section, r = mep_final_link_relocate (howto, input_bfd, input_section,
contents, rel, relocation); contents, rel, relocation);
@ -675,63 +580,6 @@ mep_elf_relocate_section
return TRUE; 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. */ /* Function to set the ELF flag bits. */
@ -899,11 +747,6 @@ elf32_mep_machine (bfd * abfd)
static bfd_boolean static bfd_boolean
mep_elf_object_p (bfd * abfd) 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)); bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
return TRUE; return TRUE;
} }
@ -940,15 +783,10 @@ mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
#define elf_info_to_howto_rel NULL #define elf_info_to_howto_rel NULL
#define elf_info_to_howto mep_info_to_howto_rela #define elf_info_to_howto mep_info_to_howto_rela
#define elf_backend_relocate_section mep_elf_relocate_section #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_object_p mep_elf_object_p
#define elf_backend_section_flags mep_elf_section_flags #define elf_backend_section_flags mep_elf_section_flags
#define elf_backend_fake_sections mep_elf_fake_sections #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_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_set_private_flags mep_elf_set_private_flags
@ -956,7 +794,6 @@ mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED,
#define bfd_elf32_bfd_merge_private_bfd_data mep_elf_merge_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 #define bfd_elf32_bfd_print_private_bfd_data mep_elf_print_private_bfd_data
/* We use only the RELA entries. */ #define elf_backend_rela_normal 1
#define USE_RELA
#include "elf32-target.h" #include "elf32-target.h"

View File

@ -7281,7 +7281,6 @@ resolve_symbol (const char * name,
struct bfd_link_hash_entry * global_entry; struct bfd_link_hash_entry * global_entry;
const char * candidate = NULL; const char * candidate = NULL;
Elf_Internal_Shdr * symtab_hdr; Elf_Internal_Shdr * symtab_hdr;
asection * sec = NULL;
size_t i; size_t i;
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
@ -7289,7 +7288,6 @@ resolve_symbol (const char * name,
for (i = 0; i < locsymcount; ++ i) for (i = 0; i < locsymcount; ++ i)
{ {
sym = isymbuf + i; sym = isymbuf + i;
sec = finfo->sections [i];
if (ELF_ST_BIND (sym->st_info) != STB_LOCAL) if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
continue; continue;
@ -7298,26 +7296,18 @@ resolve_symbol (const char * name,
symtab_hdr->sh_link, symtab_hdr->sh_link,
sym->st_name); sym->st_name);
#ifdef DEBUG #ifdef DEBUG
printf ("Comparing string: '%s' vs. '%s' = 0x%x\n", printf ("Comparing string: '%s' vs. '%s' = 0x%lx\n",
name, candidate, (unsigned int)sym->st_value); name, candidate, (unsigned long) sym->st_value);
#endif #endif
if (candidate && strcmp (candidate, name) == 0) if (candidate && strcmp (candidate, name) == 0)
{ {
* result = sym->st_value; asection *sec = finfo->sections [i];
if (sym->st_shndx > SHN_UNDEF && *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0);
sym->st_shndx < SHN_LORESERVE) *result += sec->output_offset + sec->output_section->vma;
{
#ifdef DEBUG #ifdef DEBUG
printf ("adjusting for sec '%s' @ 0x%x + 0x%x\n", printf ("Found symbol with value %8.8lx\n",
sec->output_section->name, (unsigned long) *result);
(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);
#endif #endif
return TRUE; return TRUE;
} }
@ -7335,20 +7325,8 @@ resolve_symbol (const char * name,
+ global_entry->u.def.section->output_section->vma + global_entry->u.def.section->output_section->vma
+ global_entry->u.def.section->output_offset; + global_entry->u.def.section->output_offset;
#ifdef DEBUG #ifdef DEBUG
printf ("Found GLOBAL symbol '%s' with value %8.8x\n", printf ("Found GLOBAL symbol '%s' with value %8.8lx\n",
global_entry->root.string, (unsigned int)*result); 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 #endif
return TRUE; return TRUE;
} }
@ -7402,12 +7380,10 @@ undefined_reference (const char * reftype,
static bfd_boolean static bfd_boolean
eval_symbol (bfd_vma * result, eval_symbol (bfd_vma * result,
char * sym, const char ** symp,
char ** advanced,
bfd * input_bfd, bfd * input_bfd,
struct elf_final_link_info * finfo, struct elf_final_link_info * finfo,
bfd_vma addr, bfd_vma dot,
bfd_vma section_offset,
Elf_Internal_Sym * isymbuf, Elf_Internal_Sym * isymbuf,
size_t locsymcount, size_t locsymcount,
int signed_p) int signed_p)
@ -7418,6 +7394,7 @@ eval_symbol (bfd_vma * result,
bfd_vma b; bfd_vma b;
const int bufsz = 4096; const int bufsz = 4096;
char symbuf [bufsz]; char symbuf [bufsz];
const char *sym = *symp;
const char * symend; const char * symend;
bfd_boolean symbol_is_section = FALSE; bfd_boolean symbol_is_section = FALSE;
@ -7433,21 +7410,21 @@ eval_symbol (bfd_vma * result,
switch (* sym) switch (* sym)
{ {
case '.': case '.':
* result = addr + section_offset; *result = dot;
* advanced = sym + 1; *symp = sym + 1;
return TRUE; return TRUE;
case '#': case '#':
++ sym; ++sym;
* result = strtoul (sym, advanced, 16); *result = strtoul (sym, (char **) symp, 16);
return TRUE; return TRUE;
case 'S': case 'S':
symbol_is_section = TRUE; symbol_is_section = TRUE;
case 's': case 's':
++ sym; ++sym;
symlen = strtol (sym, &sym, 10); symlen = strtol (sym, (char **) symp, 10);
++ sym; /* Skip the trailing ':'. */ sym = *symp + 1; /* Skip the trailing ':'. */
if ((symend < sym) || ((symlen + 1) > bufsz)) if ((symend < sym) || ((symlen + 1) > bufsz))
{ {
@ -7457,7 +7434,7 @@ eval_symbol (bfd_vma * result,
memcpy (symbuf, sym, symlen); memcpy (symbuf, sym, symlen);
symbuf [symlen] = '\0'; symbuf [symlen] = '\0';
* advanced = sym + symlen; *symp = sym + symlen;
/* Is it always possible, with complex symbols, that gas "mis-guessed" /* 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 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); \ sym += strlen (#op); \
if (* sym == ':') \ if (* sym == ':') \
++ sym; \ ++ sym; \
if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \ *symp = sym; \
section_offset, isymbuf, locsymcount, \ if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \
signed_p)) \ isymbuf, locsymcount, signed_p)) \
return FALSE; \ return FALSE; \
if (signed_p) \ if (signed_p) \
* result = op ((signed)a); \ *result = op ((bfd_signed_vma) a); \
else \ else \
* result = op a; \ * result = op a; \
* advanced = sym; \
return TRUE; \ return TRUE; \
} }
@ -7514,20 +7490,18 @@ eval_symbol (bfd_vma * result,
sym += strlen (#op); \ sym += strlen (#op); \
if (* sym == ':') \ if (* sym == ':') \
++ sym; \ ++ sym; \
if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \ *symp = sym; \
section_offset, isymbuf, locsymcount, \ if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \
signed_p)) \ isymbuf, locsymcount, signed_p)) \
return FALSE; \ return FALSE; \
++ sym; \ ++*symp; \
if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr, \ if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \
section_offset, isymbuf, locsymcount, \ isymbuf, locsymcount, signed_p)) \
signed_p)) \
return FALSE; \ return FALSE; \
if (signed_p) \ if (signed_p) \
* result = ((signed) a) op ((signed) b); \ *result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b); \
else \ else \
* result = a op b; \ * result = a op b; \
* advanced = sym; \
return TRUE; \ 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 static void
put_value (bfd_vma size, put_value (bfd_vma size,
unsigned long chunksz, unsigned long chunksz,
@ -7791,84 +7630,20 @@ decode_complex_addend
} }
void void
bfd_elf_perform_complex_relocation bfd_elf_perform_complex_relocation (bfd *input_bfd,
(bfd * output_bfd ATTRIBUTE_UNUSED, asection *input_section,
struct bfd_link_info * info, bfd_byte *contents,
bfd * input_bfd, Elf_Internal_Rela *rel,
asection * input_section, bfd_vma relocation)
bfd_byte * contents,
Elf_Internal_Rela * rel,
Elf_Internal_Sym * local_syms,
asection ** local_sections)
{ {
const struct elf_backend_data * bed; bfd_vma shift, x, mask;
Elf_Internal_Shdr * symtab_hdr; unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p;
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;
/* Perform this reloc, since it is complex. /* Perform this reloc, since it is complex.
(this is not to say that it necessarily refers to a complex (this is not to say that it necessarily refers to a complex
symbol; merely that it is a self-describing CGEN based reloc. symbol; merely that it is a self-describing CGEN based reloc.
i.e. the addend has the complete reloc information (bit start, end, i.e. the addend has the complete reloc information (bit start, end,
word size, etc) encoded within it.). */ 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, decode_complex_addend (& start, & oplen, & len, & wordsz,
& chunksz, & lsb0_p, & signed_p, & chunksz, & lsb0_p, & signed_p,
@ -9213,10 +8988,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
return FALSE; return FALSE;
} }
if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf,
locsymcount))
return FALSE;
/* Relocate the contents of each section. */ /* Relocate the contents of each section. */
sym_hashes = elf_sym_hashes (input_bfd); sym_hashes = elf_sym_hashes (input_bfd);
for (o = input_bfd->sections; o != NULL; o = o->next) 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) if ((o->flags & SEC_RELOC) != 0)
{ {
Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *internal_relocs;
Elf_Internal_Rela *rel, *relend;
bfd_vma r_type_mask; bfd_vma r_type_mask;
int r_sym_shift; int r_sym_shift;
int action_discarded;
int ret; int ret;
/* Get the swapped relocs. */ /* Get the swapped relocs. */
@ -9281,21 +9054,22 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
r_sym_shift = 32; r_sym_shift = 32;
} }
/* Run through the relocs looking for any against symbols action_discarded = -1;
from discarded sections and section symbols from
removed link-once sections. Complain about relocs
against discarded sections. Zero relocs against removed
link-once sections. */
if (!elf_section_ignore_discarded_relocs (o)) if (!elf_section_ignore_discarded_relocs (o))
{ action_discarded = (*bed->action_discarded) (o);
Elf_Internal_Rela *rel, *relend;
unsigned int action = (*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; rel = internal_relocs;
relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
for ( ; rel < relend; rel++) for ( ; rel < relend; rel++)
{ {
unsigned long r_symndx = rel->r_info >> r_sym_shift; unsigned long r_symndx = rel->r_info >> r_sym_shift;
unsigned int s_type;
asection **ps, *sec; asection **ps, *sec;
struct elf_link_hash_entry *h = NULL; struct elf_link_hash_entry *h = NULL;
const char *sym_name; const char *sym_name;
@ -9329,28 +9103,58 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
if (h->root.type != bfd_link_hash_defined s_type = h->type;
&& 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; sym_name = h->root.root.string;
} }
else else
{ {
Elf_Internal_Sym *sym = isymbuf + r_symndx; Elf_Internal_Sym *sym = isymbuf + r_symndx;
s_type = ELF_ST_TYPE (sym->st_info);
ps = &finfo->sections[r_symndx]; ps = &finfo->sections[r_symndx];
sym_name = bfd_elf_sym_name (input_bfd, sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr,
symtab_hdr,
sym, *ps); 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 /* Complain if the definition comes from a
discarded section. */ discarded section. */
if ((sec = *ps) != NULL && elf_discarded_section (sec)) if ((sec = *ps) != NULL && elf_discarded_section (sec))
{ {
BFD_ASSERT (r_symndx != 0); BFD_ASSERT (r_symndx != 0);
if (action & COMPLAIN) if (action_discarded & COMPLAIN)
(*finfo->info->callbacks->einfo) (*finfo->info->callbacks->einfo)
(_("%X`%s' referenced in section `%A' of %B: " (_("%X`%s' referenced in section `%A' of %B: "
"defined in discarded section `%A' of %B\n"), "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 FIXME: This is quite broken. Modifying the
symbol here means we will be changing all later symbol here means we will be changing all later
uses of the symbol, not just in this section. */ uses of the symbol, not just in this section. */
if (action & PRETEND) if (action_discarded & PRETEND)
{ {
asection *kept; 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> 2007-09-29 Mike Frysinger <vapier@gentoo.org>
* ld-alpha/tlsbin.rd: Use [0-9]+ to match section header count and * 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 } { for { set i 0 } { $i < [llength $test_list] } { incr i } {
# We need to strip the ".d", but can leave the dirname. # We need to strip the ".d", but can leave the dirname.
verbose [file rootname [lindex $test_list $i]] verbose [file rootname [lindex $test_list $i]]
setup_xfail "alpha*-*" "arc*-*" "d30v*-*" "dlx*-*" "hppa64-*-*" setup_xfail "alpha*-*" "am33*-*" "arc*-*" "d30v*-*" "dlx*-*"
setup_xfail "i370*-*" "i860*-*" "i960*-*" "ia64*-*" "mn10200-*" setup_xfail "hppa*64-*-*" "i370*-*" "i860*-*" "i960*-*" "ia64*-*"
setup_xfail "or32-*" "pj-*" setup_xfail "m88*-*" "mn10200-*" "mep-*" "or32-*" "pj-*"
run_dump_test [file rootname [lindex $test_list $i]] run_dump_test [file rootname [lindex $test_list $i]]
} }

View File

@ -27,8 +27,15 @@ if ![is_elf_format] {
return return
} }
# Alpha and IA64 do not support selective linking # These targets do not support selective linking
if {[istarget "alpha*-*-*"] || [istarget "ia64-*-*"]} { 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 return
} }