aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/gold.cc4
-rw-r--r--gold/object.cc2
-rw-r--r--gold/options.cc16
-rw-r--r--gold/options.h22
-rw-r--r--gold/script-c.h5
-rw-r--r--gold/script.cc9
-rw-r--r--gold/symtab.cc11
-rw-r--r--gold/yyscript.y6
8 files changed, 65 insertions, 10 deletions
diff --git a/gold/gold.cc b/gold/gold.cc
index f6437a8..2ac1a67 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 e444ec1..98bcb62 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -951,7 +951,7 @@ Sized_relobj<size, big_endian>::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 716b133..41fa678 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 c4e9859..db13929 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
@@ -384,6 +389,21 @@ class General_options
};
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 0eacd28..4f19b63 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 307d1cf..eef034e 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 25f1cab..cb2a798 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 3605158..ca2835f 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 '}'