X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Foutput.cc;h=077e2c4481ecb8445028c773eba51506846e957e;hb=712ec27916b5604d29d928dec060fd1ba0fd9edb;hp=29cca5dc35c4b7afa81074a7e5a2d9fe8a839155;hpb=4b95cf5c0c75d6efc1b2f96af72317aecca079f1;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/output.cc b/gold/output.cc index 29cca5dc35..077e2c4481 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1,6 +1,6 @@ // output.cc -- manage the output file for gold -// Copyright (C) 2006-2014 Free Software Foundation, Inc. +// Copyright (C) 2006-2016 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -1252,6 +1252,19 @@ Output_data_reloc_base os->set_should_link_to_dynsym(); } +// Standard relocation writer, which just calls Output_reloc::write(). + +template +struct Output_reloc_writer +{ + typedef Output_reloc Output_reloc_type; + typedef std::vector Relocs; + + static void + write(typename Relocs::const_iterator p, unsigned char* pov) + { p->write(pov); } +}; + // Write out relocation data. template @@ -1259,32 +1272,8 @@ void Output_data_reloc_base::do_write( Output_file* of) { - const off_t off = this->offset(); - const off_t oview_size = this->data_size(); - unsigned char* const oview = of->get_output_view(off, oview_size); - - if (this->sort_relocs()) - { - gold_assert(dynamic); - std::sort(this->relocs_.begin(), this->relocs_.end(), - Sort_relocs_comparison()); - } - - unsigned char* pov = oview; - for (typename Relocs::const_iterator p = this->relocs_.begin(); - p != this->relocs_.end(); - ++p) - { - p->write(pov); - pov += reloc_size; - } - - gold_assert(pov - oview == oview_size); - - of->write_output_view(off, oview_size, oview); - - // We no longer need the relocation entries. - this->relocs_.clear(); + typedef Output_reloc_writer Writer; + this->do_write_generic(of); } // Class Output_relocatable_relocs. @@ -1437,7 +1426,7 @@ Output_data_got::Got_entry::write( val = parameters->target().plt_address_for_local(object, lsi); else { - uint64_t lval = object->local_symbol_value(lsi, 0); + uint64_t lval = object->local_symbol_value(lsi, this->addend_); val = convert_types(lval); if (this->use_plt_or_tls_offset_ && is_tls) val += parameters->target().tls_offset_for_local(object, lsi, @@ -1548,6 +1537,27 @@ Output_data_got::add_local( return true; } +// Add an entry for a local symbol plus ADDEND to the GOT. This returns +// true if this is a new GOT entry, false if the symbol already has a GOT +// entry. + +template +bool +Output_data_got::add_local( + Relobj* object, + unsigned int symndx, + unsigned int got_type, + uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return false; + + unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx, + false, addend)); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + return true; +} + // Like add_local, but use the PLT offset. template @@ -1586,6 +1596,27 @@ Output_data_got::add_local_with_rel( rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0); } +// Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic +// relocation of type R_TYPE for the GOT entry. + +template +void +Output_data_got::add_local_with_rel( + Relobj* object, + unsigned int symndx, + unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return; + + unsigned int got_offset = this->add_got_entry(Got_entry()); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, + addend); +} + // Add a pair of entries for a local symbol to the GOT, and add // a dynamic relocation of type R_TYPE using the section symbol of // the output section to which input section SHNDX maps, on the first. @@ -1612,6 +1643,32 @@ Output_data_got::add_local_pair_with_rel( rel_dyn->add_output_section_generic(os, r_type, this, got_offset, 0); } +// Add a pair of entries for a local symbol plus ADDEND to the GOT, and add +// a dynamic relocation of type R_TYPE using the section symbol of +// the output section to which input section SHNDX maps, on the first. +// The first got entry will have a value of zero, the second the +// value of the local symbol. +template +void +Output_data_got::add_local_pair_with_rel( + Relobj* object, + unsigned int symndx, + unsigned int shndx, + unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return; + + unsigned int got_offset = + this->add_got_entry_pair(Got_entry(), + Got_entry(object, symndx, false, addend)); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + Output_section* os = object->output_section(shndx); + rel_dyn->add_output_section_generic(os, r_type, this, got_offset, addend); +} + // Add a pair of entries for a local symbol to the GOT, and add // a dynamic relocation of type R_TYPE using STN_UNDEF on the first. // The first got entry will have a value of zero, the second the @@ -1796,6 +1853,10 @@ Output_data_dynamic::Dynamic_entry::write( val = pool->get_offset(this->u_.str); break; + case DYNAMIC_CUSTOM: + val = parameters->target().dynamic_tag_custom_value(this->tag_); + break; + default: val = this->u_.od->address() + this->offset_; break; @@ -2197,18 +2258,6 @@ Output_section::Input_section::output_offset( } } -// Return whether this is the merge section for the input section -// SHNDX in OBJECT. - -inline bool -Output_section::Input_section::is_merge_section_for(const Relobj* object, - unsigned int shndx) const -{ - if (this->is_input_section()) - return false; - return this->u2_.posd->is_merge_section_for(object, shndx); -} - // Write out the data. We don't have to do anything for an input // section--they are handled via Object::relocate--but this is where // we write out the data for an Output_section_data. @@ -2632,6 +2681,10 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t addralign, bool keeps_input_sections) { + // We cannot merge sections with entsize == 0. + if (entsize == 0) + return false; + bool is_string = (flags & elfcpp::SHF_STRINGS) != 0; // We cannot restore merged input section states. @@ -2690,9 +2743,6 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, this->lookup_maps_->add_merge_section(msp, pomb); } - // Add input section to new merge section and link input section to new - // merge section in map. - this->lookup_maps_->add_merge_input_section(object, shndx, pomb); return true; } else @@ -2849,17 +2899,15 @@ Output_section::update_flags_for_input_section(elfcpp::Elf_Xword flags) // Find the merge section into which an input section with index SHNDX in // OBJECT has been added. Return NULL if none found. -Output_section_data* +const Output_section_data* Output_section::find_merge_section(const Relobj* object, unsigned int shndx) const { - if (!this->lookup_maps_->is_valid()) - this->build_lookup_maps(); - return this->lookup_maps_->find_merge_section(object, shndx); + return object->find_merge_section(shndx); } -// Build the lookup maps for merge and relaxed sections. This is needs -// to be declared as a const methods so that it is callable with a const +// Build the lookup maps for relaxed sections. This needs +// to be declared as a const method so that it is callable with a const // Output_section pointer. The method only updates states of the maps. void @@ -2870,24 +2918,7 @@ Output_section::build_lookup_maps() const p != this->input_sections_.end(); ++p) { - if (p->is_merge_section()) - { - Output_merge_base* pomb = p->output_merge_base(); - Merge_section_properties msp(pomb->is_string(), pomb->entsize(), - pomb->addralign()); - this->lookup_maps_->add_merge_section(msp, pomb); - for (Output_merge_base::Input_sections::const_iterator is = - pomb->input_sections_begin(); - is != pomb->input_sections_end(); - ++is) - { - const Const_section_id& csid = *is; - this->lookup_maps_->add_merge_input_section(csid.first, - csid.second, pomb); - } - - } - else if (p->is_relaxed_input_section()) + if (p->is_relaxed_input_section()) { Output_relaxed_input_section* poris = p->relaxed_input_section(); this->lookup_maps_->add_relaxed_input_section(poris->relobj(), @@ -2927,7 +2958,10 @@ Output_section::is_input_address_mapped(const Relobj* object, { section_offset_type output_offset; bool found = posd->output_offset(object, shndx, offset, &output_offset); - gold_assert(found); + // By default we assume that the address is mapped. See comment at the + // end. + if (!found) + return true; return output_offset != -1; } @@ -3037,6 +3071,10 @@ Output_section::find_starting_output_address(const Relobj* object, unsigned int shndx, uint64_t* paddr) const { + const Output_section_data* data = this->find_merge_section(object, shndx); + if (data == NULL) + return false; + // FIXME: This becomes a bottle-neck if we have many relaxed sections. // Looking up the merge section map does not always work as we sometimes // find a merge section without its address set. @@ -3051,7 +3089,7 @@ Output_section::find_starting_output_address(const Relobj* object, // method to get the output offset of input offset 0. // Unfortunately we don't know for sure that input offset 0 is // mapped at all. - if (p->is_merge_section_for(object, shndx)) + if (!p->is_input_section() && p->output_section_data() == data) { *paddr = addr; return true; @@ -3202,18 +3240,17 @@ class Output_section::Input_section_sort_entry { public: Input_section_sort_entry() - : input_section_(), index_(-1U), section_has_name_(false), - section_name_() + : input_section_(), index_(-1U), section_name_() { } Input_section_sort_entry(const Input_section& input_section, unsigned int index, - bool must_sort_attached_input_sections) - : input_section_(input_section), index_(index), - section_has_name_(input_section.is_input_section() - || input_section.is_relaxed_input_section()) + bool must_sort_attached_input_sections, + const char* output_section_name) + : input_section_(input_section), index_(index), section_name_() { - if (this->section_has_name_ + if ((input_section.is_input_section() + || input_section.is_relaxed_input_section()) && must_sort_attached_input_sections) { // This is only called single-threaded from Layout::finalize, @@ -3229,6 +3266,12 @@ class Output_section::Input_section_sort_entry // Layout::layout if this becomes a speed problem. this->section_name_ = obj->section_name(input_section.shndx()); } + else if (input_section.is_output_section_data() + && must_sort_attached_input_sections) + { + // For linker-generated sections, use the output section name. + this->section_name_.assign(output_section_name); + } } // Return the Input_section. @@ -3248,16 +3291,10 @@ class Output_section::Input_section_sort_entry return this->index_; } - // Whether there is a section name. - bool - section_has_name() const - { return this->section_has_name_; } - // The section name. const std::string& section_name() const { - gold_assert(this->section_has_name_); return this->section_name_; } @@ -3266,7 +3303,6 @@ class Output_section::Input_section_sort_entry bool has_priority() const { - gold_assert(this->section_has_name_); return this->section_name_.find('.', 1) != std::string::npos; } @@ -3276,7 +3312,6 @@ class Output_section::Input_section_sort_entry unsigned int get_priority() const { - gold_assert(this->section_has_name_); bool is_ctors; if (is_prefix_of(".ctors.", this->section_name_.c_str()) || is_prefix_of(".dtors.", this->section_name_.c_str())) @@ -3335,9 +3370,6 @@ class Output_section::Input_section_sort_entry Input_section input_section_; // The index of this Input_section in the original list. unsigned int index_; - // Whether this Input_section has a section name--it won't if this - // is some random Output_section_data. - bool section_has_name_; // The section name if there is one. std::string section_name_; }; @@ -3373,16 +3405,6 @@ Output_section::Input_section_sort_compare::operator()( return s1.index() < s2.index(); } - // We sort all the sections with no names to the end. - if (!s1.section_has_name() || !s2.section_has_name()) - { - if (s1.section_has_name()) - return true; - if (s2.section_has_name()) - return false; - return s1.index() < s2.index(); - } - // A section with a priority follows a section without a priority. bool s1_has_priority = s1.has_priority(); bool s2_has_priority = s2.has_priority(); @@ -3414,16 +3436,6 @@ Output_section::Input_section_sort_init_fini_compare::operator()( const Output_section::Input_section_sort_entry& s1, const Output_section::Input_section_sort_entry& s2) const { - // We sort all the sections with no names to the end. - if (!s1.section_has_name() || !s2.section_has_name()) - { - if (s1.section_has_name()) - return true; - if (s2.section_has_name()) - return false; - return s1.index() < s2.index(); - } - // A section without a priority follows a section with a priority. // This is the reverse of .ctors and .dtors sections. bool s1_has_priority = s1.has_priority(); @@ -3499,16 +3511,6 @@ Output_section::Input_section_sort_section_prefix_special_ordering_compare const Output_section::Input_section_sort_entry& s1, const Output_section::Input_section_sort_entry& s2) const { - // We sort all the sections with no names to the end. - if (!s1.section_has_name() || !s2.section_has_name()) - { - if (s1.section_has_name()) - return true; - if (s2.section_has_name()) - return false; - return s1.index() < s2.index(); - } - // Some input section names have special ordering requirements. int o1 = Layout::special_ordering_of_input_section(s1.section_name().c_str()); int o2 = Layout::special_ordering_of_input_section(s2.section_name().c_str()); @@ -3535,16 +3537,6 @@ Output_section::Input_section_sort_section_name_compare const Output_section::Input_section_sort_entry& s1, const Output_section::Input_section_sort_entry& s2) const { - // We sort all the sections with no names to the end. - if (!s1.section_has_name() || !s2.section_has_name()) - { - if (s1.section_has_name()) - return true; - if (s2.section_has_name()) - return false; - return s1.index() < s2.index(); - } - // We sort by name. int compare = s1.section_name().compare(s2.section_name()); if (compare != 0) @@ -3568,7 +3560,7 @@ Output_section::update_section_layout( if (p->is_input_section() || p->is_relaxed_input_section()) { - Object* obj = (p->is_input_section() + Relobj* obj = (p->is_input_section() ? p->relobj() : p->relaxed_input_section()->relobj()); unsigned int shndx = p->shndx(); @@ -3612,7 +3604,8 @@ Output_section::sort_attached_input_sections() p != this->input_sections_.end(); ++p, ++i) sort_list.push_back(Input_section_sort_entry(*p, i, - this->must_sort_attached_input_sections())); + this->must_sort_attached_input_sections(), + this->name())); // Sort the input sections. if (this->must_sort_attached_input_sections()) @@ -3922,20 +3915,7 @@ Output_section::add_script_input_section(const Input_section& sis) // Update fast lookup maps if necessary. if (this->lookup_maps_->is_valid()) { - if (sis.is_merge_section()) - { - Output_merge_base* pomb = sis.output_merge_base(); - Merge_section_properties msp(pomb->is_string(), pomb->entsize(), - pomb->addralign()); - this->lookup_maps_->add_merge_section(msp, pomb); - for (Output_merge_base::Input_sections::const_iterator p = - pomb->input_sections_begin(); - p != pomb->input_sections_end(); - ++p) - this->lookup_maps_->add_merge_input_section(p->first, p->second, - pomb); - } - else if (sis.is_relaxed_input_section()) + if (sis.is_relaxed_input_section()) { Output_relaxed_input_section* poris = sis.relaxed_input_section(); this->lookup_maps_->add_relaxed_input_section(poris->relobj(), @@ -4213,8 +4193,7 @@ Output_segment::is_first_section_relro() const { for (int i = 0; i < static_cast(ORDER_MAX); ++i) { - if (i == static_cast(ORDER_TLS_DATA) - || i == static_cast(ORDER_TLS_BSS)) + if (i == static_cast(ORDER_TLS_BSS)) continue; const Output_data_list* pdl = &this->output_lists_[i]; if (!pdl->empty()) @@ -4342,18 +4321,18 @@ Output_segment::set_section_addresses(const Target* target, align = max_align; in_tls = false; } - relro_size = align_address(relro_size, align); // Ignore the size of the .tbss section. if ((*p)->is_section_flag_set(elfcpp::SHF_TLS) && (*p)->is_section_type(elfcpp::SHT_NOBITS)) continue; + relro_size = align_address(relro_size, align); if ((*p)->is_address_valid()) relro_size += (*p)->data_size(); else { // FIXME: This could be faster. - (*p)->set_address_and_file_offset(addr + relro_size, - off + relro_size); + (*p)->set_address_and_file_offset(relro_size, + relro_size); relro_size += (*p)->data_size(); (*p)->reset_address_and_file_offset(); } @@ -4373,11 +4352,12 @@ Output_segment::set_section_addresses(const Target* target, // Align to offset N such that (N + RELRO_SIZE) % PAGE_ALIGN == 0. uint64_t desired_align = page_align - (aligned_size % page_align); - if (desired_align < *poff % page_align) - *poff += page_align - *poff % page_align; - *poff += desired_align - *poff % page_align; - addr += *poff - orig_off; - orig_off = *poff; + if (desired_align < off % page_align) + off += page_align; + off += desired_align - off % page_align; + addr += off - orig_off; + orig_off = off; + *poff = off; } if (!reset && this->are_addresses_set_)