summaryrefslogtreecommitdiff
path: root/gold/symtab.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2008-04-09 00:48:13 +0000
committerIan Lance Taylor <ian@airs.com>2008-04-09 00:48:13 +0000
commitf6a3fd0f05455d0be710cb238d89f8e0005e80ff (patch)
treedb7b9e1a6978d9288b9debc0db66fc0507dd839b /gold/symtab.cc
parente4c3ed604e50ea55e994790d1cff18f7ab025621 (diff)
downloadbinutils-redhat-f6a3fd0f05455d0be710cb238d89f8e0005e80ff.tar.gz
* options.h (class General_options): Define --wrap as a special
option. Add wrap_symbols_ field. (General_options::any_wrap_symbols): New function. (General_options::is_wrap_symbol): New function. * options.cc (General_options::parse_wrap): New function. (General_options::General_options): Initialize wrap_symbols_. * symtab.cc (Symbol_table::wrap_symbol): New function. (Symbol_table::add_from_object): Handle --wrap. * symtab.h (class Symbol_table): Declare wrap_symbol. * target.h (Target::wrap_char): New function. (Target::Target_info): Add wrap_char field. * i386.cc (Target_i386::i386_info): Initialize wrap_char. * x86_64.cc (Target_x86_64::x86_64_info): Likewise. * testsuite/testfile.cc (Target_test::test_target_info): Likewise.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r--gold/symtab.cc67
1 files changed, 67 insertions, 0 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc
index a216b3bcbd..91a2b1ea69 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -478,6 +478,54 @@ Symbol_table::force_local(Symbol* sym)
this->forced_locals_.push_back(sym);
}
+// Adjust NAME for wrapping, and update *NAME_KEY if necessary. This
+// is only called for undefined symbols, when at least one --wrap
+// option was used.
+
+const char*
+Symbol_table::wrap_symbol(Object* object, const char* name,
+ Stringpool::Key* name_key)
+{
+ // For some targets, we need to ignore a specific character when
+ // wrapping, and add it back later.
+ char prefix = '\0';
+ if (name[0] == object->target()->wrap_char())
+ {
+ prefix = name[0];
+ ++name;
+ }
+
+ if (parameters->options().is_wrap_symbol(name))
+ {
+ // Turn NAME into __wrap_NAME.
+ std::string s;
+ if (prefix != '\0')
+ s += prefix;
+ s += "__wrap_";
+ s += name;
+
+ // This will give us both the old and new name in NAMEPOOL_, but
+ // that is OK. Only the versions we need will wind up in the
+ // real string table in the output file.
+ return this->namepool_.add(s.c_str(), true, name_key);
+ }
+
+ const char* const real_prefix = "__real_";
+ const size_t real_prefix_length = strlen(real_prefix);
+ if (strncmp(name, real_prefix, real_prefix_length) == 0
+ && parameters->options().is_wrap_symbol(name + real_prefix_length))
+ {
+ // Turn __real_NAME into NAME.
+ std::string s;
+ if (prefix != '\0')
+ s += prefix;
+ s += name + real_prefix_length;
+ return this->namepool_.add(s.c_str(), true, name_key);
+ }
+
+ return name;
+}
+
// Add one symbol from OBJECT to the symbol table. NAME is symbol
// name and VERSION is the version; both are canonicalized. DEF is
// whether this is the default version.
@@ -517,6 +565,25 @@ Symbol_table::add_from_object(Object* object,
const elfcpp::Sym<size, big_endian>& sym,
const elfcpp::Sym<size, big_endian>& orig_sym)
{
+ // For an undefined symbol, we may need to adjust the name using
+ // --wrap.
+ if (orig_sym.get_st_shndx() == elfcpp::SHN_UNDEF
+ && parameters->options().any_wrap_symbols())
+ {
+ const char* wrap_name = this->wrap_symbol(object, name, &name_key);
+ if (wrap_name != name)
+ {
+ // If we see a reference to malloc with version GLIBC_2.0,
+ // and we turn it into a reference to __wrap_malloc, then we
+ // discard the version number. Otherwise the user would be
+ // required to specify the correct version for
+ // __wrap_malloc.
+ version = NULL;
+ version_key = 0;
+ name = wrap_name;
+ }
+ }
+
Symbol* const snull = NULL;
std::pair<typename Symbol_table_type::iterator, bool> ins =
this->table_.insert(std::make_pair(std::make_pair(name_key, version_key),