summaryrefslogtreecommitdiff
path: root/bfd/elflink.h
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r--bfd/elflink.h409
1 files changed, 217 insertions, 192 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 85160e90257..721b361ee31 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -921,6 +921,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
boolean size_change_ok;
char *shortname;
struct elf_link_hash_entry *hi;
+ struct bfd_link_hash_entry *bh;
struct elf_backend_data *bed;
boolean collect;
boolean dynamic;
@@ -979,11 +980,12 @@ elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
if (! override)
{
+ bh = &hi->root;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr,
- (bfd_vma) 0, name, false, collect,
- (struct bfd_link_hash_entry **) &hi)))
+ (bfd_vma) 0, name, false, collect, &bh)))
return false;
+ hi = (struct elf_link_hash_entry *) bh;
}
else
{
@@ -1098,11 +1100,12 @@ elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
}
else
{
+ bh = &hi->root;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT,
- bfd_ind_section_ptr, (bfd_vma) 0, name, false,
- collect, (struct bfd_link_hash_entry **) &hi)))
+ bfd_ind_section_ptr, (bfd_vma) 0, name, false, collect, &bh)))
return false;
+ hi = (struct elf_link_hash_entry *) bh;
/* If there is a duplicate definition somewhere, then HI may not
point to an indirect symbol. We will have reported an error
@@ -1295,6 +1298,14 @@ elf_link_add_object_symbols (abfd, info)
const char *name;
bfd_size_type oldsize;
bfd_size_type strindex;
+ struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+
+ /* ld --just-symbols and dynamic objects don't mix very well.
+ Test for --just-symbols by looking at info set up by
+ _bfd_elf_link_just_syms. */
+ if ((s = abfd->sections) != NULL
+ && elf_section_data (s)->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+ goto error_return;
/* Find the name to use in a DT_NEEDED entry that refers to this
object. If the object has a DT_SONAME entry, we use it.
@@ -1324,8 +1335,6 @@ elf_link_add_object_symbols (abfd, info)
Elf_External_Dyn *extdynend;
int elfsec;
unsigned long shlink;
- int rpath;
- int runpath;
dynbuf = (Elf_External_Dyn *) bfd_malloc (s->_raw_size);
if (dynbuf == NULL)
@@ -1342,8 +1351,6 @@ elf_link_add_object_symbols (abfd, info)
extdyn = dynbuf;
extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
- rpath = 0;
- runpath = 0;
for (; extdyn < extdynend; extdyn++)
{
Elf_Internal_Dyn dyn;
@@ -1387,13 +1394,6 @@ elf_link_add_object_symbols (abfd, info)
char *fnm, *anm;
unsigned int tagv = dyn.d_un.d_val;
- /* When we see DT_RPATH before DT_RUNPATH, we have
- to clear runpath. Do _NOT_ bfd_release, as that
- frees all more recently bfd_alloc'd blocks as
- well. */
- if (rpath && hash_table->runpath)
- hash_table->runpath = NULL;
-
amt = sizeof (struct bfd_link_needed_list);
n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
@@ -1407,13 +1407,11 @@ elf_link_add_object_symbols (abfd, info)
n->name = anm;
n->by = abfd;
n->next = NULL;
- for (pn = & hash_table->runpath;
+ for (pn = & runpath;
*pn != NULL;
pn = &(*pn)->next)
;
*pn = n;
- runpath = 1;
- rpath = 0;
}
/* Ignore DT_RPATH if we have seen DT_RUNPATH. */
if (!runpath && dyn.d_tag == DT_RPATH)
@@ -1439,18 +1437,32 @@ elf_link_add_object_symbols (abfd, info)
n->name = anm;
n->by = abfd;
n->next = NULL;
- for (pn = & hash_table->runpath;
+ for (pn = & rpath;
*pn != NULL;
pn = &(*pn)->next)
;
*pn = n;
- rpath = 1;
}
}
free (dynbuf);
}
+ /* DT_RUNPATH overrides DT_RPATH. Do _NOT_ bfd_release, as that
+ frees all more recently bfd_alloc'd blocks as well. */
+ if (runpath)
+ rpath = runpath;
+
+ if (rpath)
+ {
+ struct bfd_link_needed_list **pn;
+ for (pn = & hash_table->runpath;
+ *pn != NULL;
+ pn = &(*pn)->next)
+ ;
+ *pn = rpath;
+ }
+
/* We do not want to include any of the sections in a dynamic
object in the output file. We hack by simply clobbering the
list of sections in the BFD. This could be handled more
@@ -2196,10 +2208,9 @@ elf_link_add_object_symbols (abfd, info)
}
}
- /* If this is a non-traditional, non-relocateable link, try to
- optimize the handling of the .stab/.stabstr sections. */
+ /* If this is a non-traditional link, try to optimize the handling
+ of the .stab/.stabstr sections. */
if (! dynamic
- && ! info->relocateable
&& ! info->traditional_format
&& info->hash->creator->flavour == bfd_target_elf_flavour
&& is_elf_hash_table (info)
@@ -2292,6 +2303,7 @@ elf_link_create_dynamic_sections (abfd, info)
flagword flags;
register asection *s;
struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
struct elf_backend_data *bed;
if (! is_elf_hash_table (info))
@@ -2329,6 +2341,7 @@ elf_link_create_dynamic_sections (abfd, info)
|| ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, 2))
return false;
+ elf_hash_table (info)->eh_info.hdr_sec = s;
}
/* Create sections to hold version informations. These are removed
@@ -2384,12 +2397,12 @@ elf_link_create_dynamic_sections (abfd, info)
creating a .dynamic section. We don't want to define it if there
is no .dynamic section, since on some ELF platforms the start up
code examines it to decide how to initialize the process. */
- h = NULL;
+ bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
- (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ (const char *) 0, false, get_elf_backend_data (abfd)->collect, &bh)))
return false;
+ h = (struct elf_link_hash_entry *) bh;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
@@ -3326,19 +3339,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
unsigned int cdeps;
struct bfd_elf_version_deps *n;
struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
cdeps = 0;
for (n = t->deps; n != NULL; n = n->next)
++cdeps;
/* Add a symbol representing this version. */
- h = NULL;
+ bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
(bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (dynobj)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ get_elf_backend_data (dynobj)->collect, &bh)))
return false;
+ h = (struct elf_link_hash_entry *) bh;
h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
@@ -4480,6 +4494,8 @@ struct elf_final_link_info
size_t symbuf_count;
/* Number of symbols which fit in symbuf. */
size_t symbuf_size;
+ /* And same for symshndxbuf. */
+ size_t shndxbuf_size;
};
static boolean elf_link_output_sym
@@ -4655,8 +4671,9 @@ struct elf_link_sort_rela
enum elf_reloc_type_class type;
union
{
- Elf_Internal_Rel rel;
- Elf_Internal_Rela rela;
+ /* We use these as arrays of size int_rels_per_ext_rel. */
+ Elf_Internal_Rel rel[1];
+ Elf_Internal_Rela rela[1];
} u;
};
@@ -4676,13 +4693,13 @@ elf_link_sort_cmp1 (A, B)
return 1;
if (relativea > relativeb)
return -1;
- if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info))
+ if (ELF_R_SYM (a->u.rel->r_info) < ELF_R_SYM (b->u.rel->r_info))
return -1;
- if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info))
+ if (ELF_R_SYM (a->u.rel->r_info) > ELF_R_SYM (b->u.rel->r_info))
return 1;
- if (a->u.rel.r_offset < b->u.rel.r_offset)
+ if (a->u.rel->r_offset < b->u.rel->r_offset)
return -1;
- if (a->u.rel.r_offset > b->u.rel.r_offset)
+ if (a->u.rel->r_offset > b->u.rel->r_offset)
return 1;
return 0;
}
@@ -4706,9 +4723,9 @@ elf_link_sort_cmp2 (A, B)
return -1;
if (copya > copyb)
return 1;
- if (a->u.rel.r_offset < b->u.rel.r_offset)
+ if (a->u.rel->r_offset < b->u.rel->r_offset)
return -1;
- if (a->u.rel.r_offset > b->u.rel.r_offset)
+ if (a->u.rel->r_offset > b->u.rel->r_offset)
return 1;
return 0;
}
@@ -4726,6 +4743,7 @@ elf_link_sort_relocs (abfd, info, psec)
size_t i, j, ret;
struct elf_link_sort_rela *rela;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int i2e = bed->s->int_rels_per_ext_rel;
reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
if (reldyn == NULL || reldyn->_raw_size == 0)
@@ -4749,7 +4767,23 @@ elf_link_sort_relocs (abfd, info, psec)
if (size != reldyn->_raw_size)
return 0;
- rela = (struct elf_link_sort_rela *) bfd_zmalloc (sizeof (*rela) * count);
+ /* We waste some memory here when N = i2e is greater than 1, since
+ we allocate space for N * sizeof (*rela) where sizeof (*rela) +
+ (N - 1) * sizeof (Elf_Internal_Rel/Rela) would do. Also, we use
+ rela[k] only when k is a multiple of N, and then we index the
+ array within the union, such that rela[k].u.rel[i], i < N, is the
+ (i+1)th internal relocation corresponding to the (k/N)th external
+ relocation. This is done such that the relocation swap-in and
+ swap-out functions can gen pointers to arrays of internal
+ relocations that form a single external relocation.
+
+ If C permitted arrays of structures with dynamic sizes, we could
+ do better, but trying to avoid wasting space at the end of the
+ chunk from rela[k] to rela[k+N-1] would require us to allocate a
+ separate array of pointers and since most ports have N == 1, this
+ would be more wasteful. */
+ rela = (struct elf_link_sort_rela *) bfd_zmalloc
+ (sizeof (*rela) * count * i2e);
if (rela == NULL)
{
(*info->callbacks->warning)
@@ -4770,15 +4804,16 @@ elf_link_sort_relocs (abfd, info, psec)
erel = (Elf_External_Rel *) o->contents;
erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
- s = rela + o->output_offset / sizeof (Elf_External_Rel);
- for (; erel < erelend; erel++, s++)
+ s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+ for (; erel < erelend; erel++, s += i2e)
{
if (bed->s->swap_reloc_in)
- (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel);
+ (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel,
+ s->u.rel);
else
- elf_swap_reloc_in (abfd, erel, &s->u.rel);
+ elf_swap_reloc_in (abfd, erel, s->u.rel);
- s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+ s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
}
}
else
@@ -4788,30 +4823,34 @@ elf_link_sort_relocs (abfd, info, psec)
erela = (Elf_External_Rela *) o->contents;
erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
- s = rela + o->output_offset / sizeof (Elf_External_Rela);
- for (; erela < erelaend; erela++, s++)
+ s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+ for (; erela < erelaend; erela++, s += i2e)
{
if (bed->s->swap_reloca_in)
(*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela,
- &s->u.rela);
+ s->u.rela);
else
- elf_swap_reloca_in (dynobj, erela, &s->u.rela);
+ elf_swap_reloca_in (dynobj, erela, s->u.rela);
- s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+ s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
}
}
}
- qsort (rela, (size_t) count, sizeof (*rela), elf_link_sort_cmp1);
- for (ret = 0; ret < count && rela[ret].type == reloc_class_relative; ret++)
+ qsort (rela, (size_t) count, sizeof (*rela) * i2e, elf_link_sort_cmp1);
+ for (ret = 0; ret < count * i2e && rela[ret].type == reloc_class_relative;
+ ret += i2e)
;
- for (i = ret, j = ret; i < count; i++)
+ for (i = ret, j = ret; i < count * i2e; i += i2e)
{
- if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info))
+ if (ELF_R_SYM (rela[i].u.rel->r_info)
+ != ELF_R_SYM (rela[j].u.rel->r_info))
j = i;
- rela[i].offset = rela[j].u.rel.r_offset;
+ rela[i].offset = rela[j].u.rel->r_offset;
}
- qsort (rela + ret, (size_t) count - ret, sizeof (*rela), elf_link_sort_cmp2);
+ ret /= i2e;
+ qsort (rela + ret, (size_t) count - ret,
+ sizeof (*rela) * i2e, elf_link_sort_cmp2);
for (o = dynobj->sections; o != NULL; o = o->next)
if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
@@ -4825,14 +4864,14 @@ elf_link_sort_relocs (abfd, info, psec)
erel = (Elf_External_Rel *) o->contents;
erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
- s = rela + o->output_offset / sizeof (Elf_External_Rel);
- for (; erel < erelend; erel++, s++)
+ s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+ for (; erel < erelend; erel++, s += i2e)
{
if (bed->s->swap_reloc_out)
- (*bed->s->swap_reloc_out) (abfd, &s->u.rel,
+ (*bed->s->swap_reloc_out) (abfd, s->u.rel,
(bfd_byte *) erel);
else
- elf_swap_reloc_out (abfd, &s->u.rel, erel);
+ elf_swap_reloc_out (abfd, s->u.rel, erel);
}
}
else
@@ -4842,14 +4881,14 @@ elf_link_sort_relocs (abfd, info, psec)
erela = (Elf_External_Rela *) o->contents;
erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
- s = rela + o->output_offset / sizeof (Elf_External_Rela);
- for (; erela < erelaend; erela++, s++)
+ s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+ for (; erela < erelaend; erela++, s += i2e)
{
if (bed->s->swap_reloca_out)
- (*bed->s->swap_reloca_out) (dynobj, &s->u.rela,
+ (*bed->s->swap_reloca_out) (dynobj, s->u.rela,
(bfd_byte *) erela);
else
- elf_swap_reloca_out (dynobj, &s->u.rela, erela);
+ elf_swap_reloca_out (dynobj, s->u.rela, erela);
}
}
}
@@ -4882,6 +4921,7 @@ elf_bfd_final_link (abfd, info)
Elf_Internal_Sym elfsym;
unsigned int i;
Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *symtab_shndx_hdr;
Elf_Internal_Shdr *symstrtab_hdr;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_outext_info eoinfo;
@@ -4935,6 +4975,7 @@ elf_bfd_final_link (abfd, info)
finfo.symbuf = NULL;
finfo.symshndxbuf = NULL;
finfo.symbuf_count = 0;
+ finfo.shndxbuf_size = 0;
finfo.first_tls_sec = NULL;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
if ((o->flags & SEC_THREAD_LOCAL) != 0
@@ -5155,9 +5196,7 @@ elf_bfd_final_link (abfd, info)
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* sh_name is set in prep_headers. */
symtab_hdr->sh_type = SHT_SYMTAB;
- symtab_hdr->sh_flags = 0;
- symtab_hdr->sh_addr = 0;
- symtab_hdr->sh_size = 0;
+ /* sh_flags, sh_addr and sh_size all start off zero. */
symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
/* sh_link is set in assign_section_numbers. */
/* sh_info is set below. */
@@ -5184,9 +5223,11 @@ elf_bfd_final_link (abfd, info)
goto error_return;
if (elf_numsections (abfd) > SHN_LORESERVE)
{
- amt = finfo.symbuf_size;
+ /* Wild guess at number of output symbols. realloc'd as needed. */
+ amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
+ finfo.shndxbuf_size = amt;
amt *= sizeof (Elf_External_Sym_Shndx);
- finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
if (finfo.symshndxbuf == NULL)
goto error_return;
}
@@ -5246,7 +5287,7 @@ elf_bfd_final_link (abfd, info)
if (! elf_link_output_sym (&finfo, (const char *) NULL,
&elfsym, o))
goto error_return;
- if (i == SHN_LORESERVE)
+ if (i == SHN_LORESERVE - 1)
i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
}
}
@@ -5521,6 +5562,24 @@ elf_bfd_final_link (abfd, info)
/* Now we know the size of the symtab section. */
off += symtab_hdr->sh_size;
+ symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+ if (symtab_shndx_hdr->sh_name != 0)
+ {
+ symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+ symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+ amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->sh_size = amt;
+
+ off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
+ off, true);
+
+ if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_bwrite ((PTR) finfo.symshndxbuf, amt, abfd) != amt))
+ return false;
+ }
+
+
/* Finish up and write out the symbol string table (.strtab)
section. */
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
@@ -5795,17 +5854,10 @@ elf_bfd_final_link (abfd, info)
goto error_return;
}
- if (info->eh_frame_hdr && elf_hash_table (info)->dynobj)
+ if (info->eh_frame_hdr)
{
- o = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
- ".eh_frame_hdr");
- if (o
- && (elf_section_data (o)->sec_info_type
- == ELF_INFO_TYPE_EH_FRAME_HDR))
- {
- if (! _bfd_elf_write_section_eh_frame_hdr (abfd, o))
- goto error_return;
- }
+ if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info))
+ goto error_return;
}
if (finfo.symstrtab != NULL)
@@ -5829,7 +5881,7 @@ elf_bfd_final_link (abfd, info)
if (finfo.symbuf != NULL)
free (finfo.symbuf);
if (finfo.symshndxbuf != NULL)
- free (finfo.symbuf);
+ free (finfo.symshndxbuf);
for (o = abfd->sections; o != NULL; o = o->next)
{
if ((o->flags & SEC_RELOC) != 0
@@ -5863,7 +5915,7 @@ elf_bfd_final_link (abfd, info)
if (finfo.symbuf != NULL)
free (finfo.symbuf);
if (finfo.symshndxbuf != NULL)
- free (finfo.symbuf);
+ free (finfo.symshndxbuf);
for (o = abfd->sections; o != NULL; o = o->next)
{
if ((o->flags & SEC_RELOC) != 0
@@ -5922,11 +5974,24 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
dest = finfo->symbuf + finfo->symbuf_count;
destshndx = finfo->symshndxbuf;
if (destshndx != NULL)
- destshndx += finfo->symbuf_count;
- elf_swap_symbol_out (finfo->output_bfd, elfsym, (PTR) dest, (PTR) destshndx);
- ++finfo->symbuf_count;
+ {
+ if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
+ {
+ bfd_size_type amt;
- ++ bfd_get_symcount (finfo->output_bfd);
+ amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
+ finfo->symshndxbuf = destshndx = bfd_realloc (destshndx, amt * 2);
+ if (destshndx == NULL)
+ return false;
+ memset ((char *) destshndx + amt, 0, amt);
+ finfo->shndxbuf_size *= 2;
+ }
+ destshndx += bfd_get_symcount (finfo->output_bfd);
+ }
+
+ elf_swap_symbol_out (finfo->output_bfd, elfsym, (PTR) dest, (PTR) destshndx);
+ finfo->symbuf_count += 1;
+ bfd_get_symcount (finfo->output_bfd) += 1;
return true;
}
@@ -5951,20 +6016,6 @@ elf_link_flush_output_syms (finfo)
return false;
hdr->sh_size += amt;
-
- if (finfo->symshndxbuf != NULL)
- {
- hdr = &elf_tdata (finfo->output_bfd)->symtab_shndx_hdr;
- pos = hdr->sh_offset + hdr->sh_size;
- amt = finfo->symbuf_count * sizeof (Elf_External_Sym_Shndx);
- if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
- || (bfd_bwrite ((PTR) finfo->symshndxbuf, amt, finfo->output_bfd)
- != amt))
- return false;
-
- hdr->sh_size += amt;
- }
-
finfo->symbuf_count = 0;
}
@@ -6781,12 +6832,7 @@ elf_link_input_bfd (finfo, input_bfd)
from discarded sections and section symbols from
removed link-once sections. Complain about relocs
against discarded sections. Zero relocs against removed
- link-once sections. We should really complain if
- anything in the final link tries to use it, but
- DWARF-based exception handling might have an entry in
- .eh_frame to describe a routine in the linkonce section,
- and it turns out to be hard to remove the .eh_frame
- entry too. FIXME. */
+ link-once sections. */
if (!finfo->info->relocateable
&& !elf_section_ignore_discarded_relocs (o))
{
@@ -6815,20 +6861,12 @@ elf_link_input_bfd (finfo, input_bfd)
|| h->root.type == bfd_link_hash_defweak)
&& elf_discarded_section (h->root.u.def.section))
{
-#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0)
{
-#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section; zeroing"),
- NULL, input_bfd, o, rel->r_offset);
-#endif
BFD_ASSERT (r_symndx != 0);
memset (rel, 0, sizeof (*rel));
}
else
-#endif
{
if (! ((*finfo->info->callbacks->undefined_symbol)
(finfo->info, h->root.root.string,
@@ -6844,23 +6882,15 @@ elf_link_input_bfd (finfo, input_bfd)
if (sec != NULL && elf_discarded_section (sec))
{
-#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0
|| (sec->flags & SEC_LINK_ONCE) != 0)
{
-#if BFD_VERSION_DATE > 20021005
- (*finfo->info->callbacks->warning)
- (finfo->info,
- _("warning: relocation against removed section"),
- NULL, input_bfd, o, rel->r_offset);
-#endif
BFD_ASSERT (r_symndx != 0);
rel->r_info
= ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
rel->r_addend = 0;
}
else
-#endif
{
boolean ok;
const char *msg
@@ -6951,6 +6981,16 @@ elf_link_input_bfd (finfo, input_bfd)
next_erel = 0;
}
+ irela->r_offset = _bfd_elf_section_offset (output_bfd,
+ finfo->info, o,
+ irela->r_offset);
+ if (irela->r_offset >= (bfd_vma) -2)
+ {
+ /* This is a reloc for a deleted entry or somesuch. */
+ memset (irela, 0, sizeof (*irela));
+ continue;
+ }
+
irela->r_offset += o->output_offset;
/* Relocs in an executable have to be virtual addresses. */
@@ -7124,19 +7164,14 @@ elf_link_input_bfd (finfo, input_bfd)
return false;
break;
case ELF_INFO_TYPE_MERGE:
- if (! (_bfd_write_merged_section
- (output_bfd, o, elf_section_data (o)->sec_info)))
+ if (! _bfd_write_merged_section (output_bfd, o,
+ elf_section_data (o)->sec_info))
return false;
break;
case ELF_INFO_TYPE_EH_FRAME:
{
- asection *ehdrsec;
-
- ehdrsec
- = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj,
- ".eh_frame_hdr");
- if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec,
- contents)))
+ if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info,
+ o, contents))
return false;
}
break;
@@ -8308,7 +8343,7 @@ elf_reloc_symbol_deleted_p (offset, cookie)
for (; rcookie->rel < rcookie->relend; rcookie->rel++)
{
- unsigned long r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+ unsigned long r_symndx;
if (! rcookie->bad_symtab)
if (rcookie->rel->r_offset > offset)
@@ -8316,6 +8351,10 @@ elf_reloc_symbol_deleted_p (offset, cookie)
if (rcookie->rel->r_offset != offset)
continue;
+ r_symndx = ELF_R_SYM (rcookie->rel->r_info);
+ if (r_symndx == SHN_UNDEF)
+ return true;
+
if (r_symndx >= rcookie->locsymcount
|| ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
{
@@ -8367,24 +8406,18 @@ elf_bfd_discard_info (output_bfd, info)
struct bfd_link_info *info;
{
struct elf_reloc_cookie cookie;
- asection *stab, *eh, *ehdr;
+ asection *stab, *eh;
Elf_Internal_Shdr *symtab_hdr;
struct elf_backend_data *bed;
bfd *abfd;
+ unsigned int count;
boolean ret = false;
- boolean strip = info->strip == strip_all || info->strip == strip_debugger;
- if (info->relocateable
- || info->traditional_format
+ if (info->traditional_format
|| info->hash->creator->flavour != bfd_target_elf_flavour
|| ! is_elf_hash_table (info))
return false;
- ehdr = NULL;
- if (elf_hash_table (info)->dynobj != NULL)
- ehdr = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
- ".eh_frame_hdr");
-
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
{
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
@@ -8395,27 +8428,22 @@ elf_bfd_discard_info (output_bfd, info)
if ((abfd->flags & DYNAMIC) != 0)
continue;
- eh = NULL;
- if (ehdr)
- {
- eh = bfd_get_section_by_name (abfd, ".eh_frame");
- if (eh && (eh->_raw_size == 0
- || bfd_is_abs_section (eh->output_section)))
- eh = NULL;
- }
+ eh = bfd_get_section_by_name (abfd, ".eh_frame");
+ if (eh != NULL
+ && (eh->_raw_size == 0
+ || bfd_is_abs_section (eh->output_section)))
+ eh = NULL;
- stab = NULL;
- if (!strip)
- {
- stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab && (stab->_raw_size == 0
- || bfd_is_abs_section (stab->output_section)))
- stab = NULL;
- }
- if ((! stab
- || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
- && ! eh
- && (strip || ! bed->elf_backend_discard_info))
+ stab = bfd_get_section_by_name (abfd, ".stab");
+ if (stab != NULL
+ && (stab->_raw_size == 0
+ || bfd_is_abs_section (stab->output_section)
+ || elf_section_data (stab)->sec_info_type != ELF_INFO_TYPE_STABS))
+ stab = NULL;
+
+ if (stab == NULL
+ && eh == NULL
+ && bed->elf_backend_discard_info == NULL)
continue;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -8424,8 +8452,7 @@ elf_bfd_discard_info (output_bfd, info)
cookie.bad_symtab = elf_bad_symtab (abfd);
if (cookie.bad_symtab)
{
- cookie.locsymcount =
- symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+ cookie.locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
cookie.extsymoff = 0;
}
else
@@ -8444,16 +8471,19 @@ elf_bfd_discard_info (output_bfd, info)
return false;
}
- if (stab)
+ if (stab != NULL)
{
- cookie.rels = (NAME(_bfd_elf,link_read_relocs)
- (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
- info->keep_memory));
- if (cookie.rels)
+ cookie.rels = NULL;
+ count = stab->reloc_count;
+ if (count != 0)
+ cookie.rels = (NAME(_bfd_elf,link_read_relocs)
+ (abfd, stab, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ info->keep_memory));
+ if (cookie.rels != NULL)
{
cookie.rel = cookie.rels;
- cookie.relend =
- cookie.rels + stab->reloc_count * bed->s->int_rels_per_ext_rel;
+ 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,
elf_reloc_symbol_deleted_p,
@@ -8464,39 +8494,32 @@ elf_bfd_discard_info (output_bfd, info)
}
}
- if (eh)
+ if (eh != NULL)
{
cookie.rels = NULL;
- cookie.rel = NULL;
- cookie.relend = NULL;
- if (eh->reloc_count)
+ count = eh->reloc_count;
+ if (count != 0)
cookie.rels = (NAME(_bfd_elf,link_read_relocs)
(abfd, eh, (PTR) NULL, (Elf_Internal_Rela *) NULL,
info->keep_memory));
- if (cookie.rels)
- {
- cookie.rel = cookie.rels;
- cookie.relend =
- cookie.rels + eh->reloc_count * bed->s->int_rels_per_ext_rel;
- }
- if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
+ 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,
elf_reloc_symbol_deleted_p,
&cookie))
- {
- /* Relocs have been edited. Ensure edited version is
- used later in relocate_section. */
- elf_section_data (eh)->relocs = cookie.rels;
- ret = true;
- }
- if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
+ ret = true;
+
+ if (cookie.rels != NULL
+ && elf_section_data (eh)->relocs != cookie.rels)
free (cookie.rels);
}
- if (bed->elf_backend_discard_info)
- {
- if (bed->elf_backend_discard_info (abfd, &cookie, info))
- ret = true;
- }
+ 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)
@@ -8508,8 +8531,10 @@ elf_bfd_discard_info (output_bfd, info)
}
}
- if (ehdr && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info, ehdr))
+ if (info->eh_frame_hdr
+ && _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
ret = true;
+
return ret;
}