[gold] Implement -z stack-size option
authorRoland McGrath <mcgrathr@google.com>
Tue, 23 Aug 2016 23:43:33 +0000 (16:43 -0700)
committerRoland McGrath <mcgrathr@google.com>
Wed, 24 Aug 2016 00:15:53 +0000 (17:15 -0700)
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
gold/layout.cc
gold/layout.h
gold/options.h
gold/output.h

index ad6d691ed2013f87a3de8ce1ff6f44b64c7ea17e..8b8c60508e3e4c4ca5bb13cfc2e29be01d3f04a3 100644 (file)
@@ -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.
index 376051df02073bdd3ad0cd4048dd2b5cfd68ccc4..d14f27bddfcf48d1465e60cf0f6889c85ce5bb05 100644 (file)
@@ -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);
index c369fefa395ea104485d96e40ce91593a4554387..b2d699fccfc9b7242f0e9a8cc7eb0567a6059200 100644 (file)
@@ -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
index 8680635404bab8a0f9d94840cb1c702e976ed3d7..a1951792c80774e014bee83ee015597775219843 100644 (file)
@@ -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)"));
index d8a8aaaaba762bcd4c4a0c64f5b482c592227021..6b9186b95ead7188ef37c895f4f006f17095881c 100644 (file)
@@ -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