bfd/
* elf-bfd.h (_bfd_elf_gc_mark_rsec, _bfd_elf_gc_mark_reloc): Declare. (_bfd_elf_gc_mark): Use elf_gc_mark_hook_fn. * elflink.c (init_reloc_cookie, fini_reloc_cookie) (init_reloc_cookie_rels, fini_reloc_cookie_rels): New functions, split out from... (bfd_elf_discard_info): ...here. (init_reloc_cookie_for_section): New function. (fini_reloc_cookie_for_section): Likewise. (_bfd_elf_gc_mark_rsec, _bfd_elf_gc_mark_reloc): New functions, split out from... (_bfd_elf_gc_mark): ...here. Use init_reloc_cookie_for_section and fini_reloc_cookie_for_section.
This commit is contained in:
parent
281b8327ae
commit
5241d85325
3 changed files with 241 additions and 172 deletions
|
@ -1,3 +1,18 @@
|
|||
2007-12-15 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* elf-bfd.h (_bfd_elf_gc_mark_rsec, _bfd_elf_gc_mark_reloc): Declare.
|
||||
(_bfd_elf_gc_mark): Use elf_gc_mark_hook_fn.
|
||||
* elflink.c (init_reloc_cookie, fini_reloc_cookie)
|
||||
(init_reloc_cookie_rels, fini_reloc_cookie_rels): New functions,
|
||||
split out from...
|
||||
(bfd_elf_discard_info): ...here.
|
||||
(init_reloc_cookie_for_section): New function.
|
||||
(fini_reloc_cookie_for_section): Likewise.
|
||||
(_bfd_elf_gc_mark_rsec, _bfd_elf_gc_mark_reloc): New functions,
|
||||
split out from...
|
||||
(_bfd_elf_gc_mark): ...here. Use init_reloc_cookie_for_section
|
||||
and fini_reloc_cookie_for_section.
|
||||
|
||||
2007-12-12 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* elf32-xtensa.c (elf_xtensa_do_reloc): Update self_address along with
|
||||
|
|
|
@ -1971,10 +1971,16 @@ extern asection *_bfd_elf_gc_mark_hook
|
|||
(asection *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *);
|
||||
|
||||
extern asection *_bfd_elf_gc_mark_rsec
|
||||
(struct bfd_link_info *, asection *, elf_gc_mark_hook_fn,
|
||||
struct elf_reloc_cookie *);
|
||||
|
||||
extern bfd_boolean _bfd_elf_gc_mark_reloc
|
||||
(struct bfd_link_info *, asection *, elf_gc_mark_hook_fn,
|
||||
struct elf_reloc_cookie *, bfd_boolean);
|
||||
|
||||
extern bfd_boolean _bfd_elf_gc_mark
|
||||
(struct bfd_link_info *, asection *,
|
||||
asection * (*) (asection *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *));
|
||||
(struct bfd_link_info *, asection *, elf_gc_mark_hook_fn);
|
||||
|
||||
extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
|
386
bfd/elflink.c
386
bfd/elflink.c
|
@ -10940,6 +10940,139 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize COOKIE for input bfd ABFD. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie (struct elf_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info, bfd *abfd)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
const struct elf_backend_data *bed;
|
||||
|
||||
bed = get_elf_backend_data (abfd);
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
|
||||
cookie->abfd = abfd;
|
||||
cookie->sym_hashes = elf_sym_hashes (abfd);
|
||||
cookie->bad_symtab = elf_bad_symtab (abfd);
|
||||
if (cookie->bad_symtab)
|
||||
{
|
||||
cookie->locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
|
||||
cookie->extsymoff = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cookie->locsymcount = symtab_hdr->sh_info;
|
||||
cookie->extsymoff = symtab_hdr->sh_info;
|
||||
}
|
||||
|
||||
if (bed->s->arch_size == 32)
|
||||
cookie->r_sym_shift = 8;
|
||||
else
|
||||
cookie->r_sym_shift = 32;
|
||||
|
||||
cookie->locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (cookie->locsyms == NULL && cookie->locsymcount != 0)
|
||||
{
|
||||
cookie->locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
|
||||
cookie->locsymcount, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (cookie->locsyms == NULL)
|
||||
{
|
||||
info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
|
||||
return FALSE;
|
||||
}
|
||||
if (info->keep_memory)
|
||||
symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie, if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
if (cookie->locsyms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) cookie->locsyms)
|
||||
free (cookie->locsyms);
|
||||
}
|
||||
|
||||
/* Initialize the relocation information in COOKIE for input section SEC
|
||||
of input bfd ABFD. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info, bfd *abfd,
|
||||
asection *sec)
|
||||
{
|
||||
const struct elf_backend_data *bed;
|
||||
|
||||
if (sec->reloc_count == 0)
|
||||
{
|
||||
cookie->rels = NULL;
|
||||
cookie->relend = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
bed = get_elf_backend_data (abfd);
|
||||
|
||||
cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (cookie->rels == NULL)
|
||||
return FALSE;
|
||||
cookie->rel = cookie->rels;
|
||||
cookie->relend = (cookie->rels
|
||||
+ sec->reloc_count * bed->s->int_rels_per_ext_rel);
|
||||
}
|
||||
cookie->rel = cookie->rels;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie_rels,
|
||||
if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
|
||||
asection *sec)
|
||||
{
|
||||
if (cookie->rels && elf_section_data (sec)->relocs != cookie->rels)
|
||||
free (cookie->rels);
|
||||
}
|
||||
|
||||
/* Initialize the whole of COOKIE for input section SEC. */
|
||||
|
||||
static bfd_boolean
|
||||
init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
|
||||
struct bfd_link_info *info,
|
||||
asection *sec)
|
||||
{
|
||||
if (!init_reloc_cookie (cookie, info, sec->owner))
|
||||
goto error1;
|
||||
if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
|
||||
goto error2;
|
||||
return TRUE;
|
||||
|
||||
error2:
|
||||
fini_reloc_cookie (cookie, sec->owner);
|
||||
error1:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Free the memory allocated by init_reloc_cookie_for_section,
|
||||
if appropriate. */
|
||||
|
||||
static void
|
||||
fini_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
|
||||
asection *sec)
|
||||
{
|
||||
fini_reloc_cookie_rels (cookie, sec);
|
||||
fini_reloc_cookie (cookie, sec->owner);
|
||||
}
|
||||
|
||||
/* Garbage collect unused sections. */
|
||||
|
||||
/* Default gc_mark_hook. */
|
||||
|
@ -10972,6 +11105,63 @@ _bfd_elf_gc_mark_hook (asection *sec,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* COOKIE->rel describes a relocation against section SEC, which is
|
||||
a section we've decided to keep. Return the section that contains
|
||||
the relocation symbol, or NULL if no section contains it. */
|
||||
|
||||
asection *
|
||||
_bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
|
||||
elf_gc_mark_hook_fn gc_mark_hook,
|
||||
struct elf_reloc_cookie *cookie)
|
||||
{
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
r_symndx = cookie->rel->r_info >> cookie->r_sym_shift;
|
||||
if (r_symndx == 0)
|
||||
return NULL;
|
||||
|
||||
if (r_symndx >= cookie->locsymcount
|
||||
|| ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
|
||||
{
|
||||
h = cookie->sym_hashes[r_symndx - cookie->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;
|
||||
return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
|
||||
}
|
||||
|
||||
return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
|
||||
&cookie->locsyms[r_symndx]);
|
||||
}
|
||||
|
||||
/* COOKIE->rel describes a relocation against section SEC, which is
|
||||
a section we've decided to keep. Mark the section that contains
|
||||
the relocation symbol. IS_EH is true if the mark comes from
|
||||
.eh_frame. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
|
||||
asection *sec,
|
||||
elf_gc_mark_hook_fn gc_mark_hook,
|
||||
struct elf_reloc_cookie *cookie,
|
||||
bfd_boolean is_eh)
|
||||
{
|
||||
asection *rsec;
|
||||
|
||||
rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
|
||||
if (rsec && !rsec->gc_mark)
|
||||
{
|
||||
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
|
||||
rsec->gc_mark = 1;
|
||||
else if (is_eh)
|
||||
rsec->gc_mark_from_eh = 1;
|
||||
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The mark phase of garbage collection. For a given section, mark
|
||||
it and any sections in this section's group, and all the sections
|
||||
which define symbols to which it refers. */
|
||||
|
@ -10998,103 +11188,22 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
|||
is_eh = strcmp (sec->name, ".eh_frame") == 0;
|
||||
if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
|
||||
{
|
||||
Elf_Internal_Rela *relstart, *rel, *relend;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
size_t nlocsyms;
|
||||
size_t extsymoff;
|
||||
bfd *input_bfd = sec->owner;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (input_bfd);
|
||||
Elf_Internal_Sym *isym = NULL;
|
||||
int r_sym_shift;
|
||||
struct elf_reloc_cookie cookie;
|
||||
|
||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (input_bfd);
|
||||
|
||||
/* Read the local symbols. */
|
||||
if (elf_bad_symtab (input_bfd))
|
||||
{
|
||||
nlocsyms = symtab_hdr->sh_size / bed->s->sizeof_sym;
|
||||
extsymoff = 0;
|
||||
}
|
||||
if (!init_reloc_cookie_for_section (&cookie, info, sec))
|
||||
ret = FALSE;
|
||||
else
|
||||
extsymoff = nlocsyms = symtab_hdr->sh_info;
|
||||
|
||||
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (isym == NULL && nlocsyms != 0)
|
||||
{
|
||||
isym = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, nlocsyms, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (isym == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read the relocations. */
|
||||
relstart = _bfd_elf_link_read_relocs (input_bfd, sec, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (relstart == NULL)
|
||||
{
|
||||
ret = FALSE;
|
||||
goto out1;
|
||||
}
|
||||
relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
|
||||
|
||||
if (bed->s->arch_size == 32)
|
||||
r_sym_shift = 8;
|
||||
else
|
||||
r_sym_shift = 32;
|
||||
|
||||
for (rel = relstart; rel < relend; rel++)
|
||||
{
|
||||
unsigned long r_symndx;
|
||||
asection *rsec;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
r_symndx = rel->r_info >> r_sym_shift;
|
||||
if (r_symndx == 0)
|
||||
continue;
|
||||
|
||||
if (r_symndx >= nlocsyms
|
||||
|| ELF_ST_BIND (isym[r_symndx].st_info) != STB_LOCAL)
|
||||
{
|
||||
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;
|
||||
rsec = (*gc_mark_hook) (sec, info, rel, h, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rsec = (*gc_mark_hook) (sec, info, rel, NULL, &isym[r_symndx]);
|
||||
}
|
||||
|
||||
if (rsec && !rsec->gc_mark)
|
||||
{
|
||||
if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
|
||||
rsec->gc_mark = 1;
|
||||
else if (is_eh)
|
||||
rsec->gc_mark_from_eh = 1;
|
||||
else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out2:
|
||||
if (elf_section_data (sec)->relocs != relstart)
|
||||
free (relstart);
|
||||
out1:
|
||||
if (isym != NULL && symtab_hdr->contents != (unsigned char *) isym)
|
||||
{
|
||||
if (! info->keep_memory)
|
||||
free (isym);
|
||||
else
|
||||
symtab_hdr->contents = (unsigned char *) isym;
|
||||
for (; cookie.rel < cookie.relend; cookie.rel++)
|
||||
if (!_bfd_elf_gc_mark_reloc (info, sec, gc_mark_hook,
|
||||
&cookie, is_eh))
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
fini_reloc_cookie_for_section (&cookie, sec);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -11777,10 +11886,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
|
|||
{
|
||||
struct elf_reloc_cookie cookie;
|
||||
asection *stab, *eh;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
const struct elf_backend_data *bed;
|
||||
bfd *abfd;
|
||||
unsigned int count;
|
||||
bfd_boolean ret = FALSE;
|
||||
|
||||
if (info->traditional_format
|
||||
|
@ -11819,95 +11926,36 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
|
|||
&& bed->elf_backend_discard_info == NULL)
|
||||
continue;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
cookie.abfd = abfd;
|
||||
cookie.sym_hashes = elf_sym_hashes (abfd);
|
||||
cookie.bad_symtab = elf_bad_symtab (abfd);
|
||||
if (cookie.bad_symtab)
|
||||
if (!init_reloc_cookie (&cookie, info, abfd))
|
||||
return FALSE;
|
||||
|
||||
if (stab != NULL
|
||||
&& stab->reloc_count > 0
|
||||
&& init_reloc_cookie_rels (&cookie, info, abfd, stab))
|
||||
{
|
||||
cookie.locsymcount = symtab_hdr->sh_size / bed->s->sizeof_sym;
|
||||
cookie.extsymoff = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cookie.locsymcount = symtab_hdr->sh_info;
|
||||
cookie.extsymoff = symtab_hdr->sh_info;
|
||||
if (_bfd_discard_section_stabs (abfd, stab,
|
||||
elf_section_data (stab)->sec_info,
|
||||
bfd_elf_reloc_symbol_deleted_p,
|
||||
&cookie))
|
||||
ret = TRUE;
|
||||
fini_reloc_cookie_rels (&cookie, stab);
|
||||
}
|
||||
|
||||
if (bed->s->arch_size == 32)
|
||||
cookie.r_sym_shift = 8;
|
||||
else
|
||||
cookie.r_sym_shift = 32;
|
||||
|
||||
cookie.locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (cookie.locsyms == NULL && cookie.locsymcount != 0)
|
||||
if (eh != NULL
|
||||
&& init_reloc_cookie_rels (&cookie, info, abfd, eh))
|
||||
{
|
||||
cookie.locsyms = bfd_elf_get_elf_syms (abfd, symtab_hdr,
|
||||
cookie.locsymcount, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (cookie.locsyms == NULL)
|
||||
{
|
||||
info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (stab != NULL)
|
||||
{
|
||||
cookie.rels = NULL;
|
||||
count = stab->reloc_count;
|
||||
if (count != 0)
|
||||
cookie.rels = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (cookie.rels != NULL)
|
||||
{
|
||||
cookie.rel = cookie.rels;
|
||||
cookie.relend = cookie.rels;
|
||||
cookie.relend += count * bed->s->int_rels_per_ext_rel;
|
||||
if (_bfd_discard_section_stabs (abfd, stab,
|
||||
elf_section_data (stab)->sec_info,
|
||||
bfd_elf_reloc_symbol_deleted_p,
|
||||
&cookie))
|
||||
ret = TRUE;
|
||||
if (elf_section_data (stab)->relocs != cookie.rels)
|
||||
free (cookie.rels);
|
||||
}
|
||||
}
|
||||
|
||||
if (eh != NULL)
|
||||
{
|
||||
cookie.rels = NULL;
|
||||
count = eh->reloc_count;
|
||||
if (count != 0)
|
||||
cookie.rels = _bfd_elf_link_read_relocs (abfd, eh, NULL, NULL,
|
||||
info->keep_memory);
|
||||
cookie.rel = cookie.rels;
|
||||
cookie.relend = cookie.rels;
|
||||
if (cookie.rels != NULL)
|
||||
cookie.relend += count * bed->s->int_rels_per_ext_rel;
|
||||
|
||||
if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
|
||||
bfd_elf_reloc_symbol_deleted_p,
|
||||
&cookie))
|
||||
ret = TRUE;
|
||||
|
||||
if (cookie.rels != NULL
|
||||
&& elf_section_data (eh)->relocs != cookie.rels)
|
||||
free (cookie.rels);
|
||||
fini_reloc_cookie_rels (&cookie, eh);
|
||||
}
|
||||
|
||||
if (bed->elf_backend_discard_info != NULL
|
||||
&& (*bed->elf_backend_discard_info) (abfd, &cookie, info))
|
||||
ret = TRUE;
|
||||
|
||||
if (cookie.locsyms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) cookie.locsyms)
|
||||
{
|
||||
if (! info->keep_memory)
|
||||
free (cookie.locsyms);
|
||||
else
|
||||
symtab_hdr->contents = (unsigned char *) cookie.locsyms;
|
||||
}
|
||||
fini_reloc_cookie (&cookie, abfd);
|
||||
}
|
||||
|
||||
if (info->eh_frame_hdr
|
||||
|
|
Loading…
Reference in a new issue