summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/fileread.cc31
-rw-r--r--gold/fileread.h3
-rw-r--r--gold/gold.cc11
-rw-r--r--gold/i386.cc13
-rw-r--r--gold/options.cc34
-rw-r--r--gold/options.h8
-rw-r--r--gold/target-select.cc17
-rw-r--r--gold/target-select.h12
-rw-r--r--gold/testsuite/testfile.cc4
-rw-r--r--gold/x86_64.cc13
10 files changed, 112 insertions, 34 deletions
diff --git a/gold/fileread.cc b/gold/fileread.cc
index 797b878b8a..8e11175022 100644
--- a/gold/fileread.cc
+++ b/gold/fileread.cc
@@ -698,7 +698,7 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath,
else
{
gold_assert(format == General_options::OBJECT_FORMAT_BINARY);
- ok = this->open_binary(task, name);
+ ok = this->open_binary(options, task, name);
}
if (!ok)
@@ -714,29 +714,22 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath,
// Open a file for --format binary.
bool
-Input_file::open_binary(const Task* task, const std::string& name)
+Input_file::open_binary(const General_options& options,
+ const Task* task, const std::string& name)
{
// In order to open a binary file, we need machine code, size, and
- // endianness. If we have a target already, use it, otherwise use
- // the defaults.
- elfcpp::EM machine;
- int size;
- bool big_endian;
+ // endianness. We may not have a valid target at this point, in
+ // which case we use the default target.
+ Target* target;
if (parameters->is_target_valid())
- {
- Target* target = parameters->target();
- machine = target->machine_code();
- size = target->get_size();
- big_endian = target->is_big_endian();
- }
+ target = parameters->target();
else
- {
- machine = elfcpp::GOLD_DEFAULT_MACHINE;
- size = GOLD_DEFAULT_SIZE;
- big_endian = GOLD_DEFAULT_BIG_ENDIAN;
- }
+ target = options.default_target();
- Binary_to_elf binary_to_elf(machine, size, big_endian, name);
+ Binary_to_elf binary_to_elf(target->machine_code(),
+ target->get_size(),
+ target->is_big_endian(),
+ name);
if (!binary_to_elf.convert(task))
return false;
return this->file_.open(task, name, binary_to_elf.converted_data_leak(),
diff --git a/gold/fileread.h b/gold/fileread.h
index 33c1f091e1..6a05928fb7 100644
--- a/gold/fileread.h
+++ b/gold/fileread.h
@@ -428,7 +428,8 @@ class Input_file
// Open a binary file.
bool
- open_binary(const Task* task, const std::string& name);
+ open_binary(const General_options&, const Task* task,
+ const std::string& name);
// The argument from the command line.
const Input_file_argument* input_argument_;
diff --git a/gold/gold.cc b/gold/gold.cc
index 1775db66cf..eefcb48abb 100644
--- a/gold/gold.cc
+++ b/gold/gold.cc
@@ -31,7 +31,6 @@
#include "options.h"
#include "debug.h"
-#include "target-select.h"
#include "workqueue.h"
#include "dirsearch.h"
#include "readsyms.h"
@@ -167,15 +166,7 @@ queue_middle_tasks(const General_options& options,
// pass an empty archive to the linker and get an empty object file
// out. In order to do this we need to use a default target.
if (input_objects->number_of_input_objects() == 0)
- {
- // The GOLD_xx macros are defined by the configure script.
- Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
- GOLD_DEFAULT_SIZE,
- GOLD_DEFAULT_BIG_ENDIAN,
- 0, 0);
- gold_assert(target != NULL);
- set_parameters_target(target);
- }
+ set_parameters_target(options.default_target());
int thread_count = options.thread_count_middle();
if (thread_count == 0)
diff --git a/gold/i386.cc b/gold/i386.cc
index 2d8efdd5ec..8bd3f32bb2 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -2433,6 +2433,9 @@ public:
Target*
recognize(int machine, int osabi, int abiversion);
+ Target*
+ recognize_by_name(const char* name);
+
private:
Target_i386* target_;
};
@@ -2448,6 +2451,16 @@ Target_selector_i386::recognize(int, int, int)
return this->target_;
}
+Target*
+Target_selector_i386::recognize_by_name(const char* name)
+{
+ if (strcmp(name, "elf32-i386") != 0)
+ return NULL;
+ if (this->target_ == NULL)
+ this->target_ = new Target_i386();
+ return this->target_;
+}
+
Target_selector_i386 target_selector_i386;
} // End anonymous namespace.
diff --git a/gold/options.cc b/gold/options.cc
index e83b78d6e5..db655a2e4c 100644
--- a/gold/options.cc
+++ b/gold/options.cc
@@ -30,6 +30,7 @@
#include "debug.h"
#include "script.h"
+#include "target-select.h"
#include "options.h"
namespace gold
@@ -140,7 +141,8 @@ namespace
// minimally compatible. In practice for an ELF target this would be
// the same target as the input files; that name always start with
// "elf". Non-ELF targets would be "srec", "symbolsrec", "tekhex",
-// "binary", "ihex".
+// "binary", "ihex". See also
+// General_options::default_target_settings.
gold::General_options::Object_format
string_to_object_format(const char* arg)
@@ -635,6 +637,7 @@ General_options::General_options(Script_options* script_options)
optimization_level_(0),
output_file_name_("a.out"),
output_format_(OBJECT_FORMAT_ELF),
+ output_format_string_(NULL),
is_relocatable_(false),
strip_(STRIP_NONE),
allow_shlib_undefined_(false),
@@ -678,9 +681,38 @@ General_options::define_symbol(const char* arg)
void
General_options::set_output_format(const char* arg)
{
+ this->output_format_string_ = arg;
this->output_format_ = string_to_object_format(arg);
}
+// The x86_64 kernel build converts a binary file to an object file
+// using -r --format binary --oformat elf32-i386 foo.o. In order to
+// support that for gold we support determining the default target
+// choice from the output format. We recognize names that the GNU
+// linker uses.
+
+Target*
+General_options::default_target() const
+{
+ if (this->output_format_string_ != NULL)
+ {
+ Target* target = select_target_by_name(this->output_format_string_);
+ if (target != NULL)
+ return target;
+
+ gold_error(_("unrecognized output format %s"),
+ this->output_format_string_);
+ }
+
+ // The GOLD_DEFAULT_xx macros are defined by the configure script.
+ Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
+ GOLD_DEFAULT_SIZE,
+ GOLD_DEFAULT_BIG_ENDIAN,
+ 0, 0);
+ gold_assert(target != NULL);
+ return target;
+}
+
// Handle the -z option.
void
diff --git a/gold/options.h b/gold/options.h
index d62c2c2650..c484b55e5e 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -37,6 +37,7 @@
#include <string>
#include <vector>
+#include "elfcpp.h"
#include "script.h"
namespace gold
@@ -45,6 +46,7 @@ namespace gold
class Command_line;
class Input_file_group;
class Position_dependent_options;
+class Target;
namespace options
{
@@ -157,11 +159,14 @@ class General_options
{ return this->output_file_name_; }
// --oformat: Output format.
-
Object_format
output_format() const
{ return this->output_format_; }
+ // Return the default target.
+ Target*
+ default_target() const;
+
// -r: Whether we are doing a relocatable link.
bool
is_relocatable() const
@@ -562,6 +567,7 @@ class General_options
int optimization_level_;
const char* output_file_name_;
Object_format output_format_;
+ const char* output_format_string_;
bool is_relocatable_;
Strip strip_;
bool allow_shlib_undefined_;
diff --git a/gold/target-select.cc b/gold/target-select.cc
index 0cfa02bc6a..fdf7b89636 100644
--- a/gold/target-select.cc
+++ b/gold/target-select.cc
@@ -50,7 +50,7 @@ Target_selector::Target_selector(int machine, int size, bool is_big_endian)
// Find the target for an ELF file.
-extern Target*
+Target*
select_target(int machine, int size, bool is_big_endian, int osabi,
int abiversion)
{
@@ -69,4 +69,19 @@ select_target(int machine, int size, bool is_big_endian, int osabi,
return NULL;
}
+// Find a target using a BFD name. This is used to support the
+// --oformat option.
+
+Target*
+select_target_by_name(const char* name)
+{
+ for (Target_selector* p = target_selectors; p != NULL; p = p->next())
+ {
+ Target* ret = p->recognize_by_name(name);
+ if (ret != NULL)
+ return ret;
+ }
+ return NULL;
+}
+
} // End namespace gold.
diff --git a/gold/target-select.h b/gold/target-select.h
index da27bd4df9..5757d5b5d7 100644
--- a/gold/target-select.h
+++ b/gold/target-select.h
@@ -49,7 +49,13 @@ class Target_selector
// If we can handle this target, return a pointer to a target
// structure. The size and endianness are known.
- virtual Target* recognize(int machine, int osabi, int abiversion) = 0;
+ virtual Target*
+ recognize(int machine, int osabi, int abiversion) = 0;
+
+ // If NAME matches the target, return a pointer to a target
+ // structure.
+ virtual Target*
+ recognize_by_name(const char* name) = 0;
// Return the next Target_selector in the linked list.
Target_selector*
@@ -84,6 +90,10 @@ class Target_selector
extern Target* select_target(int machine, int size, bool big_endian,
int osabi, int abiversion);
+// Select a target using a BFD name.
+
+extern Target* select_target_by_name(const char* name);
+
} // End namespace gold.
#endif // !defined(GOLD_TARGET_SELECT_H)
diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc
index 3c98937502..24c30f52c4 100644
--- a/gold/testsuite/testfile.cc
+++ b/gold/testsuite/testfile.cc
@@ -176,6 +176,10 @@ class Target_selector_test : public Target_selector
return NULL;
}
+
+ Target*
+ recognize_by_name(const char*)
+ { return NULL; }
};
// Register the test target selectors. These don't need to be
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index d5869dc5f6..c65031e9cd 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -2223,6 +2223,9 @@ public:
Target*
recognize(int machine, int osabi, int abiversion);
+ Target*
+ recognize_by_name(const char*);
+
private:
Target_x86_64* target_;
};
@@ -2238,6 +2241,16 @@ Target_selector_x86_64::recognize(int, int, int)
return this->target_;
}
+Target*
+Target_selector_x86_64::recognize_by_name(const char* name)
+{
+ if (strcmp(name, "elf64-x86-64") != 0)
+ return NULL;
+ if (this->target_ == NULL)
+ this->target_ = new Target_x86_64();
+ return this->target_;
+}
+
Target_selector_x86_64 target_selector_x86_64;
} // End anonymous namespace.