mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 04:29:49 +00:00
* 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.
This commit is contained in:
parent
3285cf2c2f
commit
9f1d377b33
@ -1,3 +1,54 @@
|
||||
2008-05-19 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2008-05-16 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* output.cc (Output_segment::add_output_section): Remove front
|
||||
|
17
gold/i386.cc
17
gold/i386.cc
@ -426,18 +426,23 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
|
||||
|
||||
this->got_ = new Output_data_got<32, false>();
|
||||
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||
this->got_);
|
||||
Output_section* os;
|
||||
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
(elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE),
|
||||
this->got_);
|
||||
os->set_is_relro();
|
||||
|
||||
// The old GNU linker creates a .got.plt section. We just
|
||||
// create another set of data in the .got section. Note that we
|
||||
// always create a PLT if we create a GOT, although the PLT
|
||||
// might be empty.
|
||||
this->got_plt_ = new Output_data_space(4);
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||
this->got_plt_);
|
||||
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
(elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE),
|
||||
this->got_plt_);
|
||||
os->set_is_relro();
|
||||
|
||||
// The first three entries are reserved.
|
||||
this->got_plt_->set_current_data_size(3 * 4);
|
||||
|
@ -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)
|
||||
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_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)
|
||||
{
|
||||
|
@ -158,7 +158,7 @@ class Layout
|
||||
|
||||
// Add an Output_section_data to the layout. This is used for
|
||||
// special sections like the GOT section.
|
||||
void
|
||||
Output_section*
|
||||
add_output_section_data(const char* name, elfcpp::Elf_Word type,
|
||||
elfcpp::Elf_Xword flags,
|
||||
Output_section_data*);
|
||||
@ -636,6 +636,8 @@ class Layout
|
||||
Output_section_headers* section_headers_;
|
||||
// A pointer to the PT_TLS segment if there is one.
|
||||
Output_segment* tls_segment_;
|
||||
// A pointer to the PT_GNU_RELRO segment if there is one.
|
||||
Output_segment* relro_segment_;
|
||||
// The SHT_SYMTAB output section.
|
||||
Output_section* symtab_section_;
|
||||
// The SHT_SYMTAB_SHNDX for the regular symbol table if there is one.
|
||||
|
@ -811,6 +811,9 @@ class General_options
|
||||
DEFINE_bool(nodump, options::DASH_Z, '\0', false,
|
||||
N_("Mark DSO not available to dldump"),
|
||||
NULL);
|
||||
DEFINE_bool(relro, options::DASH_Z, '\0', false,
|
||||
N_("Where possible mark variables read-only after relocation"),
|
||||
N_("Don't mark variables read-only after relocation"));
|
||||
|
||||
public:
|
||||
typedef options::Dir_list Dir_list;
|
||||
|
@ -1737,6 +1737,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
|
||||
may_sort_attached_input_sections_(false),
|
||||
must_sort_attached_input_sections_(false),
|
||||
attached_input_sections_are_sorted_(false),
|
||||
is_relro_(false),
|
||||
is_relro_local_(false),
|
||||
tls_offset_(0)
|
||||
{
|
||||
// An unallocated section has no address. Forcing this means that
|
||||
@ -2645,7 +2647,7 @@ Output_segment::add_output_section(Output_section* os,
|
||||
{
|
||||
sawtls = true;
|
||||
// Put a NOBITS section after the first TLS section.
|
||||
// But a PROGBITS section after the first TLS/PROGBITS
|
||||
// Put a PROGBITS section after the first TLS/PROGBITS
|
||||
// section.
|
||||
insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS);
|
||||
}
|
||||
@ -2669,6 +2671,28 @@ Output_segment::add_output_section(Output_section* os,
|
||||
// location in the section list.
|
||||
}
|
||||
|
||||
// For the PT_GNU_RELRO segment, we need to group relro sections,
|
||||
// and we need to put them before any non-relro sections. Also,
|
||||
// relro local sections go before relro non-local sections.
|
||||
if (parameters->options().relro() && os->is_relro())
|
||||
{
|
||||
gold_assert(pdl == &this->output_data_);
|
||||
Output_segment::Output_data_list::iterator p;
|
||||
for (p = pdl->begin(); p != pdl->end(); ++p)
|
||||
{
|
||||
if (!(*p)->is_section())
|
||||
break;
|
||||
|
||||
Output_section* pos = (*p)->output_section();
|
||||
if (!pos->is_relro()
|
||||
|| (os->is_relro_local() && !pos->is_relro_local()))
|
||||
break;
|
||||
}
|
||||
|
||||
pdl->insert(p, os);
|
||||
return;
|
||||
}
|
||||
|
||||
pdl->push_back(os);
|
||||
}
|
||||
|
||||
@ -2703,6 +2727,16 @@ Output_segment::add_initial_output_data(Output_data* od)
|
||||
this->output_data_.push_front(od);
|
||||
}
|
||||
|
||||
// Return whether the first data section is a relro section.
|
||||
|
||||
bool
|
||||
Output_segment::is_first_section_relro() const
|
||||
{
|
||||
return (!this->output_data_.empty()
|
||||
&& this->output_data_.front()->is_section()
|
||||
&& this->output_data_.front()->output_section()->is_relro());
|
||||
}
|
||||
|
||||
// Return the maximum alignment of the Output_data in Output_segment.
|
||||
|
||||
uint64_t
|
||||
@ -2720,6 +2754,17 @@ Output_segment::maximum_alignment()
|
||||
if (addralign > this->max_align_)
|
||||
this->max_align_ = addralign;
|
||||
|
||||
// If -z relro is in effect, and the first section in this
|
||||
// segment is a relro section, then the segment must be aligned
|
||||
// to at least the common page size. This ensures that the
|
||||
// PT_GNU_RELRO segment will start at a page boundary.
|
||||
if (parameters->options().relro() && this->is_first_section_relro())
|
||||
{
|
||||
addralign = parameters->target().common_pagesize();
|
||||
if (addralign > this->max_align_)
|
||||
this->max_align_ = addralign;
|
||||
}
|
||||
|
||||
this->is_max_align_known_ = true;
|
||||
}
|
||||
|
||||
@ -2792,11 +2837,15 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
|
||||
|
||||
bool in_tls = false;
|
||||
|
||||
bool in_relro = (parameters->options().relro()
|
||||
&& this->is_first_section_relro());
|
||||
|
||||
off_t orig_off = *poff;
|
||||
this->offset_ = orig_off;
|
||||
|
||||
addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
|
||||
addr, poff, pshndx, &in_tls);
|
||||
addr, poff, pshndx, &in_tls,
|
||||
&in_relro);
|
||||
this->filesz_ = *poff - orig_off;
|
||||
|
||||
off_t off = *poff;
|
||||
@ -2804,7 +2853,7 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
|
||||
uint64_t ret = this->set_section_list_addresses(layout, reset,
|
||||
&this->output_bss_,
|
||||
addr, poff, pshndx,
|
||||
&in_tls);
|
||||
&in_tls, &in_relro);
|
||||
|
||||
// If the last section was a TLS section, align upward to the
|
||||
// alignment of the TLS segment, so that the overall size of the TLS
|
||||
@ -2815,6 +2864,14 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
|
||||
*poff = align_address(*poff, segment_align);
|
||||
}
|
||||
|
||||
// If all the sections were relro sections, align upward to the
|
||||
// common page size.
|
||||
if (in_relro)
|
||||
{
|
||||
uint64_t page_align = parameters->target().common_pagesize();
|
||||
*poff = align_address(*poff, page_align);
|
||||
}
|
||||
|
||||
this->memsz_ = *poff - orig_off;
|
||||
|
||||
// Ignore the file offset adjustments made by the BSS Output_data
|
||||
@ -2832,7 +2889,7 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
|
||||
Output_data_list* pdl,
|
||||
uint64_t addr, off_t* poff,
|
||||
unsigned int* pshndx,
|
||||
bool* in_tls)
|
||||
bool* in_tls, bool* in_relro)
|
||||
{
|
||||
off_t startoff = *poff;
|
||||
|
||||
@ -2883,6 +2940,19 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a non-relro section after a relro section,
|
||||
// align it to a common page boundary so that the dynamic
|
||||
// linker has a page to mark as read-only.
|
||||
if (*in_relro
|
||||
&& (!(*p)->is_section()
|
||||
|| !(*p)->output_section()->is_relro()))
|
||||
{
|
||||
uint64_t page_align = parameters->target().common_pagesize();
|
||||
if (page_align > align)
|
||||
align = page_align;
|
||||
*in_relro = false;
|
||||
}
|
||||
|
||||
off = align_address(off, align);
|
||||
(*p)->set_address_and_file_offset(addr + (off - startoff), off);
|
||||
}
|
||||
@ -2976,6 +3046,16 @@ Output_segment::set_offset()
|
||||
gold_assert(this->vaddr_ == align_address(this->vaddr_, segment_align));
|
||||
this->memsz_ = align_address(this->memsz_, segment_align);
|
||||
}
|
||||
|
||||
// If this is a RELRO segment, align the memory size. The code in
|
||||
// set_section_list ensures that the section after the RELRO segment
|
||||
// is aligned to give us room.
|
||||
if (this->type_ == elfcpp::PT_GNU_RELRO)
|
||||
{
|
||||
uint64_t page_align = parameters->target().common_pagesize();
|
||||
gold_assert(this->vaddr_ == align_address(this->vaddr_, page_align));
|
||||
this->memsz_ = align_address(this->memsz_, page_align);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the TLS offsets of the sections in the PT_TLS segment.
|
||||
|
@ -2028,6 +2028,29 @@ class Output_section : public Output_data
|
||||
set_must_sort_attached_input_sections()
|
||||
{ this->must_sort_attached_input_sections_ = true; }
|
||||
|
||||
// Return whether this section holds relro data--data which has
|
||||
// dynamic relocations but which may be marked read-only after the
|
||||
// dynamic relocations have been completed.
|
||||
bool
|
||||
is_relro() const
|
||||
{ return this->is_relro_; }
|
||||
|
||||
// Record that this section holds relro data.
|
||||
void
|
||||
set_is_relro()
|
||||
{ this->is_relro_ = true; }
|
||||
|
||||
// True if this section holds relro local data--relro data for which
|
||||
// the dynamic relocations are all RELATIVE relocations.
|
||||
bool
|
||||
is_relro_local() const
|
||||
{ return this->is_relro_local_; }
|
||||
|
||||
// Record that this section holds relro local data.
|
||||
void
|
||||
set_is_relro_local()
|
||||
{ this->is_relro_local_ = true; }
|
||||
|
||||
// Return whether this section should be written after all the input
|
||||
// sections are complete.
|
||||
bool
|
||||
@ -2626,6 +2649,10 @@ class Output_section : public Output_data
|
||||
// True if the input sections attached to this output section have
|
||||
// already been sorted.
|
||||
bool attached_input_sections_are_sorted_ : 1;
|
||||
// True if this section holds relro data.
|
||||
bool is_relro_ : 1;
|
||||
// True if this section holds relro local data.
|
||||
bool is_relro_local_ : 1;
|
||||
// For SHT_TLS sections, the offset of this section relative to the base
|
||||
// of the TLS segment.
|
||||
uint64_t tls_offset_;
|
||||
@ -2785,11 +2812,15 @@ class Output_segment
|
||||
static uint64_t
|
||||
maximum_alignment_list(const Output_data_list*);
|
||||
|
||||
// Return whether the first data section is a relro section.
|
||||
bool
|
||||
is_first_section_relro() const;
|
||||
|
||||
// Set the section addresses in an Output_data_list.
|
||||
uint64_t
|
||||
set_section_list_addresses(const Layout*, bool reset, Output_data_list*,
|
||||
uint64_t addr, off_t* poff, unsigned int* pshndx,
|
||||
bool* in_tls);
|
||||
bool* in_tls, bool* in_relro);
|
||||
|
||||
// Return the number of Output_sections in an Output_data_list.
|
||||
unsigned int
|
||||
|
@ -1001,9 +1001,12 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab,
|
||||
|
||||
this->got_ = new Output_data_got<size, big_endian>();
|
||||
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||
this->got_);
|
||||
Output_section* os;
|
||||
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
(elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE),
|
||||
this->got_);
|
||||
os->set_is_relro();
|
||||
|
||||
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
|
||||
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
|
||||
|
@ -782,6 +782,16 @@ protected_2_DEPENDENCIES = gcctestdir/ld protected_1.so
|
||||
protected_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
||||
protected_2_LDADD = protected_1.so
|
||||
|
||||
check_PROGRAMS += relro_test
|
||||
relro_test_SOURCES = relro_test_main.cc
|
||||
relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so
|
||||
relro_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
||||
relro_test_LDADD = relro_test.so
|
||||
relro_test.so: gcctestdir/ld relro_test_pic.o
|
||||
$(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o
|
||||
relro_test_pic.o: relro_test.cc
|
||||
$(CXXCOMPILE) -c -fpic -o $@ $<
|
||||
|
||||
check_PROGRAMS += script_test_1
|
||||
script_test_1_SOURCES = script_test_1.cc
|
||||
script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
||||
|
@ -228,9 +228,9 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = ver_test ver_test_2 \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6 ver_test_8 \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1 protected_2 \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1 script_test_2 \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms binary_test \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test script_test_1 \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test script_test_3
|
||||
@GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \
|
||||
@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
|
||||
@GCC_FALSE@ $(am__DEPENDENCIES_1)
|
||||
@ -346,6 +346,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_8$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_2$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms$(EXEEXT) \
|
||||
@ -514,6 +515,10 @@ am__protected_2_SOURCES_DIST = protected_main_1.cc protected_3.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.$(OBJEXT) \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_3.$(OBJEXT)
|
||||
protected_2_OBJECTS = $(am_protected_2_OBJECTS)
|
||||
am__relro_test_SOURCES_DIST = relro_test_main.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_test_OBJECTS = \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT)
|
||||
relro_test_OBJECTS = $(am_relro_test_OBJECTS)
|
||||
am__script_test_1_SOURCES_DIST = script_test_1.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_1_OBJECTS = \
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1.$(OBJEXT)
|
||||
@ -760,9 +765,9 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
|
||||
$(initpri1_SOURCES) $(justsyms_SOURCES) many_sections_r_test.c \
|
||||
$(many_sections_test_SOURCES) $(object_unittest_SOURCES) \
|
||||
$(protected_1_SOURCES) $(protected_2_SOURCES) \
|
||||
$(script_test_1_SOURCES) $(script_test_2_SOURCES) \
|
||||
script_test_3.c $(tls_pic_test_SOURCES) \
|
||||
$(tls_shared_gd_to_ie_test_SOURCES) \
|
||||
$(relro_test_SOURCES) $(script_test_1_SOURCES) \
|
||||
$(script_test_2_SOURCES) script_test_3.c \
|
||||
$(tls_pic_test_SOURCES) $(tls_shared_gd_to_ie_test_SOURCES) \
|
||||
$(tls_shared_gnu2_gd_to_ie_test_SOURCES) \
|
||||
$(tls_shared_gnu2_test_SOURCES) $(tls_shared_ie_test_SOURCES) \
|
||||
$(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \
|
||||
@ -808,7 +813,7 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
|
||||
$(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \
|
||||
many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \
|
||||
$(object_unittest_SOURCES) $(am__protected_1_SOURCES_DIST) \
|
||||
$(am__protected_2_SOURCES_DIST) \
|
||||
$(am__protected_2_SOURCES_DIST) $(am__relro_test_SOURCES_DIST) \
|
||||
$(am__script_test_1_SOURCES_DIST) \
|
||||
$(am__script_test_2_SOURCES_DIST) script_test_3.c \
|
||||
$(am__tls_pic_test_SOURCES_DIST) \
|
||||
@ -1304,6 +1309,10 @@ binary_unittest_SOURCES = binary_unittest.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_DEPENDENCIES = gcctestdir/ld protected_1.so
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_2_LDADD = protected_1.so
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_SOURCES = relro_test_main.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDADD = relro_test.so
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_SOURCES = script_test_1.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t
|
||||
@ -1468,6 +1477,9 @@ protected_1$(EXEEXT): $(protected_1_OBJECTS) $(protected_1_DEPENDENCIES)
|
||||
protected_2$(EXEEXT): $(protected_2_OBJECTS) $(protected_2_DEPENDENCIES)
|
||||
@rm -f protected_2$(EXEEXT)
|
||||
$(CXXLINK) $(protected_2_LDFLAGS) $(protected_2_OBJECTS) $(protected_2_LDADD) $(LIBS)
|
||||
relro_test$(EXEEXT): $(relro_test_OBJECTS) $(relro_test_DEPENDENCIES)
|
||||
@rm -f relro_test$(EXEEXT)
|
||||
$(CXXLINK) $(relro_test_LDFLAGS) $(relro_test_OBJECTS) $(relro_test_LDADD) $(LIBS)
|
||||
script_test_1$(EXEEXT): $(script_test_1_OBJECTS) $(script_test_1_DEPENDENCIES)
|
||||
@rm -f script_test_1$(EXEEXT)
|
||||
$(CXXLINK) $(script_test_1_LDFLAGS) $(script_test_1_OBJECTS) $(script_test_1_LDADD) $(LIBS)
|
||||
@ -1627,6 +1639,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_1.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_2.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_3.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relro_test_main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2a.Po@am__quote@
|
||||
@ -2191,6 +2204,10 @@ uninstall-am: uninstall-info-am
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_3_pic.o: protected_3.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test.so: gcctestdir/ld relro_test_pic.o
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_pic.o: relro_test.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2.o: justsyms_2.cc
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2r.o: justsyms_2.o gcctestdir/ld $(srcdir)/justsyms.t
|
||||
|
114
gold/testsuite/relro_test.cc
Normal file
114
gold/testsuite/relro_test.cc
Normal file
@ -0,0 +1,114 @@
|
||||
// relro_test.cc -- test -z relro for gold
|
||||
|
||||
// Copyright 2008 Free Software Foundation, Inc.
|
||||
// Written by Ian Lance Taylor <iant@google.com>.
|
||||
|
||||
// This file is part of gold.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
|
||||
#include <cassert>
|
||||
#include <csignal>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// This code is put into a shared library linked with -z relro.
|
||||
|
||||
// i1 and i2 are not relro variables.
|
||||
int i1 = 1;
|
||||
static int i2 = 2;
|
||||
|
||||
// P1 is a global relro variable.
|
||||
int* const p1 = &i1;
|
||||
|
||||
// P2 is a local relro variable.
|
||||
int* const p2 = &i2;
|
||||
|
||||
// Test symbol addresses.
|
||||
|
||||
bool
|
||||
t1()
|
||||
{
|
||||
void* i1addr = static_cast<void*>(&i1);
|
||||
void* i2addr = static_cast<void*>(&i2);
|
||||
const void* p1addr = static_cast<const void*>(&p1);
|
||||
const void* p2addr = static_cast<const void*>(&p2);
|
||||
|
||||
// The relro variables should precede the non-relro variables in the
|
||||
// memory image.
|
||||
assert(i1addr > p1addr);
|
||||
assert(i1addr > p2addr);
|
||||
assert(i2addr > p1addr);
|
||||
assert(i2addr > p2addr);
|
||||
|
||||
// The relro variables should not be on the same page as the
|
||||
// non-relro variables.
|
||||
const size_t page_size = getpagesize();
|
||||
uintptr_t i1page = reinterpret_cast<uintptr_t>(i1addr) & ~ (page_size - 1);
|
||||
uintptr_t i2page = reinterpret_cast<uintptr_t>(i2addr) & ~ (page_size - 1);
|
||||
uintptr_t p1page = reinterpret_cast<uintptr_t>(p1addr) & ~ (page_size - 1);
|
||||
uintptr_t p2page = reinterpret_cast<uintptr_t>(p2addr) & ~ (page_size - 1);
|
||||
assert(i1page != p1page);
|
||||
assert(i1page != p2page);
|
||||
assert(i2page != p1page);
|
||||
assert(i2page != p2page);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// A signal handler for SIGSEGV.
|
||||
|
||||
extern "C"
|
||||
void
|
||||
sigsegv_handler(int)
|
||||
{
|
||||
throw 0;
|
||||
}
|
||||
|
||||
// Use a separate function to throw the exception, so that we don't
|
||||
// need to use -fnon-call-exceptions.
|
||||
|
||||
void f2() __attribute__ ((noinline));
|
||||
void
|
||||
f2()
|
||||
{
|
||||
int** pp1 = const_cast<int**>(&p1);
|
||||
*pp1 = &i2;
|
||||
|
||||
// We shouldn't get here--the assignment to *pp1 should write to
|
||||
// memory which the dynamic linker marked as read-only, giving us a
|
||||
// SIGSEGV, causing sigsegv_handler to be invoked, to throw past us.
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// Changing a relro variable should give us a SIGSEGV.
|
||||
|
||||
bool
|
||||
t2()
|
||||
{
|
||||
signal(SIGSEGV, sigsegv_handler);
|
||||
|
||||
try
|
||||
{
|
||||
f2();
|
||||
return false;
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
assert(i == 0);
|
||||
return true;
|
||||
}
|
||||
}
|
33
gold/testsuite/relro_test_main.cc
Normal file
33
gold/testsuite/relro_test_main.cc
Normal file
@ -0,0 +1,33 @@
|
||||
// relro_test_main.cc -- test -z relro for gold, main function
|
||||
|
||||
// Copyright 2008 Free Software Foundation, Inc.
|
||||
// Written by Ian Lance Taylor <iant@google.com>.
|
||||
|
||||
// This file is part of gold.
|
||||
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
|
||||
#include <cassert>
|
||||
|
||||
extern bool t1();
|
||||
extern bool t2();
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
assert(t1());
|
||||
assert(t2());
|
||||
}
|
@ -435,18 +435,23 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
|
||||
|
||||
this->got_ = new Output_data_got<64, false>();
|
||||
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||
this->got_);
|
||||
Output_section* os;
|
||||
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
(elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE),
|
||||
this->got_);
|
||||
os->set_is_relro();
|
||||
|
||||
// The old GNU linker creates a .got.plt section. We just
|
||||
// create another set of data in the .got section. Note that we
|
||||
// always create a PLT if we create a GOT, although the PLT
|
||||
// might be empty.
|
||||
this->got_plt_ = new Output_data_space(8);
|
||||
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||
this->got_plt_);
|
||||
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
|
||||
(elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE),
|
||||
this->got_plt_);
|
||||
os->set_is_relro();
|
||||
|
||||
// The first three entries are reserved.
|
||||
this->got_plt_->set_current_data_size(3 * 8);
|
||||
|
Loading…
Reference in New Issue
Block a user