summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-26 22:10:32 +0000
committerIan Lance Taylor <iant@google.com>2008-02-26 22:10:32 +0000
commit50fe4f37d391fff65eb53e275b18452b54fdc1af (patch)
treed1cd29dd707604eb77094def098f55fe136fb08e
parent577a85e82c839655bd9dbaedffad1414bfe83f42 (diff)
downloadbinutils-redhat-50fe4f37d391fff65eb53e275b18452b54fdc1af.tar.gz
From Craig Silverstein: implement -z max-page-size and -z
common-page-size.
-rw-r--r--gold/i386.cc4
-rw-r--r--gold/options.cc56
-rw-r--r--gold/options.h30
-rw-r--r--gold/parameters.cc6
-rw-r--r--gold/parameters.h19
-rw-r--r--gold/target.h17
-rw-r--r--gold/x86_64.cc4
7 files changed, 117 insertions, 19 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index 8bd3f32bb2..0655f13727 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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.
diff --git a/gold/options.cc b/gold/options.cc
index c5f1edf978..8b607afe82 100644
--- a/gold/options.cc
+++ b/gold/options.cc
@@ -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.
diff --git a/gold/options.h b/gold/options.h
index 593256042f..d7dc06cd2e 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -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
@@ -577,6 +587,24 @@ class General_options
{ 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.
diff --git a/gold/parameters.cc b/gold/parameters.cc
index 5723b807dd..a53908ffc7 100644
--- a/gold/parameters.cc
+++ b/gold/parameters.cc
@@ -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;
}
diff --git a/gold/parameters.h b/gold/parameters.h
index 3bf6c5030b..136fd35b84 100644
--- a/gold/parameters.h
+++ b/gold/parameters.h
@@ -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.
diff --git a/gold/target.h b/gold/target.h
index c05c821ad2..fa18fc7a35 100644
--- a/gold/target.h
+++ b/gold/target.h
@@ -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
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index c65031e9cd..882398f487 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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.