aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-06 20:32:10 +0000
committerIan Lance Taylor <iant@google.com>2008-02-06 20:32:10 +0000
commitfbfba5088712eb014b9051baa71f9636359d159e (patch)
tree6836ec1f682dc1c4954429d9be124c268d530526
parent755ab8af10558c40e5090e92c46bbbd89815c292 (diff)
downloadfsf-binutils-gdb-fbfba5088712eb014b9051baa71f9636359d159e.zip
fsf-binutils-gdb-fbfba5088712eb014b9051baa71f9636359d159e.tar.gz
fsf-binutils-gdb-fbfba5088712eb014b9051baa71f9636359d159e.tar.bz2
Support creating empty output when there are no input objects.
-rw-r--r--gold/config.in9
-rwxr-xr-xgold/configure76
-rw-r--r--gold/configure.ac61
-rw-r--r--gold/configure.tgt55
-rw-r--r--gold/gold.cc20
-rw-r--r--gold/layout.cc2
-rw-r--r--gold/object.cc11
-rw-r--r--gold/object.h10
-rw-r--r--gold/parameters.h5
-rw-r--r--gold/symtab.cc4
10 files changed, 198 insertions, 55 deletions
diff --git a/gold/config.in b/gold/config.in
index 9c0db95..4dc6141 100644
--- a/gold/config.in
+++ b/gold/config.in
@@ -7,6 +7,15 @@
/* Define to do multi-threaded linking */
#undef ENABLE_THREADS
+/* Default big endian (true or false) */
+#undef GOLD_DEFAULT_BIG_ENDIAN
+
+/* Default machine code */
+#undef GOLD_DEFAULT_MACHINE
+
+/* Default size (32 or 64) */
+#undef GOLD_DEFAULT_SIZE
+
/* Define to 1 if you have the <ext/hash_map> header file. */
#undef HAVE_EXT_HASH_MAP
diff --git a/gold/configure b/gold/configure
index ef56ef5..d2006a3 100755
--- a/gold/configure
+++ b/gold/configure
@@ -1970,11 +1970,14 @@ fi
# See which specific instantiations we need.
targetobjs=
all_targets=
+default_machine=
+default_size=
+default_big_endian=
+targ_32_little=
+targ_32_big=
+targ_64_little=
+targ_64_big=
for targ in $target $canon_targets; do
- targ_32_little=
- targ_32_big=
- targ_64_little=
- targ_64_big=
if test "$targ" = "all"; then
targ_32_little=yes
targ_32_big=yes
@@ -1982,21 +1985,46 @@ for targ in $target $canon_targets; do
targ_64_big=yes
all_targets=yes
else
- case "$targ" in
- i?86-*)
- targ_32_little=yes
- targetobjs="$targetobjs i386.\$(OBJEXT)"
- ;;
- x86_64-*)
- targ_64_little=yes
- targetobjs="$targetobjs x86_64.\$(OBJEXT)"
- ;;
- *)
+ . ${srcdir}/configure.tgt
+
+ if test "$targ_obj" = "UNKNOWN"; then
{ { echo "$as_me:$LINENO: error: \"unsupported target $targ\"" >&5
echo "$as_me: error: \"unsupported target $targ\"" >&2;}
{ (exit 1); exit 1; }; }
- ;;
- esac
+ else
+ targetobjs="$targetobjs ${targ_obj}.\$(OBJEXT)"
+ if test "$targ_size" = "32"; then
+ if test "$targ_big_endian" = "false"; then
+ targ_32_little=yes
+ elif test "$targ_big_endian" = "true"; then
+ targ_32_big=yes
+ else
+ { { echo "$as_me:$LINENO: error: \"bad configure.tgt endian $targ_big_endian\"" >&5
+echo "$as_me: error: \"bad configure.tgt endian $targ_big_endian\"" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ elif test "$targ_size" = "64"; then
+ if test "$targ_big_endian" = "false"; then
+ targ_64_little=yes
+ elif test "$targ_big_endian" = "true"; then
+ targ_64_big=yes
+ else
+ { { echo "$as_me:$LINENO: error: \"bad configure.tgt endian $targ_big_endian\"" >&5
+echo "$as_me: error: \"bad configure.tgt endian $targ_big_endian\"" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ else
+ { { echo "$as_me:$LINENO: error: \"bad configure.tgt size $targ_size\"" >&5
+echo "$as_me: error: \"bad configure.tgt size $targ_size\"" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ if test "$target" = "$targ"; then
+ default_machine=$targ_machine
+ default_size=$targ_size
+ default_big_endian=$targ_big_endian
+ fi
+ fi
fi
done
@@ -2036,6 +2064,22 @@ else
fi
+
+cat >>confdefs.h <<_ACEOF
+#define GOLD_DEFAULT_MACHINE $default_machine
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GOLD_DEFAULT_SIZE $default_size
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define GOLD_DEFAULT_BIG_ENDIAN $default_big_endian
+_ACEOF
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
diff --git a/gold/configure.ac b/gold/configure.ac
index 62fdaab..c719e78 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -86,11 +86,14 @@ fi
# See which specific instantiations we need.
targetobjs=
all_targets=
+default_machine=
+default_size=
+default_big_endian=
+targ_32_little=
+targ_32_big=
+targ_64_little=
+targ_64_big=
for targ in $target $canon_targets; do
- targ_32_little=
- targ_32_big=
- targ_64_little=
- targ_64_big=
if test "$targ" = "all"; then
targ_32_little=yes
targ_32_big=yes
@@ -98,19 +101,38 @@ for targ in $target $canon_targets; do
targ_64_big=yes
all_targets=yes
else
- case "$targ" in
- i?86-*)
- targ_32_little=yes
- targetobjs="$targetobjs i386.\$(OBJEXT)"
- ;;
- x86_64-*)
- targ_64_little=yes
- targetobjs="$targetobjs x86_64.\$(OBJEXT)"
- ;;
- *)
+ . ${srcdir}/configure.tgt
+
+ if test "$targ_obj" = "UNKNOWN"; then
AC_MSG_ERROR("unsupported target $targ")
- ;;
- esac
+ else
+ targetobjs="$targetobjs ${targ_obj}.\$(OBJEXT)"
+ if test "$targ_size" = "32"; then
+ if test "$targ_big_endian" = "false"; then
+ targ_32_little=yes
+ elif test "$targ_big_endian" = "true"; then
+ targ_32_big=yes
+ else
+ AC_MSG_ERROR("bad configure.tgt endian $targ_big_endian")
+ fi
+ elif test "$targ_size" = "64"; then
+ if test "$targ_big_endian" = "false"; then
+ targ_64_little=yes
+ elif test "$targ_big_endian" = "true"; then
+ targ_64_big=yes
+ else
+ AC_MSG_ERROR("bad configure.tgt endian $targ_big_endian")
+ fi
+ else
+ AC_MSG_ERROR("bad configure.tgt size $targ_size")
+ fi
+
+ if test "$target" = "$targ"; then
+ default_machine=$targ_machine
+ default_size=$targ_size
+ default_big_endian=$targ_big_endian
+ fi
+ fi
fi
done
@@ -138,6 +160,13 @@ else
fi
AC_SUBST(TARGETOBJS)
+AC_DEFINE_UNQUOTED(GOLD_DEFAULT_MACHINE, $default_machine,
+ [Default machine code])
+AC_DEFINE_UNQUOTED(GOLD_DEFAULT_SIZE, $default_size,
+ [Default size (32 or 64)])
+AC_DEFINE_UNQUOTED(GOLD_DEFAULT_BIG_ENDIAN, $default_big_endian,
+ [Default big endian (true or false)])
+
AC_PROG_CC
AC_PROG_CXX
AC_PROG_YACC
diff --git a/gold/configure.tgt b/gold/configure.tgt
new file mode 100644
index 0000000..93615aa
--- /dev/null
+++ b/gold/configure.tgt
@@ -0,0 +1,55 @@
+# configure.tgt -- target configuration for gold -*- sh -*-
+
+# Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Ian Lance Taylor <iant@google.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# This script handles target configuration for gold. This is shell
+# code invoked by the autoconf generated configure script. Putting
+# this in a separate file lets us skip running autoconf when modifying
+# target specific information.
+
+# This file switches on the shell variable ${targ}, which is a
+# canonicalized GNU configuration triplet. It sets the following
+# shell variables:
+
+# targ_obj object file to include in the link, with no extension
+# targ_machine ELF machine code for this target
+# targ_size size of this target--32 or 64
+# targ_big_endian whether the target is big-endian--true or false
+
+# If the target is not recognized targ_obj is set to "UNKNOWN".
+
+case "$targ" in
+i?86-*)
+ targ_obj=i386
+ targ_machine=EM_386
+ targ_size=32
+ targ_big_endian=false
+ ;;
+x86_64*)
+ targ_obj=x86_64
+ targ_machine=EM_X86_64
+ targ_size=64
+ targ_big_endian=false
+ ;;
+*)
+ targ_obj=UNKNOWN
+ ;;
+esac
diff --git a/gold/gold.cc b/gold/gold.cc
index 71dac86..4b52b57 100644
--- a/gold/gold.cc
+++ b/gold/gold.cc
@@ -26,10 +26,12 @@
#include <cstdio>
#include <cstring>
#include <unistd.h>
+#include <algorithm>
#include "libiberty.h"
#include "options.h"
#include "debug.h"
+#include "target-select.h"
#include "workqueue.h"
#include "dirsearch.h"
#include "readsyms.h"
@@ -160,16 +162,24 @@ queue_middle_tasks(const General_options& options,
Layout* layout,
Workqueue* workqueue)
{
+ // We have to support the case of not seeing any input objects, and
+ // generate an empty file. Existing builds depend on being able to
+ // 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)
{
- // We had some input files, but we weren't able to open any of
- // them.
- gold_fatal(_("no input files"));
+ // 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);
}
int thread_count = options.thread_count_middle();
if (thread_count == 0)
- thread_count = input_objects->number_of_input_objects();
+ thread_count = std::max(2, input_objects->number_of_input_objects());
workqueue->set_thread_count(thread_count);
// Now we have seen all the input files.
@@ -278,7 +288,7 @@ queue_final_tasks(const General_options& options,
{
int thread_count = options.thread_count_final();
if (thread_count == 0)
- thread_count = input_objects->number_of_input_objects();
+ thread_count = std::max(2, input_objects->number_of_input_objects());
workqueue->set_thread_count(thread_count);
bool any_postprocessing_sections = layout->any_postprocessing_sections();
diff --git a/gold/layout.cc b/gold/layout.cc
index 8b17f83..faae577 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -891,7 +891,7 @@ off_t
Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
const Task* task)
{
- Target* const target = input_objects->target();
+ Target* const target = parameters->target();
target->finalize_sections(this);
diff --git a/gold/object.cc b/gold/object.cc
index 433fbc8..f82827c 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -1248,12 +1248,13 @@ Sized_relobj<size, big_endian>::get_symbol_location_info(
bool
Input_objects::add_object(Object* obj)
{
+ // Set the global target from the first object file we recognize.
Target* target = obj->target();
- if (this->target_ == NULL)
- this->target_ = target;
- else if (this->target_ != target)
+ if (!parameters->is_target_valid())
+ set_parameters_target(target);
+ else if (target != parameters->target())
{
- gold_error(_("%s: incompatible target"), obj->name().c_str());
+ obj->error(_("incompatible target"));
return false;
}
@@ -1289,8 +1290,6 @@ Input_objects::add_object(Object* obj)
}
}
- set_parameters_target(target);
-
return true;
}
diff --git a/gold/object.h b/gold/object.h
index dbe0ca1..b83d420 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -1367,8 +1367,7 @@ class Input_objects
{
public:
Input_objects()
- : relobj_list_(), dynobj_list_(), target_(NULL), sonames_(),
- system_library_directory_()
+ : relobj_list_(), dynobj_list_(), sonames_(), system_library_directory_()
{ }
// The type of the list of input relocateable objects.
@@ -1384,11 +1383,6 @@ class Input_objects
bool
add_object(Object*);
- // Get the target we should use for the output file.
- Target*
- target() const
- { return this->target_; }
-
// For each dynamic object, check whether we've seen all of its
// explicit dependencies.
void
@@ -1437,8 +1431,6 @@ class Input_objects
Relobj_list relobj_list_;
// The list of dynamic objects included in the link.
Dynobj_list dynobj_list_;
- // The target.
- Target* target_;
// SONAMEs that we have seen.
Unordered_set<std::string> sonames_;
// The directory in which we find the libc.so.
diff --git a/gold/parameters.h b/gold/parameters.h
index 2467295..67ce1e6 100644
--- a/gold/parameters.h
+++ b/gold/parameters.h
@@ -200,6 +200,11 @@ class Parameters
return this->doing_static_link_;
}
+ // Return whether the target field has been set.
+ bool
+ is_target_valid() const
+ { return this->is_target_valid_; }
+
// The target of the output file we are generating.
Target*
target() const
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 288b966..c7f6816 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1791,7 +1791,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects,
const Stringpool* dynpool,
Output_file* of) const
{
- const Target* const target = input_objects->target();
+ const Target* const target = parameters->target();
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
@@ -1966,7 +1966,7 @@ Symbol_table::warn_about_undefined_dynobj_symbol(
&& sym->shndx() == elfcpp::SHN_UNDEF
&& sym->binding() != elfcpp::STB_WEAK
&& !parameters->allow_shlib_undefined()
- && !input_objects->target()->is_defined_by_abi(sym)
+ && !parameters->target()->is_defined_by_abi(sym)
&& !input_objects->found_in_system_library_directory(sym->object()))
{
// A very ugly cast.