From 1130c90ed7c8d1bc7b70c701b62cdbc23ac9fc01 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 23 Aug 2016 16:43:33 -0700 Subject: [gold] Implement -z stack-size option gold/ * options.h (General_options): Grok -z stack-size. * output.h (Output_segment::set_size): New method. * layout.cc (Layout::create_executable_stack_info): Renamed to ... (Layout::create_stack_segment): ... this. Always create the segment if -z stack-size was used. (Layout::set_segment_offsets): Don't call ->set_offset on the PT_GNU_STACK segment. --- gold/ChangeLog | 10 ++++++++++ gold/layout.cc | 37 ++++++++++++++++++++++++------------- gold/layout.h | 4 ++-- gold/options.h | 6 ++++-- gold/output.h | 11 +++++++++-- 5 files changed, 49 insertions(+), 19 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index ad6d691ed20..8b8c60508e3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,13 @@ +2016-08-23 Roland McGrath + + * options.h (General_options): Grok -z stack-size. + * output.h (Output_segment::set_size): New method. + * layout.cc (Layout::create_executable_stack_info): Renamed to ... + (Layout::create_stack_segment): ... this. Always create the + segment if -z stack-size was used. + (Layout::set_segment_offsets): Don't call ->set_offset on the + PT_GNU_STACK segment. + 2016-08-15 Bharathi Seshadri * options.h (General_options): Add --be8 option. diff --git a/gold/layout.cc b/gold/layout.cc index 376051df020..d14f27bddfc 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -2135,7 +2135,7 @@ void Layout::create_notes() { this->create_gold_note(); - this->create_executable_stack_info(); + this->create_stack_segment(); this->create_build_id(); } @@ -2785,7 +2785,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, if (load_seg != NULL) ehdr_start->set_output_segment(load_seg, Symbol::SEGMENT_START); else - ehdr_start->set_undefined(); + ehdr_start->set_undefined(); } // Set the file offsets of all the non-data sections we've seen so @@ -2985,25 +2985,29 @@ Layout::create_gold_note() // executable. Otherwise, if at least one input file a // .note.GNU-stack section, and some input file has no .note.GNU-stack // section, we use the target default for whether the stack should be -// executable. Otherwise, we don't generate a stack note. When -// generating a object file, we create a .note.GNU-stack section with -// the appropriate marking. When generating an executable or shared -// library, we create a PT_GNU_STACK segment. +// executable. If -z stack-size was used to set a p_memsz value for +// PT_GNU_STACK, we generate the segment regardless. Otherwise, we +// don't generate a stack note. When generating a object file, we +// create a .note.GNU-stack section with the appropriate marking. +// When generating an executable or shared library, we create a +// PT_GNU_STACK segment. void -Layout::create_executable_stack_info() +Layout::create_stack_segment() { bool is_stack_executable; if (parameters->options().is_execstack_set()) { is_stack_executable = parameters->options().is_stack_executable(); if (!is_stack_executable - && this->input_requires_executable_stack_ - && parameters->options().warn_execstack()) + && this->input_requires_executable_stack_ + && parameters->options().warn_execstack()) gold_warning(_("one or more inputs require executable stack, " - "but -z noexecstack was given")); + "but -z noexecstack was given")); } - else if (!this->input_with_gnu_stack_note_) + else if (!this->input_with_gnu_stack_note_ + && (!parameters->options().user_set_stack_size() + || parameters->options().relocatable())) return; else { @@ -3032,7 +3036,12 @@ Layout::create_executable_stack_info() int flags = elfcpp::PF_R | elfcpp::PF_W; if (is_stack_executable) flags |= elfcpp::PF_X; - this->make_output_segment(elfcpp::PT_GNU_STACK, flags); + Output_segment* seg = + this->make_output_segment(elfcpp::PT_GNU_STACK, flags); + seg->set_size(parameters->options().stack_size()); + // BFD lets targets override this default alignment, but the only + // targets that do so are ones that Gold does not support so far. + seg->set_minimum_p_align(16); } } @@ -3718,7 +3727,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, p != this->segment_list_.end(); ++p) { - if ((*p)->type() != elfcpp::PT_LOAD) + // PT_GNU_STACK was set up correctly when it was created. + if ((*p)->type() != elfcpp::PT_LOAD + && (*p)->type() != elfcpp::PT_GNU_STACK) (*p)->set_offset((*p)->type() == elfcpp::PT_GNU_RELRO ? increase_relro : 0); diff --git a/gold/layout.h b/gold/layout.h index c369fefa395..b2d699fccfc 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -1037,9 +1037,9 @@ class Layout void create_gold_note(); - // Record whether the stack must be executable. + // Record whether the stack must be executable, and a user-supplied size. void - create_executable_stack_info(); + create_stack_segment(); // Create a build ID note if needed. void diff --git a/gold/options.h b/gold/options.h index 8680635404b..a1951792c80 100644 --- a/gold/options.h +++ b/gold/options.h @@ -647,7 +647,7 @@ class General_options DEFINE_bool(apply_dynamic_relocs, options::TWO_DASHES, '\0', true, N_("Apply link-time values for dynamic relocations (default)"), N_("(aarch64 only) Do not apply link-time values " - "for dynamic relocations")); + "for dynamic relocations")); DEFINE_bool(as_needed, options::TWO_DASHES, '\0', false, N_("Only set DT_NEEDED for shared libraries if used"), @@ -1296,7 +1296,7 @@ class General_options N_("Mark output as requiring executable stack"), NULL); DEFINE_bool(global, options::DASH_Z, '\0', false, N_("Make symbols in DSO available for subsequently loaded " - "objects"), NULL); + "objects"), NULL); DEFINE_bool(initfirst, options::DASH_Z, '\0', false, N_("Mark DSO to be initialized first at runtime"), NULL); @@ -1342,6 +1342,8 @@ class General_options DEFINE_bool(relro, options::DASH_Z, '\0', DEFAULT_LD_Z_RELRO, N_("Where possible mark variables read-only after relocation"), N_("Don't mark variables read-only after relocation")); + DEFINE_uint64(stack_size, options::DASH_Z, '\0', 0, + N_("Set PT_GNU_STACK segment p_memsz to SIZE"), N_("SIZE")); DEFINE_bool(text, options::DASH_Z, '\0', false, N_("Do not permit relocations in read-only segments"), N_("Permit relocations in read-only segments (default)")); diff --git a/gold/output.h b/gold/output.h index d8a8aaaaba7..6b9186b95ea 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2499,7 +2499,7 @@ class Output_data_got : public Output_data_got_base // entry. bool add_local(Relobj* object, unsigned int sym_index, unsigned int got_type, - uint64_t addend); + uint64_t addend); // Like add_local, but use the PLT offset of the local symbol if it // has one. @@ -2643,7 +2643,7 @@ class Output_data_got : public Output_data_got_base // Create a local symbol entry plus addend. Got_entry(Relobj* object, unsigned int local_sym_index, - bool use_plt_or_tls_offset, uint64_t addend) + bool use_plt_or_tls_offset, uint64_t addend) : local_sym_index_(local_sym_index), use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend) { @@ -4796,6 +4796,13 @@ class Output_segment this->min_p_align_ = align; } + // Set the memory size of this segment. + void + set_size(uint64_t size) + { + this->memsz_ = size; + } + // Set the offset of this segment based on the section. This should // only be called for a non-PT_LOAD segment. void -- cgit v1.2.1