mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-03 04:12:10 +08:00
bfd/
* elflink.c (elf_section_ignore_discarded_relocs): Revert last change. Comment. (elf_section_complain_discarded): New function. Handle .gcc_except_table too. (elf_link_input_bfd): Rewrite handling of relocs against symbols in discarded sections. * elf-bfd.h (elf_discarded_section): Protect macro arg. ld/testsuite/ * ld-discard/extern.d: Update. * ld-discard/start.d: Update. * ld-discard/static.d: Update.
This commit is contained in:
parent
0b5d887791
commit
cdd3575c22
@ -1,3 +1,13 @@
|
||||
2004-07-01 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elflink.c (elf_section_ignore_discarded_relocs): Revert last
|
||||
change. Comment.
|
||||
(elf_section_complain_discarded): New function. Handle
|
||||
.gcc_except_table too.
|
||||
(elf_link_input_bfd): Rewrite handling of relocs against symbols
|
||||
in discarded sections.
|
||||
* elf-bfd.h (elf_discarded_section): Protect macro arg.
|
||||
|
||||
2004-06-30 James E Wilson <wilson@specifixinc.com>
|
||||
|
||||
* elfxx-ia64.c (elfNN_ia64_check_relocs): New local pltoff. Initialize
|
||||
|
@ -1067,8 +1067,8 @@ struct bfd_elf_section_data
|
||||
#define elf_discarded_section(sec) \
|
||||
(!bfd_is_abs_section (sec) \
|
||||
&& bfd_is_abs_section ((sec)->output_section) \
|
||||
&& sec->sec_info_type != ELF_INFO_TYPE_MERGE \
|
||||
&& sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
|
||||
&& (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \
|
||||
&& (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
|
||||
|
||||
#define get_elf_backend_data(abfd) \
|
||||
((const struct elf_backend_data *) (abfd)->xvec->backend_data)
|
||||
|
164
bfd/elflink.c
164
bfd/elflink.c
@ -6258,18 +6258,22 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return TRUE if special handling is done for relocs in SEC against
|
||||
symbols defined in discarded sections. */
|
||||
|
||||
static bfd_boolean
|
||||
elf_section_ignore_discarded_relocs (asection *sec)
|
||||
{
|
||||
const struct elf_backend_data *bed;
|
||||
|
||||
if (strncmp (".stab", sec->name, 5) == 0
|
||||
&& (!sec->name[5] ||
|
||||
(sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
|
||||
return TRUE;
|
||||
|
||||
if (strcmp (".eh_frame", sec->name) == 0)
|
||||
return TRUE;
|
||||
switch (sec->sec_info_type)
|
||||
{
|
||||
case ELF_INFO_TYPE_STABS:
|
||||
case ELF_INFO_TYPE_EH_FRAME:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bed = get_elf_backend_data (sec->owner);
|
||||
if (bed->elf_backend_ignore_discarded_relocs != NULL
|
||||
@ -6279,6 +6283,26 @@ elf_section_ignore_discarded_relocs (asection *sec)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return TRUE if we should complain about a reloc in SEC against a
|
||||
symbol defined in a discarded section. */
|
||||
|
||||
static bfd_boolean
|
||||
elf_section_complain_discarded (asection *sec)
|
||||
{
|
||||
if (strncmp (".stab", sec->name, 5) == 0
|
||||
&& (!sec->name[5] ||
|
||||
(sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
|
||||
return FALSE;
|
||||
|
||||
if (strcmp (".eh_frame", sec->name) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (strcmp (".gcc_except_table", sec->name) == 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Link an input file into the linker output file. This function
|
||||
handles all the sections and relocations of the input file at once.
|
||||
This is so that we only have to read the local symbols once, and
|
||||
@ -6551,99 +6575,87 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
|
||||
if (!elf_section_ignore_discarded_relocs (o))
|
||||
{
|
||||
Elf_Internal_Rela *rel, *relend;
|
||||
bfd_boolean complain = elf_section_complain_discarded (o);
|
||||
|
||||
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 *sec;
|
||||
asection **ps, *sec;
|
||||
struct elf_link_hash_entry *h = NULL;
|
||||
const char *sym_name;
|
||||
|
||||
if (r_symndx >= locsymcount
|
||||
|| (elf_bad_symtab (input_bfd)
|
||||
&& finfo->sections[r_symndx] == NULL))
|
||||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
h = sym_hashes[r_symndx - extsymoff];
|
||||
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;
|
||||
|
||||
/* Complain if the definition comes from a
|
||||
discarded section. */
|
||||
sec = h->root.u.def.section;
|
||||
if ((h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& elf_discarded_section (sec))
|
||||
{
|
||||
if ((o->flags & SEC_DEBUGGING) != 0)
|
||||
{
|
||||
BFD_ASSERT (r_symndx != 0);
|
||||
/* Try to preserve debug information. */
|
||||
if (sec->kept_section != NULL
|
||||
&& sec->size == sec->kept_section->size)
|
||||
h->root.u.def.section
|
||||
= sec->kept_section;
|
||||
else
|
||||
memset (rel, 0, sizeof (*rel));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *r_name
|
||||
= xstrdup (bfd_archive_filename (o->owner));
|
||||
finfo->info->callbacks->error_handler
|
||||
(LD_DEFINITION_IN_DISCARDED_SECTION,
|
||||
_("`%T' referenced in section `%s' from %s: discarded in section `%s' from %s\n"),
|
||||
h->root.root.string,
|
||||
h->root.root.string,
|
||||
o->name, r_name,
|
||||
h->root.u.def.section->name,
|
||||
bfd_archive_filename (h->root.u.def.section->owner));
|
||||
if (r_name)
|
||||
free (r_name);
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
sec = finfo->sections[r_symndx];
|
||||
Elf_Internal_Sym *sym = isymbuf + r_symndx;
|
||||
ps = &finfo->sections[r_symndx];
|
||||
sym_name = bfd_elf_local_sym_name (input_bfd, sym);
|
||||
}
|
||||
|
||||
if (sec != NULL && elf_discarded_section (sec))
|
||||
/* Complain if the definition comes from a
|
||||
discarded section. */
|
||||
if ((sec = *ps) != NULL && elf_discarded_section (sec))
|
||||
{
|
||||
if ((o->flags & SEC_DEBUGGING) != 0)
|
||||
{
|
||||
if ((o->flags & SEC_DEBUGGING) != 0)
|
||||
{
|
||||
BFD_ASSERT (r_symndx != 0);
|
||||
/* Try to preserve debug information. */
|
||||
if (sec->kept_section != NULL
|
||||
&& sec->size == sec->kept_section->size)
|
||||
finfo->sections[r_symndx]
|
||||
= sec->kept_section;
|
||||
else
|
||||
{
|
||||
rel->r_info &= r_type_mask;
|
||||
rel->r_addend = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static int count;
|
||||
int ok;
|
||||
char *buf;
|
||||
BFD_ASSERT (r_symndx != 0);
|
||||
|
||||
ok = asprintf (&buf, "local symbol %d",
|
||||
count++);
|
||||
if (ok <= 0)
|
||||
buf = (char *) "local symbol";
|
||||
finfo->info->callbacks->error_handler
|
||||
(LD_DEFINITION_IN_DISCARDED_SECTION,
|
||||
_("`%T' referenced in section `%s': discarded in section `%s' from %s\n"),
|
||||
buf, buf, o->name, sec->name,
|
||||
bfd_archive_filename (input_bfd));
|
||||
if (ok != -1)
|
||||
free (buf);
|
||||
/* Try to preserve debug information.
|
||||
FIXME: This is quite broken. Modifying
|
||||
the symbol here means we will be changing
|
||||
all uses of the symbol, not just those in
|
||||
debug sections. The only thing that makes
|
||||
this half reasonable is that debug sections
|
||||
tend to come after other sections. Of
|
||||
course, that doesn't help with globals.
|
||||
??? All link-once sections of the same name
|
||||
ought to define the same set of symbols, so
|
||||
it would seem that globals ought to always
|
||||
be defined in the kept section. */
|
||||
if (sec->kept_section != NULL
|
||||
&& sec->size == sec->kept_section->size)
|
||||
{
|
||||
*ps = sec->kept_section;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (complain)
|
||||
{
|
||||
finfo->info->callbacks->error_handler
|
||||
(LD_DEFINITION_IN_DISCARDED_SECTION,
|
||||
_("`%T' referenced in section `%s' of %B: "
|
||||
"defined in discarded section `%s' of %B\n"),
|
||||
sym_name,
|
||||
sym_name, o->name, input_bfd,
|
||||
sec->name, sec->owner);
|
||||
}
|
||||
|
||||
/* Remove the symbol reference from the reloc, but
|
||||
don't kill the reloc completely. This is so that
|
||||
a zero value will be written into the section,
|
||||
which may have non-zero contents put there by the
|
||||
assembler. Zero in things like an eh_frame fde
|
||||
pc_begin allows stack unwinders to recognize the
|
||||
fde as bogus. */
|
||||
rel->r_info &= r_type_mask;
|
||||
rel->r_addend = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
2004-07-01 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* ld-discard/extern.d: Update.
|
||||
* ld-discard/start.d: Update.
|
||||
* ld-discard/static.d: Update.
|
||||
|
||||
2004-06-30 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR 233
|
||||
|
@ -1,3 +1,3 @@
|
||||
#source: extern.s
|
||||
#ld: -T discard.ld
|
||||
#error: `data' referenced in section `\.text' from tmpdir/dump0.o: discarded in section `\.data\.exit' from tmpdir/dump0.o
|
||||
#error: `data' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump0.o
|
||||
|
@ -1,4 +1,4 @@
|
||||
#source: start.s
|
||||
#source: exit.s
|
||||
#ld: -T discard.ld
|
||||
#error: `data' referenced in section `\.text' from tmpdir/dump0.o: discarded in section `\.data\.exit' from tmpdir/dump1.o
|
||||
#error: `data' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump1.o
|
||||
|
@ -1,3 +1,3 @@
|
||||
#source: static.s
|
||||
#ld: -T discard.ld
|
||||
#error: `local symbol 0' referenced in section `\.text': discarded in section `\.data\.exit' from tmpdir/dump0.o
|
||||
#error: `\.data\.exit' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump0.o
|
||||
|
Loading…
Reference in New Issue
Block a user