X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fcopy-relocs.cc;h=bb824b6a9fac312bf4688da02e4fca38c616cf30;hb=2da4b788f7a80ed9589d0e8856584e9dfa2813ff;hp=92c5aeaad3f9ffe4003755c6d3259a52b47127d3;hpb=83896202bf93a490c4b8e6a222903d5797e16b32;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 92c5aeaad3..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, 2011 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_generic(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 @@ -61,16 +42,19 @@ Copy_relocs::copy_reloc( 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, Output_data_reloc* reloc_section) { if (this->need_copy_reloc(sym, object, shndx)) - this->make_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); } } @@ -127,11 +111,24 @@ 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 @@ -140,11 +137,11 @@ Copy_relocs::make_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; + bool is_readonly = false; { // Lock the object so we can read from it. This is only called @@ -154,6 +151,17 @@ Copy_relocs::make_copy_reloc( 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(); @@ -163,16 +171,32 @@ Copy_relocs::make_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_, ORDER_BSS, 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); @@ -195,14 +219,13 @@ Copy_relocs::save( 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. @@ -215,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();