diff options
author | Ian Lance Taylor <ian@airs.com> | 2008-05-20 04:00:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2008-05-20 04:00:47 +0000 |
commit | 9f1d377b33ab688f86e1cc9a454d87f991d65f19 (patch) | |
tree | c1b3a61a840a01d29858641f0db6b017124501d4 /gold/layout.cc | |
parent | 3285cf2c2fa75927a67ef845d47f5eb81770ac21 (diff) | |
download | gdb-9f1d377b33ab688f86e1cc9a454d87f991d65f19.zip gdb-9f1d377b33ab688f86e1cc9a454d87f991d65f19.tar.gz gdb-9f1d377b33ab688f86e1cc9a454d87f991d65f19.tar.bz2 |
* options.h (class General_options): Add -z relro.
* layout.cc (Layout::Layout): Initialize relro_segment_.
(Layout::add_output_section_data): Return the output section.
(Layout::make_output_section): Rcognize relro sections and mark
them appropriately.
(Layout::attach_allocated_section_to_segment): Put relro sections
in a PT_GNU_RELRO segment.
(Layout::create_initial_dynamic_sections): Mark the .dynamic
section as relro.
(Layout::segment_precedes): Sort PT_GNU_RELRO segments after
PT_TLS segments.
(Layout::linkonce_mapping): Map d.rel.ro.local to
.data.rel.ro.local.
(Layout::output_section_name): Us .data.rel.ro.local for any
section which begins with that.
* layout.h (class Layout): Update add_output_section_data
declaration. Add relro_segment_ field.
* output.cc (Output_section::Output_section): Initialize is_relro_
and is_relro_local_ fields.
(Output_segment::add_output_section): Group relro sections.
(Output_segment::is_first_section_relro): New function.
(Output_segment::maximum_alignment): If there is a relro section,
align the segment to the common page size.
(Output_segment::set_section_addresses): Track whether we are
looking at relro sections. If the last section is a relro
section, align to the common page size.
(Output_segment::set_section_list_addresses): Add in_relro
parameter. Change all callers. Align to the page size when
moving from relro to non-relro section.
(Output_segment::set_offset): Align memsz of a PT_GNU_RELRO
segment.
* output.h (class Output_section): Add is_relro_ and
is_relro_local_ fields.
(Output_section::is_relro): New function.
(Output_section::set_is_relro): New function.
(Output_section::is_relro_local): New function.
(Output_section::set_is_relro_local): New function.
(class Output_segment): Update declarations.
* i386.cc (Target_i386::got_section): Mark .got section as relro.
* sparc.cc (Target_sparc::got_section): Likewise.
* x86_64.cc (Target_x86_64::got_section): Likewise.
* testsuite/relro_test_main.cc: New file.
* testsuite/relro_test.cc: New file.
* testsuite/Makefile.am (check_PROGRAMS): Add relro_test.
(relro_test_SOURCES, relro_test_DEPENDENCIES): New variables.
(relro_test_LDFLAGS, relro_test_LDADD): New variables.
(relro_test.so, relro_test_pic.o): New targets.
* testsuite/Makefile.in: Rebuild.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/gold/layout.cc b/gold/layout.cc index 07e9056..eae6679 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -90,6 +90,7 @@ Layout::Layout(const General_options& options, Script_options* script_options) special_output_list_(), section_headers_(NULL), tls_segment_(NULL), + relro_segment_(NULL), symtab_section_(NULL), symtab_xindex_(NULL), dynsym_section_(NULL), @@ -637,9 +638,10 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, return os; } -// Add POSD to an output section using NAME, TYPE, and FLAGS. +// Add POSD to an output section using NAME, TYPE, and FLAGS. Return +// the output section. -void +Output_section* Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, Output_section_data* posd) @@ -648,6 +650,7 @@ Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type, false); if (os != NULL) os->add_output_section_data(posd); + return os; } // Map section flags to segment flags. @@ -706,6 +709,23 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, || strcmp(name, ".fini_array") == 0)) os->set_may_sort_attached_input_sections(); + // With -z relro, we have to recognize the special sections by name. + // There is no other way. + if (!this->script_options_->saw_sections_clause() + && parameters->options().relro() + && type == elfcpp::SHT_PROGBITS + && (flags & elfcpp::SHF_ALLOC) != 0 + && (flags & elfcpp::SHF_WRITE) != 0) + { + if (strcmp(name, ".data.rel.ro") == 0) + os->set_is_relro(); + else if (strcmp(name, ".data.rel.ro.local") == 0) + { + os->set_is_relro(); + os->set_is_relro_local(); + } + } + // If we have already attached the sections to segments, then we // need to attach this one now. This happens for sections created // directly by the linker. @@ -831,6 +851,17 @@ Layout::attach_allocated_section_to_segment(Output_section* os) seg_flags); this->tls_segment_->add_output_section(os, seg_flags); } + + // If -z relro is in effect, and we see a relro section, we create a + // PT_GNU_RELRO segment. There can only be one such segment. + if (os->is_relro() && parameters->options().relro()) + { + gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W)); + if (this->relro_segment_ == NULL) + this->relro_segment_ = this->make_output_segment(elfcpp::PT_GNU_RELRO, + seg_flags); + this->relro_segment_->add_output_section(os, seg_flags); + } } // Make an output section for a script. @@ -901,6 +932,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab) (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), false); + this->dynamic_section_->set_is_relro(); symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -1508,12 +1540,25 @@ Layout::segment_precedes(const Output_segment* seg1, if (type2 == elfcpp::PT_LOAD && type1 != elfcpp::PT_LOAD) return false; - // We put the PT_TLS segment last, because that is where the dynamic - // linker expects to find it (this is just for efficiency; other - // positions would also work correctly). - if (type1 == elfcpp::PT_TLS && type2 != elfcpp::PT_TLS) + // We put the PT_TLS segment last except for the PT_GNU_RELRO + // segment, because that is where the dynamic linker expects to find + // it (this is just for efficiency; other positions would also work + // correctly). + if (type1 == elfcpp::PT_TLS + && type2 != elfcpp::PT_TLS + && type2 != elfcpp::PT_GNU_RELRO) + return false; + if (type2 == elfcpp::PT_TLS + && type1 != elfcpp::PT_TLS + && type1 != elfcpp::PT_GNU_RELRO) + return true; + + // We put the PT_GNU_RELRO segment last, because that is where the + // dynamic linker expects to find it (as with PT_TLS, this is just + // for efficiency). + if (type1 == elfcpp::PT_GNU_RELRO && type2 != elfcpp::PT_GNU_RELRO) return false; - if (type2 == elfcpp::PT_TLS && type1 != elfcpp::PT_TLS) + if (type2 == elfcpp::PT_GNU_RELRO && type1 != elfcpp::PT_GNU_RELRO) return true; const elfcpp::Elf_Word flags1 = seg1->flags(); @@ -2634,7 +2679,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, #define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 } const Layout::Linkonce_mapping Layout::linkonce_mapping[] = { - MAPPING_INIT("d.rel.ro", ".data.rel.ro"), // Must be before "d". + MAPPING_INIT("d.rel.ro.local", ".data.rel.ro.local"), // Before "d.rel.ro". + MAPPING_INIT("d.rel.ro", ".data.rel.ro"), // Before "d". MAPPING_INIT("t", ".text"), MAPPING_INIT("r", ".rodata"), MAPPING_INIT("d", ".data"), @@ -2736,6 +2782,9 @@ Layout::output_section_name(const char* name, size_t* plen) // initial '.', we use the name unchanged (i.e., "mysection" and // ".text" are unchanged). + // If the name starts with ".data.rel.ro.local" we use + // ".data.rel.ro.local". + // If the name starts with ".data.rel.ro" we use ".data.rel.ro". // Otherwise, we drop the second '.' and everything that comes after @@ -2749,6 +2798,13 @@ Layout::output_section_name(const char* name, size_t* plen) if (sdot == NULL) return name; + const char* const data_rel_ro_local = ".data.rel.ro.local"; + if (strncmp(name, data_rel_ro_local, strlen(data_rel_ro_local)) == 0) + { + *plen = strlen(data_rel_ro_local); + return data_rel_ro_local; + } + const char* const data_rel_ro = ".data.rel.ro"; if (strncmp(name, data_rel_ro, strlen(data_rel_ro)) == 0) { |