diff options
-rw-r--r-- | gold/ChangeLog | 42 | ||||
-rw-r--r-- | gold/archive.cc | 6 | ||||
-rw-r--r-- | gold/gold.cc | 3 | ||||
-rw-r--r-- | gold/options.h | 21 | ||||
-rw-r--r-- | gold/resolve.cc | 8 | ||||
-rw-r--r-- | gold/symtab.cc | 235 | ||||
-rw-r--r-- | gold/symtab.h | 93 |
7 files changed, 307 insertions, 101 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index ba92005..49acc33 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,47 @@ 2008-05-06 Ian Lance Taylor <iant@google.com> + PR 6049 + * options.h (DEFINE_set): Add VARNAME_begin and VARNAME_end + functions. + (class General_options): Remove existing --undefined, and add + --no-undefined instead. Add new --undefined as synonym for -u. + * archive.cc (Archive::add_symbols): Check whether symbol was + named with -u. + * gold.cc (queue_middle_tasks): Add -u symbols to symbol table. + * symtab.h (class Symbol): Rename CONSTANT to IS_CONSTANT; change + all uses. Add IS_UNDEFINED. Update declarations to split + different versions of init_base. Declare init_base_undefined. + (Symbol::is_defined): Handle IS_UNDEFINED. + (Symbol::is_undefined): Likewise. + (Symbol::is_weak_undefined): Call is_undefined. + (Symbol::is_absolute): Handle IS_CONSTANT. + (class Sized_symbol): Update declarations to split different + versions of init. Declare init_undefined. + (class Symbol_table): Declare new functions. + * symtab.cc (Symbol::init_base_object): Rename from init_base. + Change all callers. + (Symbol::init_base_output_data): Likewise. + (Symbol::init_base_output_segment): Likewise. + (Symbol::init_base_constant): Likewise. + (Symbol::init_base_undefined): New function. + (Sized_symbol::init_object): Rename from init. Change all + callers. + (Sized_symbol::init_output_data): Likewise. + (Sized_symbol::init_output_segment): Likewise. + (Sized_symbol::init_constant): Likewise. + (Sized_symbol::init_undefined): New function. + (Symbol_table::add_undefined_symbols_from_command_line): New + function. + (Symbol_table::do_add_undefined_symbols_from_command_line): New + function. + (Symbol::final_value_is_known): Handle IS_UNDEFINED. + (Symbol::output_section): Likewise. + (Symbol::set_output_section): Likewise. + (Symbol_table::sized_finalize_symbol): Likewise. + (Symbol_table::sized_write_globals): Likewise. + * resolve.cc (Symbol_table::should_override): Likewise. + (Symbol::override_base_with_special): Likewise. + * symtab.cc (Symbol_table::add_from_dynobj): If we see a protected symbol, change it to have default visibility. * testsuite/protected_1.cc: New file. diff --git a/gold/archive.cc b/gold/archive.cc index be623b5..1e16de9 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -326,7 +326,11 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, + this->armap_[i].name_offset); Symbol* sym = symtab->lookup(sym_name); if (sym == NULL) - continue; + { + // Check whether the symbol was named in a -u option. + if (!parameters->options().is_undefined(sym_name)) + continue; + } else if (!sym->is_undefined()) { this->armap_checked_[i] = true; diff --git a/gold/gold.cc b/gold/gold.cc index 54b0828..396a5a9 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -212,6 +212,9 @@ queue_middle_tasks(const General_options& options, // Define symbols from any linker scripts. layout->define_script_symbols(symtab); + // Add any symbols named with -u options to the symbol table. + symtab->add_undefined_symbols_from_command_line(); + // Attach sections to segments. layout->attach_sections_to_segments(); diff --git a/gold/options.h b/gold/options.h index cf9b887..bfb40c7 100644 --- a/gold/options.h +++ b/gold/options.h @@ -369,13 +369,22 @@ struct Struct_special : public Struct_var bool \ any_##varname__() const \ { return !this->varname__##_.value.empty(); } \ + \ bool \ is_##varname__(const char* symbol) const \ { \ return (!this->varname__##_.value.empty() \ && (this->varname__##_.value.find(std::string(symbol)) \ != this->varname__##_.value.end())); \ - } + } \ + \ + options::String_set::const_iterator \ + varname__##_begin() const \ + { return this->varname__##_.value.begin(); } \ + \ + options::String_set::const_iterator \ + varname__##_end() const \ + { return this->varname__##_.value.end(); } // When you have a list of possible values (expressed as string) // After helparg__ should come an initializer list, like @@ -652,6 +661,10 @@ class General_options DEFINE_bool(noinhibit_exec, options::TWO_DASHES, '\0', false, N_("Create an output file even if errors occur"), NULL); + DEFINE_bool_alias(no_undefined, defs, options::TWO_DASHES, '\0', + N_("Report undefined symbols (even with --shared)"), + NULL, false); + DEFINE_string(output, options::TWO_DASHES, 'o', "a.out", N_("Set output file name"), N_("FILE")); @@ -733,10 +746,8 @@ class General_options DEFINE_uint64(Ttext, options::ONE_DASH, '\0', -1U, N_("Set the address of the text segment"), N_("ADDRESS")); - DEFINE_bool_alias(undefined, defs, options::TWO_DASHES, '\0', - "Allow undefined symbols with --shared", - "Report undefined symbols (even with --shared)", - true); + DEFINE_set(undefined, options::TWO_DASHES, 'u', + N_("Create undefined reference to SYMBOL"), N_("SYMBOL")); DEFINE_bool(verbose, options::TWO_DASHES, '\0', false, N_("Synonym for --debug=files"), NULL); diff --git a/gold/resolve.cc b/gold/resolve.cc index 21a7fc6..291bca6 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -281,7 +281,10 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, *adjust_common_sizes = false; unsigned int tobits; - if (to->source() != Symbol::FROM_OBJECT) + if (to->source() == Symbol::IS_UNDEFINED) + tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true, + to->type()); + else if (to->source() != Symbol::FROM_OBJECT) tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false, to->type()); else @@ -662,7 +665,8 @@ Symbol::override_base_with_special(const Symbol* from) case IN_OUTPUT_SEGMENT: this->u_.in_output_segment = from->u_.in_output_segment; break; - case CONSTANT: + case IS_CONSTANT: + case IS_UNDEFINED: break; default: gold_unreachable(); diff --git a/gold/symtab.cc b/gold/symtab.cc index 522ca62..4d463e2 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -105,9 +105,9 @@ Symbol::demangled_name() const template<int size, bool big_endian> void -Symbol::init_base(const char* name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>& sym, - unsigned int st_shndx, bool is_ordinary) +Symbol::init_base_object(const char* name, const char* version, Object* object, + const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary) { this->init_fields(name, version, sym.get_st_type(), sym.get_st_bind(), sym.get_st_visibility(), sym.get_st_nonvis()); @@ -123,9 +123,10 @@ Symbol::init_base(const char* name, const char* version, Object* object, // in an Output_data. void -Symbol::init_base(const char* name, Output_data* od, elfcpp::STT type, - elfcpp::STB binding, elfcpp::STV visibility, - unsigned char nonvis, bool offset_is_from_end) +Symbol::init_base_output_data(const char* name, Output_data* od, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + bool offset_is_from_end) { this->init_fields(name, NULL, type, binding, visibility, nonvis); this->u_.in_output_data.output_data = od; @@ -138,9 +139,10 @@ Symbol::init_base(const char* name, Output_data* od, elfcpp::STT type, // in an Output_segment. void -Symbol::init_base(const char* name, Output_segment* os, elfcpp::STT type, - elfcpp::STB binding, elfcpp::STV visibility, - unsigned char nonvis, Segment_offset_base offset_base) +Symbol::init_base_output_segment(const char* name, Output_segment* os, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + Segment_offset_base offset_base) { this->init_fields(name, NULL, type, binding, visibility, nonvis); this->u_.in_output_segment.output_segment = os; @@ -153,12 +155,25 @@ Symbol::init_base(const char* name, Output_segment* os, elfcpp::STT type, // as a constant. void -Symbol::init_base(const char* name, elfcpp::STT type, - elfcpp::STB binding, elfcpp::STV visibility, - unsigned char nonvis) +Symbol::init_base_constant(const char* name, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis) +{ + this->init_fields(name, NULL, type, binding, visibility, nonvis); + this->source_ = IS_CONSTANT; + this->in_reg_ = true; +} + +// Initialize the fields in the base class Symbol for an undefined +// symbol. + +void +Symbol::init_base_undefined(const char* name, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis) { this->init_fields(name, NULL, type, binding, visibility, nonvis); - this->source_ = CONSTANT; + this->source_ = IS_UNDEFINED; this->in_reg_ = true; } @@ -178,11 +193,12 @@ Symbol::allocate_base_common(Output_data* od) template<int size> template<bool big_endian> void -Sized_symbol<size>::init(const char* name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>& sym, - unsigned int st_shndx, bool is_ordinary) +Sized_symbol<size>::init_object(const char* name, const char* version, + Object* object, + const elfcpp::Sym<size, big_endian>& sym, + unsigned int st_shndx, bool is_ordinary) { - this->init_base(name, version, object, sym, st_shndx, is_ordinary); + this->init_base_object(name, version, object, sym, st_shndx, is_ordinary); this->value_ = sym.get_st_value(); this->symsize_ = sym.get_st_size(); } @@ -192,14 +208,15 @@ Sized_symbol<size>::init(const char* name, const char* version, Object* object, template<int size> void -Sized_symbol<size>::init(const char* name, Output_data* od, - Value_type value, Size_type symsize, - elfcpp::STT type, elfcpp::STB binding, - elfcpp::STV visibility, unsigned char nonvis, - bool offset_is_from_end) -{ - this->init_base(name, od, type, binding, visibility, nonvis, - offset_is_from_end); +Sized_symbol<size>::init_output_data(const char* name, Output_data* od, + Value_type value, Size_type symsize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, + unsigned char nonvis, + bool offset_is_from_end) +{ + this->init_base_output_data(name, od, type, binding, visibility, nonvis, + offset_is_from_end); this->value_ = value; this->symsize_ = symsize; } @@ -209,13 +226,15 @@ Sized_symbol<size>::init(const char* name, Output_data* od, template<int size> void -Sized_symbol<size>::init(const char* name, Output_segment* os, - Value_type value, Size_type symsize, - elfcpp::STT type, elfcpp::STB binding, - elfcpp::STV visibility, unsigned char nonvis, - Segment_offset_base offset_base) +Sized_symbol<size>::init_output_segment(const char* name, Output_segment* os, + Value_type value, Size_type symsize, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, + unsigned char nonvis, + Segment_offset_base offset_base) { - this->init_base(name, os, type, binding, visibility, nonvis, offset_base); + this->init_base_output_segment(name, os, type, binding, visibility, nonvis, + offset_base); this->value_ = value; this->symsize_ = symsize; } @@ -225,15 +244,29 @@ Sized_symbol<size>::init(const char* name, Output_segment* os, template<int size> void -Sized_symbol<size>::init(const char* name, Value_type value, Size_type symsize, - elfcpp::STT type, elfcpp::STB binding, - elfcpp::STV visibility, unsigned char nonvis) +Sized_symbol<size>::init_constant(const char* name, Value_type value, + Size_type symsize, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis) { - this->init_base(name, type, binding, visibility, nonvis); + this->init_base_constant(name, type, binding, visibility, nonvis); this->value_ = value; this->symsize_ = symsize; } +// Initialize the fields in Sized_symbol for an undefined symbol. + +template<int size> +void +Sized_symbol<size>::init_undefined(const char* name, elfcpp::STT type, + elfcpp::STB binding, elfcpp::STV visibility, + unsigned char nonvis) +{ + this->init_base_undefined(name, type, binding, visibility, nonvis); + this->value_ = 0; + this->symsize_ = 0; +} + // Allocate a common symbol. template<int size> @@ -280,20 +313,25 @@ Symbol::final_value_is_known() const if (parameters->options().shared() || parameters->options().relocatable()) return false; - // If the symbol is not from an object file, then it is defined, and - // known. + // If the symbol is not from an object file, and is not undefined, + // then it is defined, and known. if (this->source_ != FROM_OBJECT) - return true; - - // If the symbol is from a dynamic object, then the final value is - // not known. - if (this->object()->is_dynamic()) - return false; + { + if (this->source_ != IS_UNDEFINED) + return true; + } + else + { + // If the symbol is from a dynamic object, then the final value + // is not known. + if (this->object()->is_dynamic()) + return false; - // If the symbol is not undefined (it is defined or common), then - // the final value is known. - if (!this->is_undefined()) - return true; + // If the symbol is not undefined (it is defined or common), + // then the final value is known. + if (!this->is_undefined()) + return true; + } // If the symbol is undefined, then whether the final value is known // depends on whether we are doing a static link. If we are doing a @@ -326,7 +364,8 @@ Symbol::output_section() const return this->u_.in_output_data.output_data->output_section(); case IN_OUTPUT_SEGMENT: - case CONSTANT: + case IS_CONSTANT: + case IS_UNDEFINED: return NULL; default: @@ -347,12 +386,13 @@ Symbol::set_output_section(Output_section* os) case IN_OUTPUT_DATA: gold_assert(this->output_section() == os); break; - case CONSTANT: + case IS_CONSTANT: this->source_ = IN_OUTPUT_DATA; this->u_.in_output_data.output_data = os; this->u_.in_output_data.offset_is_from_end = false; break; case IN_OUTPUT_SEGMENT: + case IS_UNDEFINED: default: gold_unreachable(); } @@ -714,7 +754,7 @@ Symbol_table::add_from_object(Object* object, } } - ret->init(name, version, object, sym, st_shndx, is_ordinary); + ret->init_object(name, version, object, sym, st_shndx, is_ordinary); ins.first->second = ret; if (def) @@ -1332,8 +1372,8 @@ Symbol_table::do_define_in_output_data( return NULL; gold_assert(version == NULL || oldsym != NULL); - sym->init(name, od, value, symsize, type, binding, visibility, nonvis, - offset_is_from_end); + sym->init_output_data(name, od, value, symsize, type, binding, visibility, + nonvis, offset_is_from_end); if (oldsym == NULL) { @@ -1432,8 +1472,8 @@ Symbol_table::do_define_in_output_segment( return NULL; gold_assert(version == NULL || oldsym != NULL); - sym->init(name, os, value, symsize, type, binding, visibility, nonvis, - offset_base); + sym->init_output_segment(name, os, value, symsize, type, binding, + visibility, nonvis, offset_base); if (oldsym == NULL) { @@ -1532,7 +1572,7 @@ Symbol_table::do_define_as_constant( return NULL; gold_assert(version == NULL || version == name || oldsym != NULL); - sym->init(name, value, symsize, type, binding, visibility, nonvis); + sym->init_constant(name, value, symsize, type, binding, visibility, nonvis); if (oldsym == NULL) { @@ -1668,6 +1708,79 @@ Symbol_table::get_copy_source(const Symbol* sym) const return p->second; } +// Add any undefined symbols named on the command line. + +void +Symbol_table::add_undefined_symbols_from_command_line() +{ + if (parameters->options().any_undefined()) + { + if (parameters->target().get_size() == 32) + { +#if defined(HAVE_TARGET_32_LITTL) || defined(HAVE_TARGET_32_BIG) + this->do_add_undefined_symbols_from_command_line<32>(); +#else + gold_unreachable(); +#endif + } + else if (parameters->target().get_size() == 64) + { +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) + this->do_add_undefined_symbols_from_command_line<64>(); +#else + gold_unreachable(); +#endif + } + else + gold_unreachable(); + } +} + +template<int size> +void +Symbol_table::do_add_undefined_symbols_from_command_line() +{ + for (options::String_set::const_iterator p = + parameters->options().undefined_begin(); + p != parameters->options().undefined_end(); + ++p) + { + const char* name = p->c_str(); + + if (this->lookup(name) != NULL) + continue; + + const char* version = NULL; + + Sized_symbol<size>* sym; + Sized_symbol<size>* oldsym; + if (parameters->target().is_big_endian()) + { +#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) + sym = this->define_special_symbol<size, true>(&name, &version, + false, &oldsym); +#else + gold_unreachable(); +#endif + } + else + { +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) + sym = this->define_special_symbol<size, false>(&name, &version, + false, &oldsym); +#else + gold_unreachable(); +#endif + } + + gold_assert(oldsym == NULL); + + sym->init_undefined(name, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL, + elfcpp::STV_DEFAULT, 0); + ++this->saw_undefined_; + } +} + // Set the dynamic symbol indexes. INDEX is the index of the first // global dynamic symbol. Pointers to the symbols are stored into the // vector SYMS. The names are added to DYNPOOL. This returns an @@ -1927,10 +2040,14 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) } break; - case Symbol::CONSTANT: + case Symbol::IS_CONSTANT: value = sym->value(); break; + case Symbol::IS_UNDEFINED: + value = 0; + break; + default: gold_unreachable(); } @@ -2123,10 +2240,14 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, shndx = elfcpp::SHN_ABS; break; - case Symbol::CONSTANT: + case Symbol::IS_CONSTANT: shndx = elfcpp::SHN_ABS; break; + case Symbol::IS_UNDEFINED: + shndx = elfcpp::SHN_UNDEF; + break; + default: gold_unreachable(); } diff --git a/gold/symtab.h b/gold/symtab.h index 020f242..b58909b 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -78,7 +78,9 @@ class Symbol // section. IN_OUTPUT_SEGMENT, // Symbol value is constant. - CONSTANT + IS_CONSTANT, + // Symbol is undefined. + IS_UNDEFINED }; // When the source is IN_OUTPUT_SEGMENT, we need to describe what @@ -390,7 +392,7 @@ class Symbol { bool is_ordinary; if (this->source_ != FROM_OBJECT) - return true; + return this->source_ != IS_UNDEFINED; unsigned int shndx = this->shndx(&is_ordinary); return (is_ordinary ? shndx != elfcpp::SHN_UNDEF @@ -409,30 +411,26 @@ class Symbol is_undefined() const { bool is_ordinary; - return (this->source_ == FROM_OBJECT - && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF - && is_ordinary); + return ((this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF + && is_ordinary) + || this->source_ == IS_UNDEFINED); } // Return whether this is a weak undefined symbol. bool is_weak_undefined() const - { - bool is_ordinary; - return (this->source_ == FROM_OBJECT - && this->binding() == elfcpp::STB_WEAK - && this->shndx(&is_ordinary) == elfcpp::SHN_UNDEF - && is_ordinary); - } + { return this->is_undefined() && this->binding() == elfcpp::STB_WEAK; } // Return whether this is an absolute symbol. bool is_absolute() const { bool is_ordinary; - return (this->source_ == FROM_OBJECT - && this->shndx(&is_ordinary) == elfcpp::SHN_ABS - && !is_ordinary); + return ((this->source_ == FROM_OBJECT + && this->shndx(&is_ordinary) == elfcpp::SHN_ABS + && !is_ordinary) + || this->source_ == IS_CONSTANT); } // Return whether this is a common symbol. @@ -664,25 +662,32 @@ class Symbol // index rather than a special code. template<int size, bool big_endian> void - init_base(const char *name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, - bool is_ordinary); + init_base_object(const char *name, const char* version, Object* object, + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); // Initialize fields for an Output_data. void - init_base(const char* name, Output_data*, elfcpp::STT, elfcpp::STB, - elfcpp::STV, unsigned char nonvis, bool offset_is_from_end); + init_base_output_data(const char* name, Output_data*, elfcpp::STT, + elfcpp::STB, elfcpp::STV, unsigned char nonvis, + bool offset_is_from_end); // Initialize fields for an Output_segment. void - init_base(const char* name, Output_segment* os, elfcpp::STT type, - elfcpp::STB binding, elfcpp::STV visibility, - unsigned char nonvis, Segment_offset_base offset_base); + init_base_output_segment(const char* name, Output_segment* os, + elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis, + Segment_offset_base offset_base); // Initialize fields for a constant. void - init_base(const char* name, elfcpp::STT type, elfcpp::STB binding, - elfcpp::STV visibility, unsigned char nonvis); + init_base_constant(const char* name, elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis); + + // Initialize fields for an undefined symbol. + void + init_base_undefined(const char* name, elfcpp::STT type, elfcpp::STB binding, + elfcpp::STV visibility, unsigned char nonvis); // Override existing symbol. template<int size, bool big_endian> @@ -838,26 +843,31 @@ class Sized_symbol : public Symbol // index rather than a special code. template<bool big_endian> void - init(const char *name, const char* version, Object* object, - const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, - bool is_ordinary); + init_object(const char *name, const char* version, Object* object, + const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx, + bool is_ordinary); // Initialize fields for an Output_data. void - init(const char* name, Output_data*, Value_type value, Size_type symsize, - elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis, - bool offset_is_from_end); + init_output_data(const char* name, Output_data*, Value_type value, + Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV, + unsigned char nonvis, bool offset_is_from_end); // Initialize fields for an Output_segment. void - init(const char* name, Output_segment*, Value_type value, Size_type symsize, - elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis, - Segment_offset_base offset_base); + init_output_segment(const char* name, Output_segment*, Value_type value, + Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV, + unsigned char nonvis, Segment_offset_base offset_base); // Initialize fields for a constant. void - init(const char* name, Value_type value, Size_type symsize, - elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis); + init_constant(const char* name, Value_type value, Size_type symsize, + elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis); + + // Initialize fields for an undefined symbol. + void + init_undefined(const char* name, elfcpp::STT, elfcpp::STB, elfcpp::STV, + unsigned char nonvis); // Override existing symbol. template<bool big_endian> @@ -1184,6 +1194,11 @@ class Symbol_table void detect_odr_violations(const Task*, const char* output_file_name) const; + // Add any undefined symbols named on the command line to the symbol + // table. + void + add_undefined_symbols_from_command_line(); + // SYM is defined using a COPY reloc. Return the dynamic object // where the original definition was found. Dynobj* @@ -1340,6 +1355,12 @@ class Symbol_table elfcpp::STV visibility, unsigned char nonvis, bool only_if_ref, bool force_override); + // Add any undefined symbols named on the command line to the symbol + // table, sized version. + template<int size> + void + do_add_undefined_symbols_from_command_line(); + // Allocate the common symbols, sized version. template<int size> void |