From Craig Silverstein: implement -z max-page-size and -z
authorIan Lance Taylor <iant@google.com>
Tue, 26 Feb 2008 22:10:32 +0000 (22:10 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 26 Feb 2008 22:10:32 +0000 (22:10 +0000)
common-page-size.

gold/i386.cc
gold/options.cc
gold/options.h
gold/parameters.cc
gold/parameters.h
gold/target.h
gold/x86_64.cc

index 8bd3f32bb24386751d05308ee34308ba76cbc0b0..0655f137276dca665e39152f65d6e68f32cd59a7 100644 (file)
@@ -366,8 +366,8 @@ const Target::Target_info Target_i386::i386_info =
   true,                        // is_default_stack_executable
   "/usr/lib/libc.so.1",        // dynamic_linker
   0x08048000,          // default_text_segment_address
-  0x1000,              // abi_pagesize
-  0x1000               // common_pagesize
+  0x1000,              // abi_pagesize (overridable by -z max-page-size)
+  0x1000               // common_pagesize (overridable by -z common-page-size)
 };
 
 // Get the GOT section, creating it if necessary.
index c5f1edf97824b0abe4fc795569407c465de6d9dc..8b607afe827e7d73f06a3a6db7079854a794ec0c 100644 (file)
@@ -109,8 +109,13 @@ struct options::One_z_option
   // The name of the option.
   const char* name;
 
-  // The member function in General_options called to record it.
-  void (General_options::*set)(bool);
+  // The member function in General_options called to record an option
+  // which does not take an argument.
+  void (General_options::*set_noarg)(bool);
+
+  // The member function in General_options called to record an option
+  // which does take an argument.
+  void (General_options::*set_arg)(const char*);
 };
 
 // We have a separate table for --debug options.
@@ -593,7 +598,9 @@ options::Command_line_options::options[] =
   GENERAL_ARG('z', NULL,
              N_("Subcommands as follows:\n\
     -z execstack              Mark output as requiring executable stack\n\
-    -z noexecstack            Mark output as not requiring executable stack"),
+    -z noexecstack            Mark output as not requiring executable stack\n\
+    -z max-page-size=SIZE     Set maximum page size to SIZE\n\
+    -z common-page-size=SIZE  Set common page size to SIZE"),
              N_("-z SUBCOMMAND"), ONE_DASH,
              &General_options::handle_z_option),
 
@@ -618,8 +625,10 @@ const int options::Command_line_options::options_size =
 const options::One_z_option
 options::Command_line_options::z_options[] =
 {
-  { "execstack", &General_options::set_execstack },
-  { "noexecstack", &General_options::set_noexecstack },
+  { "execstack", &General_options::set_execstack, NULL },
+  { "noexecstack", &General_options::set_noexecstack, NULL },
+  { "max-page-size", NULL, &General_options::set_max_page_size },
+  { "common-page-size", NULL, &General_options::set_common_page_size }
 };
 
 const int options::Command_line_options::z_options_size =
@@ -670,6 +679,8 @@ General_options::General_options(Script_options* script_options)
     thread_count_middle_(0),
     thread_count_final_(0),
     execstack_(EXECSTACK_FROM_INPUT),
+    max_page_size_(0),
+    common_page_size_(0),
     debug_(0),
     script_options_(script_options)
 {
@@ -731,21 +742,42 @@ General_options::default_target() const
 void
 General_options::handle_z_option(const char* arg)
 {
+  // ARG may be a word, like "noexec", or it may be an option in its
+  // own right, like "max-page-size=SIZE".
+  const char* argarg = strchr(arg, '=');   // the argument to the -z argument
+  int arglen;
+  if (argarg)
+    {
+      arglen = argarg - arg;
+      argarg++;
+    }
+  else
+    arglen = strlen(arg);
+
   const int z_options_size = options::Command_line_options::z_options_size;
   const gold::options::One_z_option* z_options =
     gold::options::Command_line_options::z_options;
   for (int i = 0; i < z_options_size; ++i)
     {
-      if (strcmp(arg, z_options[i].name) == 0)
+      if (memcmp(arg, z_options[i].name, arglen) == 0
+          && z_options[i].name[arglen] == '\0')
        {
-         (this->*(z_options[i].set))(true);
-         return;
-       }
+          if (z_options[i].set_noarg && argarg)
+            gold::gold_fatal(_("-z subcommand does not take an argument: %s\n"),
+                             z_options[i].name);
+          else if (z_options[i].set_arg && !argarg)
+            gold::gold_fatal(_("-z subcommand requires an argument: %s\n"),
+                             z_options[i].name);
+          else if (z_options[i].set_arg)
+            (this->*(z_options[i].set_arg))(argarg);
+          else
+            (this->*(z_options[i].set_noarg))(true);
+          return;
+        }
     }
 
-  fprintf(stderr, _("%s: unrecognized -z subcommand: %s\n"),
-         program_name, arg);
-  ::exit(EXIT_FAILURE);
+  gold::gold_fatal(_("%s: unrecognized -z subcommand: %s\n"),
+                   program_name, arg);
 }
 
 // Handle the --debug option.
index 593256042fbe5235bd5b37c24d03d5a7db781848..d7dc06cd2e1e4fb8af534676151b23d6293c1c9c 100644 (file)
@@ -319,6 +319,16 @@ class General_options
   is_stack_executable() const
   { return this->execstack_ == EXECSTACK_YES; }
 
