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 |