off_t offset,
const elfcpp::Ehdr<size, big_endian>& ehdr)
: Dynobj(name, input_file, offset),
- elf_file_(this, ehdr)
+ elf_file_(this, ehdr),
+ dynsym_shndx_(-1U)
{
}
void
Sized_dynobj<size, big_endian>::find_dynsym_sections(
const unsigned char* pshdrs,
- unsigned int* pdynsym_shndx,
unsigned int* pversym_shndx,
unsigned int* pverdef_shndx,
unsigned int* pverneed_shndx,
unsigned int* pdynamic_shndx)
{
- *pdynsym_shndx = -1U;
*pversym_shndx = -1U;
*pverdef_shndx = -1U;
*pverneed_shndx = -1U;
*pdynamic_shndx = -1U;
+ unsigned int xindex_shndx = 0;
+ unsigned int xindex_link = 0;
const unsigned int shnum = this->shnum();
const unsigned char* p = pshdrs;
for (unsigned int i = 0; i < shnum; ++i, p += This::shdr_size)
switch (shdr.get_sh_type())
{
case elfcpp::SHT_DYNSYM:
- pi = pdynsym_shndx;
+ this->dynsym_shndx_ = i;
+ if (xindex_shndx > 0 && xindex_link == i)
+ {
+ Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset());
+ xindex->read_symtab_xindex<size, big_endian>(this, xindex_shndx,
+ pshdrs);
+ this->set_xindex(xindex);
+ }
+ pi = NULL;
break;
case elfcpp::SHT_GNU_versym:
pi = pversym_shndx;
case elfcpp::SHT_DYNAMIC:
pi = pdynamic_shndx;
break;
+ case elfcpp::SHT_SYMTAB_SHNDX:
+ xindex_shndx = i;
+ xindex_link = this->adjust_shndx(shdr.get_sh_link());
+ if (xindex_link == this->dynsym_shndx_)
+ {
+ Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset());
+ xindex->read_symtab_xindex<size, big_endian>(this, xindex_shndx,
+ pshdrs);
+ this->set_xindex(xindex);
+ }
+ pi = NULL;
+ break;
default:
pi = NULL;
break;
gold_assert(shdr.get_sh_type() == type);
- if (shdr.get_sh_link() != link)
+ if (this->adjust_shndx(shdr.get_sh_link()) != link)
this->error(_("unexpected link in section %u header: %u != %u"),
- shndx, shdr.get_sh_link(), link);
+ shndx, this->adjust_shndx(shdr.get_sh_link()), link);
*view = this->get_lasting_view(shdr.get_sh_offset(), shdr.get_sh_size(),
- false);
+ true, false);
*view_size = convert_to_section_size_type(shdr.get_sh_size());
*view_info = shdr.get_sh_info();
}
const off_t dynamic_size = dynamicshdr.get_sh_size();
const unsigned char* pdynamic = this->get_view(dynamicshdr.get_sh_offset(),
- dynamic_size, false);
+ dynamic_size, true, false);
- const unsigned int link = dynamicshdr.get_sh_link();
+ const unsigned int link = this->adjust_shndx(dynamicshdr.get_sh_link());
if (link != strtab_shndx)
{
if (link >= this->shnum())
}
strtab_size = strtabshdr.get_sh_size();
- strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false);
+ strtabu = this->get_view(strtabshdr.get_sh_offset(), strtab_size, false,
+ false);
}
const char* const strtab = reinterpret_cast<const char*>(strtabu);
const unsigned char* const pshdrs = sd->section_headers->data();
- unsigned int dynsym_shndx;
unsigned int versym_shndx;
unsigned int verdef_shndx;
unsigned int verneed_shndx;
unsigned int dynamic_shndx;
- this->find_dynsym_sections(pshdrs, &dynsym_shndx, &versym_shndx,
- &verdef_shndx, &verneed_shndx, &dynamic_shndx);
+ this->find_dynsym_sections(pshdrs, &versym_shndx, &verdef_shndx,
+ &verneed_shndx, &dynamic_shndx);
unsigned int strtab_shndx = -1U;
sd->symbol_names = NULL;
sd->symbol_names_size = 0;
- if (dynsym_shndx != -1U)
+ if (this->dynsym_shndx_ != -1U)
{
// Get the dynamic symbols.
- typename This::Shdr dynsymshdr(pshdrs + dynsym_shndx * This::shdr_size);
+ typename This::Shdr dynsymshdr(pshdrs
+ + this->dynsym_shndx_ * This::shdr_size);
gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM);
sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(),
- dynsymshdr.get_sh_size(), false);
+ dynsymshdr.get_sh_size(), true,
+ false);
sd->symbols_size =
convert_to_section_size_type(dynsymshdr.get_sh_size());
// Get the symbol names.
- strtab_shndx = dynsymshdr.get_sh_link();
+ strtab_shndx = this->adjust_shndx(dynsymshdr.get_sh_link());
if (strtab_shndx >= this->shnum())
{
this->error(_("invalid dynamic symbol table name index: %u"),
sd->symbol_names = this->get_lasting_view(strtabshdr.get_sh_offset(),
strtabshdr.get_sh_size(),
- false);
+ false, false);
sd->symbol_names_size =
convert_to_section_size_type(strtabshdr.get_sh_size());
unsigned int dummy;
this->read_dynsym_section(pshdrs, versym_shndx, elfcpp::SHT_GNU_versym,
- dynsym_shndx, &sd->versym, &sd->versym_size,
- &dummy);
+ this->dynsym_shndx_,
+ &sd->versym, &sd->versym_size, &dummy);
// We require that the version definition and need section link
// to the same string table as the dynamic symbol table. This
sd->symbol_names_size);
}
+// Return the Xindex structure to use for object with lots of
+// sections.
+
+template<int size, bool big_endian>
+Xindex*
+Sized_dynobj<size, big_endian>::do_initialize_xindex()
+{
+ gold_assert(this->dynsym_shndx_ != -1U);
+ Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset());
+ xindex->initialize_symtab_xindex<size, big_endian>(this, this->dynsym_shndx_);
+ return xindex;
+}
+
// Lay out the input sections for a dynamic object. We don't want to
// include sections from a dynamic object, so all that we actually do
// here is check for .gnu.warning sections.
// based on the number of symbols there are. If there are fewer
// than 3 symbols we use 1 bucket, fewer than 17 symbols we use 3
// buckets, fewer than 37 we use 17 buckets, and so forth. We never
- // use more than 32771 buckets. This is straight from the old GNU
+ // use more than 262147 buckets. This is straight from the old GNU
// linker.
static const unsigned int buckets[] =
{
1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
- 16411, 32771
+ 16411, 32771, 65537, 131101, 262147
};
const int buckets_count = sizeof buckets / sizeof buckets[0];
unsigned int symcount = hashcodes.size();
unsigned int ret = 1;
+ const double full_fraction
+ = 1.0 - parameters->options().hash_bucket_empty_fraction();
for (int i = 0; i < buckets_count; ++i)
{
- if (symcount < buckets[i])
+ if (symcount < buckets[i] * full_fraction)
break;
ret = buckets[i];
}