+  // -z max-page-size
+  uint64_t
+  max_page_size() const
+  { return this->max_page_size_; }
+
+  // -z common-page-size
+  uint64_t
+  common_page_size() const
+  { return this->common_page_size_; }
+
   // --debug
   unsigned int
   debug() const
@@ -576,6 +586,24 @@ class General_options
   set_noexecstack(bool)
   { this->execstack_ = EXECSTACK_NO; }
 
+  void
+  set_max_page_size(const char* arg)
+  {
+    char* endptr;
+    this->max_page_size_ = strtoull(arg, &endptr, 0);
+    if (*endptr != '\0' || this->max_page_size_ == 0)
+      gold_fatal(_("invalid max-page-size: %s"), arg);
+  }
+
+  void
+  set_common_page_size(const char* arg)
+  {
+    char* endptr;
+    this->common_page_size_ = strtoull(arg, &endptr, 0);
+    if (*endptr != '\0' || this->common_page_size_ == 0)
+      gold_fatal(_("invalid common-page-size: %s"), arg);
+  }
+
   void
   set_debug(unsigned int flags)
   { this->debug_ = flags; }
@@ -622,6 +650,8 @@ class General_options
   int thread_count_middle_;
   int thread_count_final_;
   Execstack execstack_;
+  uint64_t max_page_size_;
+  uint64_t common_page_size_;
   unsigned int debug_;
   // Some options can also be set from linker scripts.  Those are
   // stored here.
index 5723b807dd09031087ab3dca4232d74319ff71ac..a53908ffc7cb80c51a3a194aa44a4646bb2a53ed 100644 (file)
@@ -38,7 +38,8 @@ Parameters::Parameters(Errors* errors)
     symbolic_(false), demangle_(false), detect_odr_violations_(false),
     optimization_level_(0), export_dynamic_(false), debug_(0),
     is_doing_static_link_valid_(false), doing_static_link_(false),
-    is_target_valid_(false), target_(NULL)
+    is_target_valid_(false), target_(NULL), size_(0), is_big_endian_(false),
+    max_page_size_(0), common_page_size_(0)
 {
 }
 
@@ -74,6 +75,9 @@ Parameters::set_from_options(const General_options* options)
   else
     this->strip_ = STRIP_NONE;
 
+  this->max_page_size_ = options->max_page_size();
+  this->common_page_size_ = options->common_page_size();
+
   this->options_valid_ = true;
 }
 
index 3bf6c5030b0d424db663baf8cf366312b6b22298..136fd35b84565994b56bd22abfa4fba1eea8a62c 100644 (file)
@@ -230,6 +230,22 @@ class Parameters
     return this->is_big_endian_;
   }
 
+  // The maximum page size
+  uint64_t
+  max_page_size() const
+  {
+    gold_assert(this->is_target_valid_);
+    return this->max_page_size_;
+  }
+
+  // The common page size
+  uint64_t
+  common_page_size() const
+  {
+    gold_assert(this->is_target_valid_);
+    return this->common_page_size_;
+  }
+
   // Set values recorded from options.
   void
   set_from_options(const General_options*);
@@ -313,6 +329,9 @@ class Parameters
   int size_;
   // Whether the output file is big endian.
   bool is_big_endian_;
+  // The maximum page size and common page size
+  int max_page_size_;
+  int common_page_size_;
 };
 
 // This is a global variable.
index c05c821ad2a81d9e59091e2426a72df0d00924a3..fa18fc7a356a1e49647a2d4d3dba10b81c8469b3 100644 (file)
@@ -34,6 +34,7 @@
 #define GOLD_TARGET_H
 
 #include "elfcpp.h"
+#include "parameters.h"
 
 namespace gold
 {
@@ -103,12 +104,24 @@ class Target
   // Return the ABI specified page size.
   uint64_t
   abi_pagesize() const
-  { return this->pti_->abi_pagesize; }
+  {
+    if (parameters->max_page_size() > 0)
+      return parameters->max_page_size();
+    else
+      return this->pti_->abi_pagesize;
+  }
 
   // Return the common page size used on actual systems.
   uint64_t
   common_pagesize() const
-  { return this->pti_->common_pagesize; }
+  {
+    if (parameters->common_page_size() > 0)
+      return std::min(parameters->common_page_size(),
+                     this->abi_pagesize());
+    else
+      return std::min(this->pti_->common_pagesize,
+                     this->abi_pagesize());
+  }
 
   // If we see some object files with .note.GNU-stack sections, and
   // some objects files without them, this returns whether we should
index c65031e9cdcba07ffda5605608f8938c4b28e922..882398f487adf98ea1b18405c42ccb62f697167f 100644 (file)
@@ -360,8 +360,8 @@ const Target::Target_info Target_x86_64::x86_64_info =
   true,                        // is_default_stack_executable
   "/lib/ld64.so.1",     // program interpreter
   0x400000,            // default_text_segment_address
-  0x1000,              // abi_pagesize
-  0x1000               // common_pagesize
+  0x1000,              // abi_pagesize (overridable by -z max-page-size)
+  0x1000               // common_pagesize (overridable by -z common-page-size)
 };
 
 // Get the GOT section, creating it if necessary.