diff options
author | Ian Lance Taylor <ian@airs.com> | 2008-04-09 00:48:13 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2008-04-09 00:48:13 +0000 |
commit | 0864d55193d9ad757c26cba29da1de1c00be4ba8 (patch) | |
tree | bd0b661d221890ae9c1e7211dd2a861f5140f2a7 /gold/symtab.cc | |
parent | 789aa6de31480d7b322e515b43451b1b1108fedc (diff) | |
download | gdb-0864d55193d9ad757c26cba29da1de1c00be4ba8.zip gdb-0864d55193d9ad757c26cba29da1de1c00be4ba8.tar.gz gdb-0864d55193d9ad757c26cba29da1de1c00be4ba8.tar.bz2 |
* 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.cc | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc index a216b3b..91a2b1e 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), |