From fbfba5088712eb014b9051baa71f9636359d159e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 6 Feb 2008 20:32:10 +0000 Subject: [PATCH] Support creating empty output when there are no input objects. --- gold/config.in | 9 ++++++ gold/configure | 76 ++++++++++++++++++++++++++++++++++++---------- gold/configure.ac | 61 +++++++++++++++++++++++++++---------- gold/configure.tgt | 55 +++++++++++++++++++++++++++++++++ gold/gold.cc | 20 +++++++++--- gold/layout.cc | 2 +- gold/object.cc | 11 +++---- gold/object.h | 10 +----- gold/parameters.h | 5 +++ gold/symtab.cc | 4 +-- 10 files changed, 198 insertions(+), 55 deletions(-) create mode 100644 gold/configure.tgt diff --git a/gold/config.in b/gold/config.in index 9c0db951f17..4dc61414155 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 header file. */ #undef HAVE_EXT_HASH_MAP diff --git a/gold/configure b/gold/configure index ef56ef5e3b3..d2006a3d532 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 62fdaab4de9..c719e785341 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 00000000000..93615aa0d38 --- /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 . + +# 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 71dac861798..4b52b570abc 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -26,10 +26,12 @@ #include #include #include +#include #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 8b17f83ab4f..faae577336c 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 433fbc842c5..f82827c3b2f 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1248,12 +1248,13 @@ Sized_relobj::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 dbe0ca1390e..b83d420f65c 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 sonames_; // The directory in which we find the libc.so. diff --git a/gold/parameters.h b/gold/parameters.h index 2467295c857..67ce1e6eff9 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 288b9669661..c7f68166a46 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::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. -- 2.30.2