summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <mcgrathr@google.com>2016-08-23 16:43:33 -0700
committerRoland McGrath <mcgrathr@google.com>2016-08-23 17:15:53 -0700
commit1130c90ed7c8d1bc7b70c701b62cdbc23ac9fc01 (patch)
tree3f6a853a52a853553a008e273183dbb233613291
parent4ba25152ff03e835bbbb2512ea71b7fefe3b7e89 (diff)
downloadbinutils-gdb-1130c90ed7c8d1bc7b70c701b62cdbc23ac9fc01.tar.gz
[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.
-rw-r--r--gold/ChangeLog10
-rw-r--r--gold/layout.cc37
-rw-r--r--gold/layout.h4
-rw-r--r--gold/options.h6
-rw-r--r--gold/output.h11
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 <roland@hack.frob.com>
+
+ * 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 <bseshadr@cisco.com>
* 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