X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fcopy-relocs.cc;h=bb824b6a9fac312bf4688da02e4fca38c616cf30;hb=63ffd7c9131c0e9723016d33cf8d435cc508d02b;hp=1ff7ffebd69aa2e65c970300761be702aa02d0ef;hpb=ec6dfed69baea2819c0d8f6b9ba33acffd1a6c6f;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 1ff7ffebd6..bb824b6a9f 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -1,6 +1,6 @@ // copy-relocs.cc -- handle COPY relocations for gold. -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -28,25 +28,6 @@ namespace gold { -// Copy_relocs::Copy_reloc_entry methods. - -// Emit the reloc if appropriate. - -template -void -Copy_relocs::Copy_reloc_entry::emit( - Output_data_reloc* reloc_section) -{ - // If the symbol is no longer defined in a dynamic object, then we - // emitted a COPY relocation, and we do not want to emit this - // dynamic relocation. - if (this->sym_->is_from_dynobj()) - reloc_section->add_global(this->sym_, this->reloc_type_, - this->output_section_, this->relobj_, - this->shndx_, this->address_, - this->addend_); -} - // Copy_relocs methods. // Handle a relocation against a symbol which may force us to generate @@ -58,19 +39,22 @@ Copy_relocs::copy_reloc( Symbol_table* symtab, Layout* layout, Sized_symbol* sym, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int shndx, - Output_section *output_section, - const Reloc& rel, + Output_section* output_section, + unsigned int r_type, + typename elfcpp::Elf_types::Elf_Addr r_offset, + typename elfcpp::Elf_types::Elf_Swxword r_addend, Output_data_reloc* reloc_section) { if (this->need_copy_reloc(sym, object, shndx)) - this->emit_copy_reloc(symtab, layout, sym, reloc_section); + this->make_copy_reloc(symtab, layout, sym, object, reloc_section); else { // We may not need a COPY relocation. Save this relocation to // possibly be emitted later. - this->save(sym, object, shndx, output_section, rel); + this->save(sym, object, shndx, output_section, + r_type, r_offset, r_addend); } } @@ -81,7 +65,7 @@ template bool Copy_relocs::need_copy_reloc( Sized_symbol* sym, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int shndx) const { if (!parameters->options().copyreloc()) @@ -105,14 +89,46 @@ Copy_relocs::need_copy_reloc( template void Copy_relocs::emit_copy_reloc( + Symbol_table* symtab, + Sized_symbol* sym, + Output_data* posd, + off_t offset, + Output_data_reloc* reloc_section) +{ + // Define the symbol as being copied. + symtab->define_with_copy_reloc(sym, posd, offset); + + // Add the COPY relocation to the dynamic reloc section. + reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd, + offset, 0); +} + +// Make a COPY relocation for SYM and emit it. + +template +void +Copy_relocs::make_copy_reloc( Symbol_table* symtab, Layout* layout, Sized_symbol* sym, + Sized_relobj_file* object, Output_data_reloc* reloc_section) { // We should not be here if -z nocopyreloc is given. gold_assert(parameters->options().copyreloc()); + gold_assert(sym->is_from_dynobj()); + + // The symbol must not have protected visibility. + if (sym->is_protected()) + { + gold_error(_("%s: cannot make copy relocation for " + "protected symbol '%s', defined in %s"), + object->name().c_str(), + sym->name(), + sym->object()->name().c_str()); + } + typename elfcpp::Elf_types::Elf_WXword symsize = sym->symsize(); // There is no defined way to determine the required alignment of @@ -121,12 +137,32 @@ Copy_relocs::emit_copy_reloc( // is defined; presumably we do not require an alignment larger than // that. Then we reduce that alignment if the symbol is not aligned // within the section. - gold_assert(sym->is_from_dynobj()); bool is_ordinary; unsigned int shndx = sym->shndx(&is_ordinary); gold_assert(is_ordinary); - typename elfcpp::Elf_types::Elf_WXword addralign = - sym->object()->section_addralign(shndx); + typename elfcpp::Elf_types::Elf_WXword addralign; + bool is_readonly = false; + + { + // Lock the object so we can read from it. This is only called + // single-threaded from scan_relocs, so it is OK to lock. + // Unfortunately we have no way to pass in a Task token. + const Task* dummy_task = reinterpret_cast(-1); + Object* obj = sym->object(); + Task_lock_obj tl(dummy_task, obj); + addralign = obj->section_addralign(shndx); + if (parameters->options().relro()) + { + if ((obj->section_flags(shndx) & elfcpp::SHF_WRITE) == 0) + is_readonly = true; + else + { + // Symbols in .data.rel.ro should also be treated as read-only. + if (obj->section_name(shndx) == ".data.rel.ro") + is_readonly = true; + } + } + } typename Sized_symbol::Value_type value = sym->value(); while ((value & (addralign - 1)) != 0) @@ -135,17 +171,32 @@ Copy_relocs::emit_copy_reloc( // Mark the dynamic object as needed for the --as-needed option. sym->object()->set_is_needed(); - if (this->dynbss_ == NULL) + Output_data_space* dynbss; + + if (is_readonly) { - this->dynbss_ = new Output_data_space(addralign, "** dynbss"); - layout->add_output_section_data(".bss", - elfcpp::SHT_NOBITS, - elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->dynbss_, false, false, false, - false); + if (this->dynrelro_ == NULL) + { + this->dynrelro_ = new Output_data_space(addralign, "** dynrelro"); + layout->add_output_section_data(".data.rel.ro", + elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->dynrelro_, ORDER_RELRO, false); + } + dynbss = this->dynrelro_; + } + else + { + if (this->dynbss_ == NULL) + { + this->dynbss_ = new Output_data_space(addralign, "** dynbss"); + layout->add_output_section_data(".bss", + elfcpp::SHT_NOBITS, + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->dynbss_, ORDER_BSS, false); + } + dynbss = this->dynbss_; } - - Output_data_space* dynbss = this->dynbss_; if (addralign > dynbss->addralign()) dynbss->set_space_alignment(addralign); @@ -156,24 +207,7 @@ Copy_relocs::emit_copy_reloc( section_size_type offset = dynbss_size; dynbss->set_current_data_size(dynbss_size + symsize); - // Define the symbol as being copied. - symtab->define_with_copy_reloc(sym, dynbss, offset); - - // Add the COPY relocation to the dynamic reloc section. - this->add_copy_reloc(sym, offset, reloc_section); -} - -// Add a COPY relocation for SYM to RELOC_SECTION. - -template -void -Copy_relocs::add_copy_reloc( - Symbol* sym, - section_size_type offset, - Output_data_reloc* reloc_section) -{ - reloc_section->add_global(sym, this->copy_reloc_type_, this->dynbss_, - offset, 0); + this->emit_copy_reloc(symtab, sym, dynbss, offset, reloc_section); } // Save a relocation to possibly be emitted later. @@ -182,17 +216,16 @@ template void Copy_relocs::save( Symbol* sym, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int shndx, Output_section* output_section, - const Reloc& rel) + unsigned int r_type, + typename elfcpp::Elf_types::Elf_Addr r_offset, + typename elfcpp::Elf_types::Elf_Swxword r_addend) { - unsigned int reloc_type = elfcpp::elf_r_type(rel.get_r_info()); - typename elfcpp::Elf_types::Elf_Addr addend = - Reloc_types::get_reloc_addend_noerror(&rel); - this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, object, shndx, - output_section, rel.get_r_offset(), - addend)); + this->entries_.push_back(Copy_reloc_entry(sym, r_type, object, shndx, + output_section, r_offset, + r_addend)); } // Emit any saved relocs. @@ -205,7 +238,18 @@ Copy_relocs::emit( for (typename Copy_reloc_entries::iterator p = this->entries_.begin(); p != this->entries_.end(); ++p) - p->emit(reloc_section); + { + Copy_reloc_entry& entry = *p; + + // If the symbol is no longer defined in a dynamic object, then we + // emitted a COPY relocation, and we do not want to emit this + // dynamic relocation. + if (entry.sym_->is_from_dynobj()) + reloc_section->add_global_generic(entry.sym_, entry.reloc_type_, + entry.output_section_, entry.relobj_, + entry.shndx_, entry.address_, + entry.addend_); + } // We no longer need the saved information. this->entries_.clear();