* options.cc (General_options::parse_dynamic_list): New function.
* options.h (General_options): New flags dynamic_list, dynamic_list_data, dynamic_list_cpp_new, and dynamic_list_cpp_typeinfo. New variable dynamic_list_. (General_options::in_dynamic_list): New function. * script.cc (Lex::Mode): New enum DYNAMIC_LIST. (Lex::can_start_name): Add support for DYNAMIC_LIST mode. (Lex::can_continue_name): Likewise. (yylex): Likewise. (read_script_file): New parameter script_options. (read_dynamic_list): New function. (Script_options::define_dynamic_list): New function. (dynamic_list_keyword_parsecodes): New variable. (dynamic_list_keywords): New variable. * script.h (Script_options::define_dynamic_list): New function prototype. (read_dynamic_list): New function prototype. * symtab.cc (strprefix): New macro. (Symbol::should_add_dynsym_entry): Support dynamic_list, dynamic_list_data, dynamic_list_cpp_new, and dynamic_list_cpp_typeinfo. * yyscript.y (PARSING_DYNAMIC_LIST): New token. (dynamic_list_expr): New rule. (dynamic_list_nodes): Likewise. (dynamic_list_node): Likewise. * testsuite/Makefile.am (dynamic_list): New test. * testsuite/Makefile.in: Regenerated. * testsuite/dynamic_list.t: New file. * testsuite/dynamic_list.sh: New file.
This commit is contained in:
parent
e0bb29a584
commit
c82fbeee59
11 changed files with 277 additions and 18 deletions
|
@ -1,3 +1,35 @@
|
||||||
|
2008-11-05 Craig Silverstein <csilvers@google.com>
|
||||||
|
|
||||||
|
* options.cc (General_options::parse_dynamic_list): New function.
|
||||||
|
* options.h (General_options): New flags dynamic_list,
|
||||||
|
dynamic_list_data, dynamic_list_cpp_new, and
|
||||||
|
dynamic_list_cpp_typeinfo. New variable dynamic_list_.
|
||||||
|
(General_options::in_dynamic_list): New function.
|
||||||
|
* script.cc (Lex::Mode): New enum DYNAMIC_LIST.
|
||||||
|
(Lex::can_start_name): Add support for DYNAMIC_LIST mode.
|
||||||
|
(Lex::can_continue_name): Likewise.
|
||||||
|
(yylex): Likewise.
|
||||||
|
(read_script_file): New parameter script_options.
|
||||||
|
(read_dynamic_list): New function.
|
||||||
|
(Script_options::define_dynamic_list): New function.
|
||||||
|
(dynamic_list_keyword_parsecodes): New variable.
|
||||||
|
(dynamic_list_keywords): New variable.
|
||||||
|
* script.h (Script_options::define_dynamic_list): New function
|
||||||
|
prototype.
|
||||||
|
(read_dynamic_list): New function prototype.
|
||||||
|
* symtab.cc (strprefix): New macro.
|
||||||
|
(Symbol::should_add_dynsym_entry): Support dynamic_list,
|
||||||
|
dynamic_list_data, dynamic_list_cpp_new, and
|
||||||
|
dynamic_list_cpp_typeinfo.
|
||||||
|
* yyscript.y (PARSING_DYNAMIC_LIST): New token.
|
||||||
|
(dynamic_list_expr): New rule.
|
||||||
|
(dynamic_list_nodes): Likewise.
|
||||||
|
(dynamic_list_node): Likewise.
|
||||||
|
* testsuite/Makefile.am (dynamic_list): New test.
|
||||||
|
* testsuite/Makefile.in: Regenerated.
|
||||||
|
* testsuite/dynamic_list.t: New file.
|
||||||
|
* testsuite/dynamic_list.sh: New file.
|
||||||
|
|
||||||
2008-11-05 Craig Silverstein <csilvers@google.com>
|
2008-11-05 Craig Silverstein <csilvers@google.com>
|
||||||
|
|
||||||
* testsuite/tls_test_c.c: Add prototype for t11 and t11_last.
|
* testsuite/tls_test_c.c: Add prototype for t11 and t11_last.
|
||||||
|
|
|
@ -347,6 +347,14 @@ 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_dynamic_list(const char*, const char* arg,
|
||||||
|
Command_line* cmdline)
|
||||||
|
{
|
||||||
|
if (!read_dynamic_list(arg, cmdline, &this->dynamic_list_))
|
||||||
|
gold::gold_fatal(_("unable to parse dynamic-list script file %s"), 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)
|
||||||
|
|
|
@ -620,6 +620,18 @@ class General_options
|
||||||
N_("Try to detect violations of the One Definition Rule"),
|
N_("Try to detect violations of the One Definition Rule"),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
DEFINE_bool(dynamic_list_data, options::TWO_DASHES, '\0', false,
|
||||||
|
N_("Add data symbols to dynamic symbols"), NULL);
|
||||||
|
|
||||||
|
DEFINE_bool(dynamic_list_cpp_new, options::TWO_DASHES, '\0', false,
|
||||||
|
N_("Add C++ operator new/delete to dynamic symbols"), NULL);
|
||||||
|
|
||||||
|
DEFINE_bool(dynamic_list_cpp_typeinfo, options::TWO_DASHES, '\0', false,
|
||||||
|
N_("Add C++ typeinfo to dynamic symbols"), NULL);
|
||||||
|
|
||||||
|
DEFINE_special(dynamic_list, options::TWO_DASHES, '\0',
|
||||||
|
N_("Read a list of dynamic symbols"), N_("FILE"));
|
||||||
|
|
||||||
DEFINE_string(entry, options::TWO_DASHES, 'e', NULL,
|
DEFINE_string(entry, options::TWO_DASHES, 'e', NULL,
|
||||||
N_("Set program start address"), N_("ADDRESS"));
|
N_("Set program start address"), N_("ADDRESS"));
|
||||||
|
|
||||||
|
@ -933,6 +945,11 @@ class General_options
|
||||||
plugins() const
|
plugins() const
|
||||||
{ return this->plugins_; }
|
{ return this->plugins_; }
|
||||||
|
|
||||||
|
// True iff SYMBOL was found in the file specified by dynamic-list.
|
||||||
|
bool
|
||||||
|
in_dynamic_list(const char* symbol) const
|
||||||
|
{ return this->dynamic_list_.version_script_info()->symbol_is_local(symbol); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Don't copy this structure.
|
// Don't copy this structure.
|
||||||
General_options(const General_options&);
|
General_options(const General_options&);
|
||||||
|
@ -982,6 +999,10 @@ class General_options
|
||||||
bool do_demangle_;
|
bool do_demangle_;
|
||||||
// List of plugin libraries.
|
// List of plugin libraries.
|
||||||
Plugin_manager* plugins_;
|
Plugin_manager* plugins_;
|
||||||
|
// The parsed output of --dynamic-list files. For convenience in
|
||||||
|
// script.cc, we store this as a Script_options object, even though
|
||||||
|
// we only use a single Version_tree from it.
|
||||||
|
Script_options dynamic_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The position-dependent options. We use this to store the state of
|
// The position-dependent options. We use this to store the state of
|
||||||
|
|
|
@ -184,7 +184,9 @@ class Lex
|
||||||
// Reading an expression in a linker script.
|
// Reading an expression in a linker script.
|
||||||
EXPRESSION,
|
EXPRESSION,
|
||||||
// Reading a version script.
|
// Reading a version script.
|
||||||
VERSION_SCRIPT
|
VERSION_SCRIPT,
|
||||||
|
// Reading a --dynamic-list file.
|
||||||
|
DYNAMIC_LIST
|
||||||
};
|
};
|
||||||
|
|
||||||
Lex(const char* input_string, size_t input_length, int parsing_token)
|
Lex(const char* input_string, size_t input_length, int parsing_token)
|
||||||
|
@ -393,8 +395,9 @@ Lex::can_start_name(char c, char c2)
|
||||||
case '~':
|
case '~':
|
||||||
return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2);
|
return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2);
|
||||||
|
|
||||||
case '*': case '[':
|
case '*': case '[':
|
||||||
return (this->mode_ == VERSION_SCRIPT
|
return (this->mode_ == VERSION_SCRIPT
|
||||||
|
|| this->mode_ == DYNAMIC_LIST
|
||||||
|| (this->mode_ == LINKER_SCRIPT
|
|| (this->mode_ == LINKER_SCRIPT
|
||||||
&& can_continue_name(&c2)));
|
&& can_continue_name(&c2)));
|
||||||
|
|
||||||
|
@ -429,6 +432,7 @@ Lex::can_continue_name(const char* c)
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
return c + 1;
|
return c + 1;
|
||||||
|
|
||||||
|
// TODO(csilvers): why not allow ~ in names for version-scripts?
|
||||||
case '/': case '\\': case '~':
|
case '/': case '\\': case '~':
|
||||||
case '=': case '+':
|
case '=': case '+':
|
||||||
case ',':
|
case ',':
|
||||||
|
@ -437,19 +441,22 @@ Lex::can_continue_name(const char* c)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case '[': case ']': case '*': case '?': case '-':
|
case '[': case ']': case '*': case '?': case '-':
|
||||||
if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT)
|
if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT
|
||||||
|
|| this->mode_ == DYNAMIC_LIST)
|
||||||
return c + 1;
|
return c + 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// TODO(csilvers): why allow this? ^ is meaningless in version scripts.
|
||||||
case '^':
|
case '^':
|
||||||
if (this->mode_ == VERSION_SCRIPT)
|
if (this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST)
|
||||||
return c + 1;
|
return c + 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
if (this->mode_ == LINKER_SCRIPT)
|
if (this->mode_ == LINKER_SCRIPT)
|
||||||
return c + 1;
|
return c + 1;
|
||||||
else if (this->mode_ == VERSION_SCRIPT && (c[1] == ':'))
|
else if ((this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST)
|
||||||
|
&& (c[1] == ':'))
|
||||||
{
|
{
|
||||||
// A name can have '::' in it, as that's a c++ namespace
|
// A name can have '::' in it, as that's a c++ namespace
|
||||||
// separator. But a single colon is not part of a name.
|
// separator. But a single colon is not part of a name.
|
||||||
|
@ -1161,7 +1168,7 @@ class Parser_closure
|
||||||
command_line_(command_line), script_options_(script_options),
|
command_line_(command_line), script_options_(script_options),
|
||||||
version_script_info_(script_options->version_script_info()),
|
version_script_info_(script_options->version_script_info()),
|
||||||
lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
|
lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
|
||||||
{
|
{
|
||||||
// We start out processing C symbols in the default lex mode.
|
// We start out processing C symbols in the default lex mode.
|
||||||
language_stack_.push_back("");
|
language_stack_.push_back("");
|
||||||
lex_mode_stack_.push_back(lex->mode());
|
lex_mode_stack_.push_back(lex->mode());
|
||||||
|
@ -1373,6 +1380,7 @@ read_input_script(Workqueue* workqueue, const General_options& options,
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_script_file(const char* filename, Command_line* cmdline,
|
read_script_file(const char* filename, Command_line* cmdline,
|
||||||
|
Script_options* script_options,
|
||||||
int first_token, Lex::Mode lex_mode)
|
int first_token, Lex::Mode lex_mode)
|
||||||
{
|
{
|
||||||
// TODO: if filename is a relative filename, search for it manually
|
// TODO: if filename is a relative filename, search for it manually
|
||||||
|
@ -1404,7 +1412,7 @@ read_script_file(const char* filename, Command_line* cmdline,
|
||||||
false,
|
false,
|
||||||
input_file.is_in_sysroot(),
|
input_file.is_in_sysroot(),
|
||||||
cmdline,
|
cmdline,
|
||||||
&cmdline->script_options(),
|
script_options,
|
||||||
&lex);
|
&lex);
|
||||||
if (yyparse(&closure) != 0)
|
if (yyparse(&closure) != 0)
|
||||||
{
|
{
|
||||||
|
@ -1425,21 +1433,32 @@ read_script_file(const char* filename, Command_line* cmdline,
|
||||||
bool
|
bool
|
||||||
read_commandline_script(const char* filename, Command_line* cmdline)
|
read_commandline_script(const char* filename, Command_line* cmdline)
|
||||||
{
|
{
|
||||||
return read_script_file(filename, cmdline,
|
return read_script_file(filename, cmdline, &cmdline->script_options(),
|
||||||
PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT);
|
PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE was found as an argument to --version-script. Read it as a
|
// FILENAME was found as an argument to --version-script. Read it as
|
||||||
// version script, and store its contents in
|
// a version script, and store its contents in
|
||||||
// cmdline->script_options()->version_script_info().
|
// cmdline->script_options()->version_script_info().
|
||||||
|
|
||||||
bool
|
bool
|
||||||
read_version_script(const char* filename, Command_line* cmdline)
|
read_version_script(const char* filename, Command_line* cmdline)
|
||||||
{
|
{
|
||||||
return read_script_file(filename, cmdline,
|
return read_script_file(filename, cmdline, &cmdline->script_options(),
|
||||||
PARSING_VERSION_SCRIPT, Lex::VERSION_SCRIPT);
|
PARSING_VERSION_SCRIPT, Lex::VERSION_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FILENAME was found as an argument to --dynamic-list. Read it as a
|
||||||
|
// list of symbols, and store its contents in DYNAMIC_LIST.
|
||||||
|
|
||||||
|
bool
|
||||||
|
read_dynamic_list(const char* filename, Command_line* cmdline,
|
||||||
|
Script_options* dynamic_list)
|
||||||
|
{
|
||||||
|
return read_script_file(filename, cmdline, dynamic_list,
|
||||||
|
PARSING_DYNAMIC_LIST, Lex::DYNAMIC_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
// Implement the --defsym option on the command line. Return true if
|
// Implement the --defsym option on the command line. Return true if
|
||||||
// all is well.
|
// all is well.
|
||||||
|
|
||||||
|
@ -1622,6 +1641,19 @@ version_script_keywords(&version_script_keyword_parsecodes[0],
|
||||||
(sizeof(version_script_keyword_parsecodes)
|
(sizeof(version_script_keyword_parsecodes)
|
||||||
/ sizeof(version_script_keyword_parsecodes[0])));
|
/ sizeof(version_script_keyword_parsecodes[0])));
|
||||||
|
|
||||||
|
static const Keyword_to_parsecode::Keyword_parsecode
|
||||||
|
dynamic_list_keyword_parsecodes[] =
|
||||||
|
{
|
||||||
|
{ "extern", EXTERN },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Keyword_to_parsecode
|
||||||
|
dynamic_list_keywords(&dynamic_list_keyword_parsecodes[0],
|
||||||
|
(sizeof(dynamic_list_keyword_parsecodes)
|
||||||
|
/ sizeof(dynamic_list_keyword_parsecodes[0])));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Comparison function passed to bsearch.
|
// Comparison function passed to bsearch.
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -1963,6 +1995,9 @@ yylex(YYSTYPE* lvalp, void* closurev)
|
||||||
case Lex::VERSION_SCRIPT:
|
case Lex::VERSION_SCRIPT:
|
||||||
parsecode = version_script_keywords.keyword_to_parsecode(str, len);
|
parsecode = version_script_keywords.keyword_to_parsecode(str, len);
|
||||||
break;
|
break;
|
||||||
|
case Lex::DYNAMIC_LIST:
|
||||||
|
parsecode = dynamic_list_keywords.keyword_to_parsecode(str, len);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2339,7 +2374,7 @@ script_start_output_section(void* closurev, const char* name, size_t namelen,
|
||||||
// Finish processing entries for an output section.
|
// Finish processing entries for an output section.
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
script_finish_output_section(void* closurev,
|
script_finish_output_section(void* closurev,
|
||||||
const struct Parser_output_section_trailer* trail)
|
const struct Parser_output_section_trailer* trail)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
|
|
|
@ -398,7 +398,7 @@ read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*,
|
||||||
// Read it as a script, and execute its contents immediately.
|
// Read it as a script, and execute its contents immediately.
|
||||||
|
|
||||||
bool
|
bool
|
||||||
read_commandline_script(const char* filename, Command_line*);
|
read_commandline_script(const char* filename, Command_line* cmdline);
|
||||||
|
|
||||||
// FILE was found as an argument to --version-script. Read it as a
|
// FILE was found as an argument to --version-script. Read it as a
|
||||||
// version script, and store its contents in
|
// version script, and store its contents in
|
||||||
|
@ -407,6 +407,14 @@ read_commandline_script(const char* filename, Command_line*);
|
||||||
bool
|
bool
|
||||||
read_version_script(const char* filename, Command_line* cmdline);
|
read_version_script(const char* filename, Command_line* cmdline);
|
||||||
|
|
||||||
|
// FILENAME was found as an argument to --dynamic-list. Read it as a
|
||||||
|
// version script (actually, a versym_node from a version script), and
|
||||||
|
// store its contents in DYNAMIC_LIST.
|
||||||
|
|
||||||
|
bool
|
||||||
|
read_dynamic_list(const char* filename, Command_line* cmdline,
|
||||||
|
Script_options* dynamic_list);
|
||||||
|
|
||||||
} // End namespace gold.
|
} // End namespace gold.
|
||||||
|
|
||||||
#endif // !defined(GOLD_SCRIPT_H)
|
#endif // !defined(GOLD_SCRIPT_H)
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "workqueue.h"
|
#include "workqueue.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
#include "demangle.h" // needed for --dynamic-list-cpp-new
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
namespace gold
|
namespace gold
|
||||||
|
@ -288,6 +289,9 @@ Sized_symbol<size>::allocate_common(Output_data* od, Value_type value)
|
||||||
this->value_ = value;
|
this->value_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The ""'s around str ensure str is a string literal, so sizeof works.
|
||||||
|
#define strprefix(var, str) (strncmp(var, str, sizeof("" str "") - 1) == 0)
|
||||||
|
|
||||||
// Return true if this symbol should be added to the dynamic symbol
|
// Return true if this symbol should be added to the dynamic symbol
|
||||||
// table.
|
// table.
|
||||||
|
|
||||||
|
@ -302,6 +306,48 @@ Symbol::should_add_dynsym_entry() const
|
||||||
if (this->is_forced_local())
|
if (this->is_forced_local())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// If the symbol was forced dynamic in a --dynamic-list file, add it.
|
||||||
|
if (parameters->options().in_dynamic_list(this->name()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If dynamic-list-data was specified, add any STT_OBJECT.
|
||||||
|
if (parameters->options().dynamic_list_data()
|
||||||
|
&& !this->is_from_dynobj()
|
||||||
|
&& this->type() == elfcpp::STT_OBJECT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If --dynamic-list-cpp-new was specified, add any new/delete symbol.
|
||||||
|
// If --dynamic-list-cpp-typeinfo was specified, add any typeinfo symbols.
|
||||||
|
if ((parameters->options().dynamic_list_cpp_new()
|
||||||
|
|| parameters->options().dynamic_list_cpp_typeinfo())
|
||||||
|
&& !this->is_from_dynobj())
|
||||||
|
{
|
||||||
|
// TODO(csilvers): We could probably figure out if we're an operator
|
||||||
|
// new/delete or typeinfo without the need to demangle.
|
||||||
|
char* demangled_name = cplus_demangle(this->name(),
|
||||||
|
DMGL_ANSI | DMGL_PARAMS);
|
||||||
|
if (demangled_name == NULL)
|
||||||
|
{
|
||||||
|
// Not a C++ symbol, so it can't satisfy these flags
|
||||||
|
}
|
||||||
|
else if (parameters->options().dynamic_list_cpp_new()
|
||||||
|
&& (strprefix(demangled_name, "operator new")
|
||||||
|
|| strprefix(demangled_name, "operator delete")))
|
||||||
|
{
|
||||||
|
free(demangled_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (parameters->options().dynamic_list_cpp_typeinfo()
|
||||||
|
&& (strprefix(demangled_name, "typeinfo name for")
|
||||||
|
|| strprefix(demangled_name, "typeinfo for")))
|
||||||
|
{
|
||||||
|
free(demangled_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
free(demangled_name);
|
||||||
|
}
|
||||||
|
|
||||||
// If exporting all symbols or building a shared library,
|
// If exporting all symbols or building a shared library,
|
||||||
// and the symbol is defined in a regular object and is
|
// and the symbol is defined in a regular object and is
|
||||||
// externally visible, we need to add it.
|
// externally visible, we need to add it.
|
||||||
|
|
|
@ -903,6 +903,21 @@ script_test_4: basic_test.o gcctestdir/ld $(srcdir)/script_test_4.t
|
||||||
script_test_4.stdout: script_test_4
|
script_test_4.stdout: script_test_4
|
||||||
$(TEST_READELF) -SlW script_test_4 > script_test_4.stdout
|
$(TEST_READELF) -SlW script_test_4 > script_test_4.stdout
|
||||||
|
|
||||||
|
# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new,
|
||||||
|
# and --dynamic-list-cpp-typeinfo
|
||||||
|
|
||||||
|
check_SCRIPTS += dynamic_list.sh
|
||||||
|
check_DATA += dynamic_list.stdout
|
||||||
|
MOSTLYCLEANFILES += dynamic_list.stdout
|
||||||
|
dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t
|
||||||
|
$(CXXLINK) -Bgcctestdir/ basic_test.o \
|
||||||
|
-Wl,--dynamic-list $(srcdir)/dynamic_list.t \
|
||||||
|
-Wl,--dynamic-list-data \
|
||||||
|
-Wl,--dynamic-list-cpp-new \
|
||||||
|
-Wl,--dynamic-list-cpp-typeinfo
|
||||||
|
dynamic_list.stdout: dynamic_list
|
||||||
|
$(TEST_READELF) -DWs dynamic_list > dynamic_list.stdout
|
||||||
|
|
||||||
check_PROGRAMS += thin_archive_test_1
|
check_PROGRAMS += thin_archive_test_1
|
||||||
thin_archive_test_1_SOURCES = thin_archive_main.cc
|
thin_archive_test_1_SOURCES = thin_archive_main.cc
|
||||||
thin_archive_test_1_DEPENDENCIES = gcctestdir/ld libthin1.a alt/libthin2.a
|
thin_archive_test_1_DEPENDENCIES = gcctestdir/ld libthin1.a alt/libthin2.a
|
||||||
|
|
|
@ -162,13 +162,16 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||||
# Test --detect-odr-violations
|
# Test --detect-odr-violations
|
||||||
|
|
||||||
# Similar to --detect-odr-violations: check for undefined symbols in .so's
|
# Similar to --detect-odr-violations: check for undefined symbols in .so's
|
||||||
|
|
||||||
|
# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new,
|
||||||
|
# and --dynamic-list-cpp-typeinfo
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = weak_plt.sh debug_msg.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = weak_plt.sh debug_msg.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh dynamic_list.sh
|
||||||
|
|
||||||
# Create the data files that debug_msg.sh analyzes.
|
# Create the data files that debug_msg.sh analyzes.
|
||||||
|
|
||||||
|
@ -184,7 +187,8 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms ver_test_10.syms \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms ver_test_10.syms \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_8 = tls_test \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_8 = tls_test \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test \
|
||||||
|
@ -229,7 +233,8 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout
|
||||||
|
|
||||||
# Test -o when emitting to a special file (such as something in /dev).
|
# Test -o when emitting to a special file (such as something in /dev).
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = flagstest_o_specialfile
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = flagstest_o_specialfile
|
||||||
|
@ -1458,9 +1463,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
|
||||||
exit 1;; \
|
exit 1;; \
|
||||||
esac; \
|
esac; \
|
||||||
done; \
|
done; \
|
||||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testsuite/Makefile'; \
|
||||||
cd $(top_srcdir) && \
|
cd $(top_srcdir) && \
|
||||||
$(AUTOMAKE) --foreign testsuite/Makefile
|
$(AUTOMAKE) --gnu testsuite/Makefile
|
||||||
.PRECIOUS: Makefile
|
.PRECIOUS: Makefile
|
||||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
@case '$?' in \
|
@case '$?' in \
|
||||||
|
@ -2418,6 +2423,14 @@ uninstall-am: uninstall-info-am
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_4.stdout: script_test_4
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_4.stdout: script_test_4
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list $(srcdir)/dynamic_list.t \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-data \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-cpp-new \
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-cpp-typeinfo
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list.stdout: dynamic_list
|
||||||
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -DWs dynamic_list > dynamic_list.stdout
|
||||||
|
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@libthin1.a: thin_archive_test_1.o alt/thin_archive_test_2.o
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@libthin1.a: thin_archive_test_1.o alt/thin_archive_test_2.o
|
||||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@
|
@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@
|
||||||
|
|
50
gold/testsuite/dynamic_list.sh
Executable file
50
gold/testsuite/dynamic_list.sh
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# dynamic_list.sh -- test --dynamic-list and --dynamic-list-*
|
||||||
|
|
||||||
|
# Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
# Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
|
# This file is part of gold.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301, USA.
|
||||||
|
|
||||||
|
# This file goes with dynamic_list.t, which is a dynamic-list script.
|
||||||
|
|
||||||
|
check()
|
||||||
|
{
|
||||||
|
if ! grep -qw "$2" "$1"
|
||||||
|
then
|
||||||
|
echo "Did not find expected text in $1:"
|
||||||
|
echo " $2"
|
||||||
|
echo ""
|
||||||
|
echo "Actual output below:"
|
||||||
|
cat "$1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check dynamic_list.stdout "main" # comes via --dynamic-list
|
||||||
|
check dynamic_list.stdout "_ZdlPv" # "operator delete(void*)"
|
||||||
|
check dynamic_list.stdout "_Z4t1_6v" # t1_6()
|
||||||
|
check dynamic_list.stdout "_ZN4t16aC2Ev" # t16a:t16a()
|
||||||
|
check dynamic_list.stdout "_ZN4t16aD1Ev" # t16a:~t16a()
|
||||||
|
check dynamic_list.stdout "_ZN4t16a1tEv" # t16a:t()
|
||||||
|
check dynamic_list.stdout "_ZTI4t16a" # typeinfo for t16a
|
||||||
|
check dynamic_list.stdout "_ZTI4t16b" # typeinfo for t16b
|
||||||
|
check dynamic_list.stdout "_ZTS4t16a" # typeinfo name for t16a
|
||||||
|
check dynamic_list.stdout "_ZTS4t16b" # typeinfo name for t16b
|
||||||
|
check dynamic_list.stdout "t20v" # comes via --dynamic-list-data
|
11
gold/testsuite/dynamic_list.t
Normal file
11
gold/testsuite/dynamic_list.t
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
main;
|
||||||
|
not_a_symbol;
|
||||||
|
global;
|
||||||
|
extern "C++" { t1_6* };
|
||||||
|
};
|
||||||
|
{
|
||||||
|
extern "C++" { t16a* };
|
||||||
|
local;
|
||||||
|
extern;
|
||||||
|
};
|
|
@ -193,6 +193,7 @@
|
||||||
%token PARSING_LINKER_SCRIPT
|
%token PARSING_LINKER_SCRIPT
|
||||||
%token PARSING_VERSION_SCRIPT
|
%token PARSING_VERSION_SCRIPT
|
||||||
%token PARSING_DEFSYM
|
%token PARSING_DEFSYM
|
||||||
|
%token PARSING_DYNAMIC_LIST
|
||||||
|
|
||||||
/* Non-terminal types, where needed. */
|
/* Non-terminal types, where needed. */
|
||||||
|
|
||||||
|
@ -222,6 +223,7 @@ top:
|
||||||
PARSING_LINKER_SCRIPT linker_script
|
PARSING_LINKER_SCRIPT linker_script
|
||||||
| PARSING_VERSION_SCRIPT version_script
|
| PARSING_VERSION_SCRIPT version_script
|
||||||
| PARSING_DEFSYM defsym_expr
|
| PARSING_DEFSYM defsym_expr
|
||||||
|
| PARSING_DYNAMIC_LIST dynamic_list_expr
|
||||||
;
|
;
|
||||||
|
|
||||||
/* A file contains a list of commands. */
|
/* A file contains a list of commands. */
|
||||||
|
@ -836,6 +838,24 @@ defsym_expr:
|
||||||
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Handle the --dynamic-list option. A dynamic list has the format
|
||||||
|
{ sym1; sym2; extern "C++" { namespace::sym3 }; };
|
||||||
|
We store the symbol we see in the "local" list; that is where
|
||||||
|
Command_line::in_dynamic_list() will look to do its check.
|
||||||
|
TODO(csilvers): More than one of these brace-lists can appear, and
|
||||||
|
should just be merged and treated as a single list. */
|
||||||
|
dynamic_list_expr: dynamic_list_nodes ;
|
||||||
|
|
||||||
|
dynamic_list_nodes:
|
||||||
|
dynamic_list_node
|
||||||
|
| dynamic_list_nodes dynamic_list_node
|
||||||
|
;
|
||||||
|
|
||||||
|
dynamic_list_node:
|
||||||
|
'{' vers_defns ';' '}' ';'
|
||||||
|
{ script_new_vers_node (closure, NULL, $2); }
|
||||||
|
;
|
||||||
|
|
||||||
/* A version script. */
|
/* A version script. */
|
||||||
version_script:
|
version_script:
|
||||||
vers_nodes
|
vers_nodes
|
||||||
|
|
Loading…
Reference in a new issue