mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-05 12:53:16 +08:00
* 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.
This commit is contained in:
parent
789aa6de31
commit
0864d55193
@ -1,5 +1,21 @@
|
|||||||
2008-04-08 Ian Lance Taylor <iant@google.com>
|
2008-04-08 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
* errors.cc (Errors::undefined_symbol): Mention symbol version if
|
* errors.cc (Errors::undefined_symbol): Mention symbol version if
|
||||||
there is one.
|
there is one.
|
||||||
|
|
||||||
|
@ -373,6 +373,7 @@ const Target::Target_info Target_i386::i386_info =
|
|||||||
false, // has_resolve
|
false, // has_resolve
|
||||||
true, // has_code_fill
|
true, // has_code_fill
|
||||||
true, // is_default_stack_executable
|
true, // is_default_stack_executable
|
||||||
|
'\0', // wrap_char
|
||||||
"/usr/lib/libc.so.1", // dynamic_linker
|
"/usr/lib/libc.so.1", // dynamic_linker
|
||||||
0x08048000, // default_text_segment_address
|
0x08048000, // default_text_segment_address
|
||||||
0x1000, // abi_pagesize (overridable by -z max-page-size)
|
0x1000, // abi_pagesize (overridable by -z max-page-size)
|
||||||
|
@ -324,6 +324,13 @@ General_options::parse_version_script(const char*, const char* arg,
|
|||||||
gold::gold_fatal(_("unable to parse version script file %s"), arg);
|
gold::gold_fatal(_("unable to parse version script file %s"), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
General_options::parse_wrap(const char*, const char* arg,
|
||||||
|
Command_line*)
|
||||||
|
{
|
||||||
|
this->wrap_symbols_.insert(std::string(arg));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
General_options::parse_start_group(const char*, const char*,
|
General_options::parse_start_group(const char*, const char*,
|
||||||
Command_line* cmdline)
|
Command_line* cmdline)
|
||||||
@ -581,7 +588,7 @@ namespace gold
|
|||||||
|
|
||||||
General_options::General_options()
|
General_options::General_options()
|
||||||
: execstack_status_(General_options::EXECSTACK_FROM_INPUT), static_(false),
|
: execstack_status_(General_options::EXECSTACK_FROM_INPUT), static_(false),
|
||||||
do_demangle_(false)
|
do_demangle_(false), wrap_symbols_()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,6 +620,9 @@ class General_options
|
|||||||
N_("Include all archive contents"),
|
N_("Include all archive contents"),
|
||||||
N_("Include only needed archive contents"));
|
N_("Include only needed archive contents"));
|
||||||
|
|
||||||
|
DEFINE_special(wrap, options::TWO_DASHES, '\0',
|
||||||
|
N_("Use wrapper functions for SYMBOL"), N_("SYMBOL"));
|
||||||
|
|
||||||
DEFINE_special(start_group, options::TWO_DASHES, '(',
|
DEFINE_special(start_group, options::TWO_DASHES, '(',
|
||||||
N_("Start a library search group"), NULL);
|
N_("Start a library search group"), NULL);
|
||||||
DEFINE_special(end_group, options::TWO_DASHES, ')',
|
DEFINE_special(end_group, options::TWO_DASHES, ')',
|
||||||
@ -702,6 +705,19 @@ class General_options
|
|||||||
do_demangle() const
|
do_demangle() const
|
||||||
{ return this->do_demangle_; }
|
{ return this->do_demangle_; }
|
||||||
|
|
||||||
|
// Whether there are any symbols to wrap.
|
||||||
|
bool
|
||||||
|
any_wrap_symbols() const
|
||||||
|
{ return !this->wrap_symbols_.empty(); }
|
||||||
|
|
||||||
|
// Whether to wrap SYMBOL.
|
||||||
|
bool
|
||||||
|
is_wrap_symbol(const char* symbol) const
|
||||||
|
{
|
||||||
|
return (this->wrap_symbols_.find(std::string(symbol))
|
||||||
|
!= this->wrap_symbols_.end());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Don't copy this structure.
|
// Don't copy this structure.
|
||||||
General_options(const General_options&);
|
General_options(const General_options&);
|
||||||
@ -745,6 +761,8 @@ class General_options
|
|||||||
bool static_;
|
bool static_;
|
||||||
// Whether to do demangling.
|
// Whether to do demangling.
|
||||||
bool do_demangle_;
|
bool do_demangle_;
|
||||||
|
// List of symbols used with --wrap.
|
||||||
|
Unordered_set<std::string> wrap_symbols_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The position-dependent options. We use this to store the state of
|
// The position-dependent options. We use this to store the state of
|
||||||
|
@ -478,6 +478,54 @@ Symbol_table::force_local(Symbol* sym)
|
|||||||
this->forced_locals_.push_back(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
|
// Add one symbol from OBJECT to the symbol table. NAME is symbol
|
||||||
// name and VERSION is the version; both are canonicalized. DEF is
|
// name and VERSION is the version; both are canonicalized. DEF is
|
||||||
// whether this is the default version.
|
// 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>& sym,
|
||||||
const elfcpp::Sym<size, big_endian>& orig_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;
|
Symbol* const snull = NULL;
|
||||||
std::pair<typename Symbol_table_type::iterator, bool> ins =
|
std::pair<typename Symbol_table_type::iterator, bool> ins =
|
||||||
this->table_.insert(std::make_pair(std::make_pair(name_key, version_key),
|
this->table_.insert(std::make_pair(std::make_pair(name_key, version_key),
|
||||||
|
@ -1213,6 +1213,10 @@ class Symbol_table
|
|||||||
void
|
void
|
||||||
force_local(Symbol*);
|
force_local(Symbol*);
|
||||||
|
|
||||||
|
// Adjust NAME and *NAME_KEY for wrapping.
|
||||||
|
const char*
|
||||||
|
wrap_symbol(Object* object, const char*, Stringpool::Key* name_key);
|
||||||
|
|
||||||
// Whether we should override a symbol, based on flags in
|
// Whether we should override a symbol, based on flags in
|
||||||
// resolve.cc.
|
// resolve.cc.
|
||||||
static bool
|
static bool
|
||||||
|
@ -132,6 +132,15 @@ class Target
|
|||||||
is_default_stack_executable() const
|
is_default_stack_executable() const
|
||||||
{ return this->pti_->is_default_stack_executable; }
|
{ return this->pti_->is_default_stack_executable; }
|
||||||
|
|
||||||
|
// Return a character which may appear as a prefix for a wrap
|
||||||
|
// symbol. If this character appears, we strip it when checking for
|
||||||
|
// wrapping and add it back when forming the final symbol name.
|
||||||
|
// This should be '\0' if not special prefix is required, which is
|
||||||
|
// the normal case.
|
||||||
|
char
|
||||||
|
wrap_char() const
|
||||||
|
{ return this->pti_->wrap_char; }
|
||||||
|
|
||||||
// This is called to tell the target to complete any sections it is
|
// This is called to tell the target to complete any sections it is
|
||||||
// handling. After this all sections must have their final size.
|
// handling. After this all sections must have their final size.
|
||||||
void
|
void
|
||||||
@ -179,6 +188,8 @@ class Target
|
|||||||
// Whether an object file with no .note.GNU-stack sections implies
|
// Whether an object file with no .note.GNU-stack sections implies
|
||||||
// that the stack should be executable.
|
// that the stack should be executable.
|
||||||
bool is_default_stack_executable;
|
bool is_default_stack_executable;
|
||||||
|
// Prefix character to strip when checking for wrapping.
|
||||||
|
char wrap_char;
|
||||||
// The default dynamic linker name.
|
// The default dynamic linker name.
|
||||||
const char* dynamic_linker;
|
const char* dynamic_linker;
|
||||||
// The default text segment address.
|
// The default text segment address.
|
||||||
|
@ -88,6 +88,7 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info =
|
|||||||
false, // has_resolve
|
false, // has_resolve
|
||||||
false, // has_code_fill
|
false, // has_code_fill
|
||||||
false, // is_default_stack_executable
|
false, // is_default_stack_executable
|
||||||
|
'\0', // wrap_char
|
||||||
"/dummy", // dynamic_linker
|
"/dummy", // dynamic_linker
|
||||||
0x08000000, // default_text_segment_address
|
0x08000000, // default_text_segment_address
|
||||||
0x1000, // abi_pagesize
|
0x1000, // abi_pagesize
|
||||||
|
@ -369,6 +369,7 @@ const Target::Target_info Target_x86_64::x86_64_info =
|
|||||||
false, // has_resolve
|
false, // has_resolve
|
||||||
true, // has_code_fill
|
true, // has_code_fill
|
||||||
true, // is_default_stack_executable
|
true, // is_default_stack_executable
|
||||||
|
'\0', // wrap_char
|
||||||
"/lib/ld64.so.1", // program interpreter
|
"/lib/ld64.so.1", // program interpreter
|
||||||
0x400000, // default_text_segment_address
|
0x400000, // default_text_segment_address
|
||||||
0x1000, // abi_pagesize (overridable by -z max-page-size)
|
0x1000, // abi_pagesize (overridable by -z max-page-size)
|
||||||
|
Loading…
Reference in New Issue
Block a user