From 0dfbdef4c43cfe12bb3e2505ebe5acc651a35c98 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 28 Feb 2008 20:35:39 +0000 Subject: [PATCH] Support -d/--define-common. --- gold/gold.cc | 4 +--- gold/object.cc | 2 +- gold/options.cc | 16 +++++++++++++++- gold/options.h | 22 ++++++++++++++++++++++ gold/script-c.h | 5 +++++ gold/script.cc | 9 +++++++++ gold/symtab.cc | 11 +++++++---- gold/yyscript.y | 6 +++++- 8 files changed, 65 insertions(+), 10 deletions(-) diff --git a/gold/gold.cc b/gold/gold.cc index f6437a811b..2ac1a6738c 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -254,9 +254,7 @@ queue_middle_tasks(const General_options& options, // Allocate common symbols. This requires write access to the // symbol table, but is independent of the relocation processing. - // FIXME: We should have an option to do this even for a relocatable - // link. - if (!parameters->options().relocatable()) + if (parameters->options().define_common()) { blocker->add_blocker(); workqueue->queue(new Allocate_commons_task(options, symtab, layout, diff --git a/gold/object.cc b/gold/object.cc index e444ec1ead..98bcb62e80 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -951,7 +951,7 @@ Sized_relobj::do_finalize_local_symbols(unsigned int index, if (shndx >= elfcpp::SHN_LORESERVE) { - if (shndx == elfcpp::SHN_ABS) + if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON) lv.set_output_value(lv.input_value()); else { diff --git a/gold/options.cc b/gold/options.cc index 716b133d6f..41fa6783a0 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -488,6 +488,14 @@ options::Command_line_options::options[] = N_("--compress-debug-sections=[none" ZLIB_STR "]"), TWO_DASHES, &General_options::set_compress_debug_sections), + GENERAL_NOARG('d', "define-common", N_("Define common symbols"), + NULL, TWO_DASHES, &General_options::set_define_common), + GENERAL_NOARG('\0', "dc", NULL, NULL, ONE_DASH, + &General_options::set_define_common), + GENERAL_NOARG('\0', "dp", NULL, NULL, ONE_DASH, + &General_options::set_define_common), + GENERAL_NOARG('\0', "no-define-common", N_("Do not define common symbols"), + NULL, TWO_DASHES, &General_options::set_no_define_common), SPECIAL('\0', "defsym", N_("Define a symbol"), N_("--defsym SYMBOL=EXPRESSION"), TWO_DASHES, &add_to_defsym), @@ -664,7 +672,9 @@ const int options::Command_line_options::debug_options_size = // The default values for the general options. General_options::General_options() - : entry_(NULL), + : define_common_(false), + user_set_define_common_(false), + entry_(NULL), export_dynamic_(false), soname_(NULL), dynamic_linker_(NULL), @@ -1138,6 +1148,10 @@ Command_line::normalize_options() this->options_.set_strip_debug(true); } + // Set default value for define_common. + if (!this->options_.user_set_define_common()) + this->options_.set_define_common(!this->options_.relocatable()); + // FIXME: we can/should be doing a lot more sanity checking here. } diff --git a/gold/options.h b/gold/options.h index c4e9859aae..db1392908d 100644 --- a/gold/options.h +++ b/gold/options.h @@ -121,6 +121,11 @@ class General_options General_options(); + // -d: define common symbols. + bool + define_common() const + { return this->define_common_; } + // -e: set entry address. const char* entry() const @@ -383,6 +388,21 @@ class General_options ZLIB_COMPRESSION, }; + void + set_define_common(bool value) + { + this->define_common_ = value; + this->user_set_define_common_ = true; + } + + void + set_no_define_common(bool value) + { this->set_define_common(!value); } + + bool + user_set_define_common() const + { return this->user_set_define_common_; } + void set_entry(const char* arg) { this->entry_ = arg; } @@ -625,6 +645,8 @@ class General_options void add_sysroot(); + bool define_common_; + bool user_set_define_common_; const char* entry_; bool export_dynamic_; const char* soname_; diff --git a/gold/script-c.h b/gold/script-c.h index 0eacd28fca..4f19b6353f 100644 --- a/gold/script-c.h +++ b/gold/script-c.h @@ -235,6 +235,11 @@ script_end_as_needed(void* closure); extern void script_set_entry(void* closure, const char*, size_t); +/* Called by the bison parser to set whether to define common symbols. */ + +extern void +script_set_common_allocation(void* closure, int); + /* Called by the bison parser to parse an OPTION. */ extern void diff --git a/gold/script.cc b/gold/script.cc index 307d1cfaa2..eef034ecd8 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -2080,6 +2080,15 @@ script_set_entry(void* closurev, const char* entry, size_t length) script_parse_option(closurev, arg.c_str(), arg.size()); } +// Called by the bison parser to set whether to define common symbols. + +extern "C" void +script_set_common_allocation(void* closurev, int set) +{ + const char* arg = set != 0 ? "--define-common" : "--no-define-common"; + script_parse_option(closurev, arg, strlen(arg)); +} + // Called by the bison parser to define a symbol. extern "C" void diff --git a/gold/symtab.cc b/gold/symtab.cc index 25f1cab348..cb2a798f78 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -1715,7 +1715,8 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) // FIXME: We need some target specific support here. if (shndx >= elfcpp::SHN_LORESERVE - && shndx != elfcpp::SHN_ABS) + && shndx != elfcpp::SHN_ABS + && shndx != elfcpp::SHN_COMMON) { gold_error(_("%s: unsupported symbol section 0x%x"), sym->demangled_name().c_str(), shndx); @@ -1730,7 +1731,7 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) } else if (shndx == elfcpp::SHN_UNDEF) value = 0; - else if (shndx == elfcpp::SHN_ABS) + else if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON) value = sym->value(); else { @@ -1904,7 +1905,8 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, // FIXME: We need some target specific support here. if (in_shndx >= elfcpp::SHN_LORESERVE - && in_shndx != elfcpp::SHN_ABS) + && in_shndx != elfcpp::SHN_ABS + && in_shndx != elfcpp::SHN_COMMON) { gold_error(_("%s: unsupported symbol section 0x%x"), sym->demangled_name().c_str(), in_shndx); @@ -1920,7 +1922,8 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, shndx = elfcpp::SHN_UNDEF; } else if (in_shndx == elfcpp::SHN_UNDEF - || in_shndx == elfcpp::SHN_ABS) + || in_shndx == elfcpp::SHN_ABS + || in_shndx == elfcpp::SHN_COMMON) shndx = in_shndx; else { diff --git a/gold/yyscript.y b/gold/yyscript.y index 3605158092..ca2835fb7e 100644 --- a/gold/yyscript.y +++ b/gold/yyscript.y @@ -232,10 +232,14 @@ linker_script: /* A command which may appear at top level of a linker script. */ file_cmd: - GROUP + FORCE_COMMON_ALLOCATION + { script_set_common_allocation(closure, 1); } + | GROUP { script_start_group(closure); } '(' input_list ')' { script_end_group(closure); } + | INHIBIT_COMMON_ALLOCATION + { script_set_common_allocation(closure, 0); } | OPTION '(' string ')' { script_parse_option(closure, $3.value, $3.length); } | PHDRS '{' phdrs_defs '}'