diff options
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r-- | gold/symtab.cc | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc index 562e1fc..8a9e6f1 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -2355,30 +2355,17 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool, return off; } -// Finalize the symbol SYM. This returns true if the symbol should be -// added to the symbol table, false otherwise. +// Compute the final value of SYM and store status in location PSTATUS. +// During relaxation, this may be called multiple times for a symbol to +// compute its would-be final value in each relaxation pass. template<int size> -bool -Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) +typename Sized_symbol<size>::Value_type +Symbol_table::compute_final_value( + const Sized_symbol<size>* sym, + Compute_final_value_status* pstatus) const { typedef typename Sized_symbol<size>::Value_type Value_type; - - Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(unsized_sym); - - // The default version of a symbol may appear twice in the symbol - // table. We only need to finalize it once. - if (sym->has_symtab_index()) - return false; - - if (!sym->in_reg()) - { - gold_assert(!sym->has_symtab_index()); - sym->set_symtab_index(-1U); - gold_assert(sym->dynsym_index() == -1U); - return false; - } - Value_type value; switch (sym->source()) @@ -2392,9 +2379,8 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) && shndx != elfcpp::SHN_ABS && !Symbol::is_common_shndx(shndx)) { - gold_error(_("%s: unsupported symbol section 0x%x"), - sym->demangled_name().c_str(), shndx); - shndx = elfcpp::SHN_UNDEF; + *pstatus = CFVS_UNSUPPORTED_SYMBOL_SECTION; + return 0; } Object* symobj = sym->object(); @@ -2435,12 +2421,12 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) if (os == NULL) { - sym->set_symtab_index(-1U); bool static_or_reloc = (parameters->doing_static_link() || parameters->options().relocatable()); gold_assert(static_or_reloc || sym->dynsym_index() == -1U); - return false; + *pstatus = CFVS_NO_OUTPUT_SECTION; + return 0; } if (secoff64 == -1ULL) @@ -2513,6 +2499,57 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) gold_unreachable(); } + *pstatus = CFVS_OK; + return value; +} + +// Finalize the symbol SYM. This returns true if the symbol should be +// added to the symbol table, false otherwise. + +template<int size> +bool +Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) +{ + typedef typename Sized_symbol<size>::Value_type Value_type; + + Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(unsized_sym); + + // The default version of a symbol may appear twice in the symbol + // table. We only need to finalize it once. + if (sym->has_symtab_index()) + return false; + + if (!sym->in_reg()) + { + gold_assert(!sym->has_symtab_index()); + sym->set_symtab_index(-1U); + gold_assert(sym->dynsym_index() == -1U); + return false; + } + + // Compute final symbol value. + Compute_final_value_status status; + Value_type value = this->compute_final_value(sym, &status); + + switch (status) + { + case CFVS_OK: + break; + case CFVS_UNSUPPORTED_SYMBOL_SECTION: + { + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + gold_error(_("%s: unsupported symbol section 0x%x"), + sym->demangled_name().c_str(), shndx); + } + break; + case CFVS_NO_OUTPUT_SECTION: + sym->set_symtab_index(-1U); + return false; + default: + gold_unreachable(); + } + sym->set_value(value); if (parameters->options().strip_all() |