| Index: gold/symtab.cc
|
| ===================================================================
|
| --- a/gold/symtab.cc
|
| +++ b/gold/symtab.cc
|
| @@ -527,7 +527,8 @@
|
| : saw_undefined_(0), offset_(0), table_(count), namepool_(),
|
| forwarders_(), commons_(), tls_commons_(), small_commons_(),
|
| large_commons_(), forced_locals_(), warnings_(),
|
| - version_script_(version_script), gc_(NULL), icf_(NULL)
|
| + version_script_(version_script), gc_(NULL), icf_(NULL),
|
| + global_got_index_((unsigned int)-1)
|
| {
|
| namepool_.reserve(count);
|
| }
|
| @@ -2353,17 +2354,38 @@
|
| ++this->saw_undefined_;
|
| }
|
|
|
| +bool got_offset_compare(Symbol* sym1, Symbol* sym2)
|
| +{
|
| + return sym1->got_offset(0) < sym2->got_offset(0);
|
| +}
|
| +
|
| +// Returns true if symbol is external global symbol.
|
| +
|
| +bool is_external_symbol(Symbol* sym)
|
| +{
|
| + return ((!sym->has_dynsym_index() && sym->has_got_offset(0))
|
| + && (!sym->final_value_is_known()
|
| + || (parameters->options().output_is_position_independent())));
|
| +}
|
| +
|
| // Set the dynamic symbol indexes. INDEX is the index of the first
|
| // global dynamic symbol. Pointers to the symbols are stored into the
|
| // vector SYMS. The names are added to DYNPOOL. This returns an
|
| // updated dynamic symbol index.
|
|
|
| +// [MIPS] The dynamic symbol table is divided into local and global parts.
|
| +// The global part of the dynamic symbol table is further divided into two
|
| +// parts: symbols that do not have GOT entries associated with them and
|
| +// symbols that do have GOT entries associated with them.
|
| unsigned int
|
| Symbol_table::set_dynsym_indexes(unsigned int index,
|
| std::vector<Symbol*>* syms,
|
| Stringpool* dynpool,
|
| Versions* versions)
|
| {
|
| + std::vector<Symbol*> externals;
|
| + int i;
|
| +
|
| for (Symbol_table_type::iterator p = this->table_.begin();
|
| p != this->table_.end();
|
| ++p)
|
| @@ -2376,6 +2398,10 @@
|
|
|
| if (!sym->should_add_dynsym_entry(this))
|
| sym->set_dynsym_index(-1U);
|
| + else if (is_external_symbol(sym))
|
| + {
|
| + externals.push_back(sym);
|
| + }
|
| else if (!sym->has_dynsym_index())
|
| {
|
| sym->set_dynsym_index(index);
|
| @@ -2395,10 +2421,49 @@
|
| }
|
| }
|
|
|
| - // Finish up the versions. In some cases this may add new dynamic
|
| - // symbols.
|
| + // At the end of dynamic symbol table place global symbols that has
|
| + // .got entry.
|
| + std::sort(externals.begin(), externals.end(), got_offset_compare);
|
| + for (i = 0; (unsigned int)i < externals.size(); i++)
|
| + {
|
| + Symbol* sym = externals[i];
|
| +
|
| + if (sym->has_dynsym_index())
|
| + continue;
|
| +
|
| + // Record any version information.
|
| + if (sym->version() != NULL)
|
| + versions->record_version(this, dynpool, sym);
|
| + }
|
| +
|
| index = versions->finalize(this, index, syms);
|
|
|
| + // Set index of the first external symbol that has .got entry.
|
| + this->global_got_index_ = index;
|
| +
|
| + for (i = 0; (unsigned int)i < externals.size(); i++)
|
| + {
|
| + Symbol* sym = externals[i];
|
| +
|
| + if (sym->has_dynsym_index())
|
| + continue;
|
| +
|
| + sym->set_dynsym_index(index);
|
| + ++index;
|
| + syms->push_back(sym);
|
| + dynpool->add(sym->name(), false, NULL);
|
| +
|
| + // If the symbol is defined in a dynamic object and is
|
| + // referenced in a regular object, then mark the dynamic
|
| + // object as needed. This is used to implement --as-needed.
|
| + if (sym->is_from_dynobj() && sym->in_reg())
|
| + sym->object()->set_is_needed();
|
| + }
|
| +
|
| + // If there are no global symbols with .got entry set value to -1.
|
| + if (this->global_got_index_ == index)
|
| + this->global_got_index_ = (unsigned int)-1;
|
| +
|
| return index;
|
| }
|
|
|
| @@ -3580,6 +3645,40 @@
|
| elfcpp::Elf_types<64>::Elf_Addr value);
|
| #endif
|
|
|
| +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
|
| +template
|
| +void
|
| +Sized_symbol<32>::init_output_data(
|
| + const char* name,
|
| + const char* version,
|
| + Output_data* od,
|
| + Value_type value,
|
| + Size_type symsize,
|
| + elfcpp::STT type,
|
| + elfcpp::STB binding,
|
| + elfcpp::STV visibility,
|
| + unsigned char nonvis,
|
| + bool offset_is_from_end,
|
| + bool is_predefined);
|
| +#endif
|
| +
|
| +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
|
| +template
|
| +void
|
| +Sized_symbol<64>::init_output_data(
|
| + const char* name,
|
| + const char* version,
|
| + Output_data* od,
|
| + Value_type value,
|
| + Size_type symsize,
|
| + elfcpp::STT type,
|
| + elfcpp::STB binding,
|
| + elfcpp::STV visibility,
|
| + unsigned char nonvis,
|
| + bool offset_is_from_end,
|
| + bool is_predefined);
|
| +#endif
|
| +
|
| #ifdef HAVE_TARGET_32_LITTLE
|
| template
|
| void
|
|
|