Chromium Code Reviews| 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,29 @@ |
| ++this->saw_undefined_; |
| } |
| +bool got_offset_compare(Symbol* sym1, Symbol* sym2) |
| +{ |
| + return sym1->got_offset(0) < sym2->got_offset(0); |
| +} |
| + |
| // 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; |
|
robertm
2012/05/11 21:50:50
move "*" to left
|
| + int i; |
| + |
| for (Symbol_table_type::iterator p = this->table_.begin(); |
| p != this->table_.end(); |
| ++p) |
| @@ -2376,7 +2389,13 @@ |
| if (!sym->should_add_dynsym_entry(this)) |
| sym->set_dynsym_index(-1U); |
| - else if (!sym->has_dynsym_index()) |
| + else if((!sym->has_dynsym_index() && sym->has_got_offset(0)) |
|
robertm
2012/05/11 21:50:50
This condition is complex enough that it might be
|
| + && (!sym->final_value_is_known() |
| + || (parameters->options().output_is_position_independent()))) |
| + { |
| + externals.push_back(sym); |
| + } |
| + else if(!sym->has_dynsym_index()) |
| { |
| sym->set_dynsym_index(index); |
| ++index; |
| @@ -2395,10 +2414,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 +3638,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 |