summaryrefslogtreecommitdiff
path: root/gold/resolve.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2015-06-07 14:03:09 -0700
committerCary Coutant <ccoutant@gmail.com>2015-06-07 14:03:52 -0700
commitb8cf50755b573140aae71f7247b604373fcdfbeb (patch)
tree9703225459949bc9fde830bbf7bba2cca5dcd38d /gold/resolve.cc
parent66f38e2951a1f7110ca3f1adf362322ec4208428 (diff)
downloadbinutils-gdb-b8cf50755b573140aae71f7247b604373fcdfbeb.tar.gz
Fix incorrect handling of STT_COMMON symbols in shared libraries.
The gABI allows STT_COMMON symbols to appear in executables and shared objects, so that the dynamic loader can resolve commons across modules. When reading a shared object, however, an STT_COMMON symbol should be treated as a regular definition at link time. In a relocatable object, the gABI requires that any STT_COMMON symbols must also be defined in the special SHN_COMMON section (which we extend to include target-specific small and large common sections). Thus, there is no need for gold to treat STT_COMMON symbols as common unless the st_shndx field is also set to a common section. gold/ PR gold/18288 * resolve.cc (symbol_to_bits): Remove type parameter; adjust all callers. Don't use STT_COMMON to check for common symbols. (Symbol_table::resolve): Warn if relocatable object has STT_COMMON symbol that's not in a common section. * symtab.h (Symbol::is_common): Don't use STT_COMMON to check for common symbols.
Diffstat (limited to 'gold/resolve.cc')
-rw-r--r--gold/resolve.cc30
1 files changed, 17 insertions, 13 deletions
diff --git a/gold/resolve.cc b/gold/resolve.cc
index 1c0344c689c..fdae0bae4a4 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -173,7 +173,7 @@ static const unsigned int common_flag = 2 << def_undef_or_common_shift;
static unsigned int
symbol_to_bits(elfcpp::STB binding, bool is_dynamic,
- unsigned int shndx, bool is_ordinary, elfcpp::STT type)
+ unsigned int shndx, bool is_ordinary)
{
unsigned int bits;
@@ -218,9 +218,7 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic,
break;
default:
- if (type == elfcpp::STT_COMMON)
- bits |= common_flag;
- else if (!is_ordinary && Symbol::is_common_shndx(shndx))
+ if (!is_ordinary && Symbol::is_common_shndx(shndx))
bits |= common_flag;
else
bits |= def_flag;
@@ -272,6 +270,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
if (!object->is_dynamic())
{
+ if (sym.get_st_type() == elfcpp::STT_COMMON
+ && (is_ordinary || !Symbol::is_common_shndx(st_shndx)))
+ {
+ gold_warning(_("STT_COMMON symbol '%s' in %s "
+ "is not in a common section"),
+ to->demangled_name().c_str(),
+ to->object()->name().c_str());
+ return;
+ }
// Record that we've seen this symbol in a regular object.
to->set_in_reg();
}
@@ -314,7 +321,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
bool adjust_common = false;
typename Sized_symbol<size>::Size_type tosize = 0;
typename Sized_symbol<size>::Value_type tovalue = 0;
- if (to->is_common() && !is_ordinary && st_shndx == elfcpp::SHN_COMMON)
+ if (to->is_common()
+ && !is_ordinary && Symbol::is_common_shndx(st_shndx))
{
adjust_common = true;
tosize = to->symsize();
@@ -370,8 +378,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
: sym.get_st_type());
unsigned int frombits = symbol_to_bits(sym.get_st_bind(),
object->is_dynamic(),
- st_shndx, is_ordinary,
- fromtype);
+ st_shndx, is_ordinary);
bool adjust_common_sizes;
bool adjust_dyndef;
@@ -454,11 +461,9 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
unsigned int tobits;
if (to->source() == Symbol::IS_UNDEFINED)
- tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true,
- to->type());
+ tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true);
else if (to->source() != Symbol::FROM_OBJECT)
- tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false,
- to->type());
+ tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false);
else
{
bool is_ordinary;
@@ -466,8 +471,7 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
tobits = symbol_to_bits(to->binding(),
to->object()->is_dynamic(),
shndx,
- is_ordinary,
- to->type());
+ is_ordinary);
}
if ((to->type() == elfcpp::STT_TLS) ^ (fromtype == elfcpp::STT_TLS)