diff options
author | Cary Coutant <ccoutant@google.com> | 2010-07-09 01:34:31 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2010-07-09 01:34:31 +0000 |
commit | ce279a62c420e20c2d33e89641b6d9ed581a90c2 (patch) | |
tree | 10299dc3eb7f6c0fddb969fa11ae0dc079165aa0 /gold/resolve.cc | |
parent | 2ee2fea80422d6e481541aa20a5d4e26ca8f0192 (diff) | |
download | fsf-binutils-gdb-ce279a62c420e20c2d33e89641b6d9ed581a90c2.zip fsf-binutils-gdb-ce279a62c420e20c2d33e89641b6d9ed581a90c2.tar.gz fsf-binutils-gdb-ce279a62c420e20c2d33e89641b6d9ed581a90c2.tar.bz2 |
* resolve.cc (Symbol_table::resolve): Remember whether undef was
weak when resolving to a dynamic def.
(Symbol_table::should_override): Add adjust_dyndef flag; set it
for weak undef/dynamic def cases. Adjust callers.
* symtab.cc (Symbol::init_fields): Initialize undef_binding_set_ and
undef_binding_weak_.
(Symbol_table::sized_write_globals): Adjust symbol binding.
(Symbol_table::sized_write_symbol): Add binding parameter.
* symtab.h (Symbol::set_undef_binding): New method.
(Symbol::is_undef_binding_weak): New method.
(Symbol::undef_binding_set_, Symbol::undef_binding_weak_): New members.
(Symbol_table::should_override): Add new parameter.
(Symbol_table::sized_write_symbol): Add new parameter.
* testsuite/weak_undef_file1.cc: Add new test case.
* testsuite/weak_undef_file2.cc: Fix header comment.
* testsuite/weak_undef_test.cc: Add new test case.
Diffstat (limited to 'gold/resolve.cc')
-rw-r--r-- | gold/resolve.cc | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/gold/resolve.cc b/gold/resolve.cc index 8b1c321..af3d489 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -335,18 +335,33 @@ Symbol_table::resolve(Sized_symbol<size>* to, sym.get_st_type()); bool adjust_common_sizes; + bool adjust_dyndef; typename Sized_symbol<size>::Size_type tosize = to->symsize(); if (Symbol_table::should_override(to, frombits, OBJECT, object, - &adjust_common_sizes)) + &adjust_common_sizes, + &adjust_dyndef)) { + elfcpp::STB tobinding = to->binding(); this->override(to, sym, st_shndx, is_ordinary, object, version); if (adjust_common_sizes && tosize > to->symsize()) to->set_symsize(tosize); + if (adjust_dyndef) + { + // We are overriding an UNDEF or WEAK UNDEF with a DYN DEF. + // Remember which kind of UNDEF it was for future reference. + to->set_undef_binding(tobinding); + } } else { if (adjust_common_sizes && sym.get_st_size() > tosize) to->set_symsize(sym.get_st_size()); + if (adjust_dyndef) + { + // We are keeping a DYN DEF after seeing an UNDEF or WEAK UNDEF. + // Remember which kind of UNDEF it was. + to->set_undef_binding(sym.get_st_bind()); + } // The ELF ABI says that even for a reference to a symbol we // merge the visibility. to->override_visibility(sym.get_st_visibility()); @@ -381,9 +396,11 @@ Symbol_table::resolve(Sized_symbol<size>* to, bool Symbol_table::should_override(const Symbol* to, unsigned int frombits, Defined defined, Object* object, - bool* adjust_common_sizes) + bool* adjust_common_sizes, + bool* adjust_dyndef) { *adjust_common_sizes = false; + *adjust_dyndef = false; unsigned int tobits; if (to->source() == Symbol::IS_UNDEFINED) @@ -531,12 +548,17 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, return false; case UNDEF * 16 + DYN_DEF: - case WEAK_UNDEF * 16 + DYN_DEF: case DYN_UNDEF * 16 + DYN_DEF: case DYN_WEAK_UNDEF * 16 + DYN_DEF: // Use a dynamic definition if we have a reference. return true; + case WEAK_UNDEF * 16 + DYN_DEF: + // When overriding a weak undef by a dynamic definition, + // we need to remember that the original undef was weak. + *adjust_dyndef = true; + return true; + case COMMON * 16 + DYN_DEF: case WEAK_COMMON * 16 + DYN_DEF: case DYN_COMMON * 16 + DYN_DEF: @@ -554,12 +576,17 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, return false; case UNDEF * 16 + DYN_WEAK_DEF: - case WEAK_UNDEF * 16 + DYN_WEAK_DEF: case DYN_UNDEF * 16 + DYN_WEAK_DEF: case DYN_WEAK_UNDEF * 16 + DYN_WEAK_DEF: // Use a weak dynamic definition if we have a reference. return true; + case WEAK_UNDEF * 16 + DYN_WEAK_DEF: + // When overriding a weak undef by a dynamic definition, + // we need to remember that the original undef was weak. + *adjust_dyndef = true; + return true; + case COMMON * 16 + DYN_WEAK_DEF: case WEAK_COMMON * 16 + DYN_WEAK_DEF: case DYN_COMMON * 16 + DYN_WEAK_DEF: @@ -570,12 +597,16 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, case DEF * 16 + UNDEF: case WEAK_DEF * 16 + UNDEF: - case DYN_DEF * 16 + UNDEF: - case DYN_WEAK_DEF * 16 + UNDEF: case UNDEF * 16 + UNDEF: // A new undefined reference tells us nothing. return false; + case DYN_DEF * 16 + UNDEF: + case DYN_WEAK_DEF * 16 + UNDEF: + // For a dynamic def, we need to remember which kind of undef we see. + *adjust_dyndef = true; + return false; + case WEAK_UNDEF * 16 + UNDEF: case DYN_UNDEF * 16 + UNDEF: case DYN_WEAK_UNDEF * 16 + UNDEF: @@ -591,8 +622,6 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, case DEF * 16 + WEAK_UNDEF: case WEAK_DEF * 16 + WEAK_UNDEF: - case DYN_DEF * 16 + WEAK_UNDEF: - case DYN_WEAK_DEF * 16 + WEAK_UNDEF: case UNDEF * 16 + WEAK_UNDEF: case WEAK_UNDEF * 16 + WEAK_UNDEF: case DYN_UNDEF * 16 + WEAK_UNDEF: @@ -604,6 +633,12 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, // A new weak undefined reference tells us nothing. return false; + case DYN_DEF * 16 + WEAK_UNDEF: + case DYN_WEAK_DEF * 16 + WEAK_UNDEF: + // For a dynamic def, we need to remember which kind of undef we see. + *adjust_dyndef = true; + return false; + case DEF * 16 + DYN_UNDEF: case WEAK_DEF * 16 + DYN_UNDEF: case DYN_DEF * 16 + DYN_UNDEF: @@ -811,10 +846,12 @@ bool Symbol_table::should_override_with_special(const Symbol* to, Defined defined) { bool adjust_common_sizes; + bool adjust_dyn_def; unsigned int frombits = global_flag | regular_flag | def_flag; bool ret = Symbol_table::should_override(to, frombits, defined, NULL, - &adjust_common_sizes); - gold_assert(!adjust_common_sizes); + &adjust_common_sizes, + &adjust_dyn_def); + gold_assert(!adjust_common_sizes && !adjust_dyn_def); return ret; } |