* 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>
|
||||
|
||||
* 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);
|
||||
}
|
||||
|
||||
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
|
||||
General_options::parse_start_group(const char*, const char*,
|
||||
Command_line* cmdline)
|
||||
|
|
|
@ -620,6 +620,18 @@ class General_options
|
|||
N_("Try to detect violations of the One Definition Rule"),
|
||||
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,
|
||||
N_("Set program start address"), N_("ADDRESS"));
|
||||
|
||||
|
@ -933,6 +945,11 @@ class General_options
|
|||
plugins() const
|
||||
{ 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:
|
||||
// Don't copy this structure.
|
||||
General_options(const General_options&);
|
||||
|
@ -982,6 +999,10 @@ class General_options
|
|||
bool do_demangle_;
|
||||
// List of plugin libraries.
|
||||
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
|
||||
|
|
|
@ -184,7 +184,9 @@ class Lex
|
|||
// Reading an expression in a linker script.
|
||||
EXPRESSION,
|
||||
// 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)
|
||||
|
@ -393,8 +395,9 @@ Lex::can_start_name(char c, char c2)
|
|||
case '~':
|
||||
return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2);
|
||||
|
||||
case '*': case '[':
|
||||
case '*': case '[':
|
||||
return (this->mode_ == VERSION_SCRIPT
|
||||
|| this->mode_ == DYNAMIC_LIST
|
||||
|| (this->mode_ == LINKER_SCRIPT
|
||||
&& 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':
|
||||
return c + 1;
|
||||
|
||||
// TODO(csilvers): why not allow ~ in names for version-scripts?
|
||||
case '/': case '\\': case '~':
|
||||
case '=': case '+':
|
||||
case ',':
|
||||
|
@ -437,19 +441,22 @@ Lex::can_continue_name(const char* c)
|
|||
return NULL;
|
||||
|
||||
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 NULL;
|
||||
|
||||
// TODO(csilvers): why allow this? ^ is meaningless in version scripts.
|
||||
case '^':
|
||||
if (this->mode_ == VERSION_SCRIPT)
|
||||
if (this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST)
|
||||
return c + 1;
|
||||
return NULL;
|
||||
|
||||
case ':':
|
||||
if (this->mode_ == LINKER_SCRIPT)
|
||||
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
|
||||
// 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),
|
||||
version_script_info_(script_options->version_script_info()),
|
||||
lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
|
||||
{
|
||||
{
|
||||
// We start out processing C symbols in the default lex mode.
|
||||
language_stack_.push_back("");
|
||||
lex_mode_stack_.push_back(lex->mode());
|
||||
|
@ -1373,6 +1380,7 @@ read_input_script(Workqueue* workqueue, const General_options& options,
|
|||
|
||||
static bool
|
||||
read_script_file(const char* filename, Command_line* cmdline,
|
||||
Script_options* script_options,
|
||||
int first_token, Lex::Mode lex_mode)
|
||||
{
|
||||
// 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,
|
||||
input_file.is_in_sysroot(),
|
||||
cmdline,
|
||||
&cmdline->script_options(),
|
||||
script_options,
|
||||
&lex);
|
||||
if (yyparse(&closure) != 0)
|
||||
{
|
||||
|
@ -1425,21 +1433,32 @@ read_script_file(const char* filename, Command_line* cmdline,
|
|||
bool
|
||||
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);
|
||||
}
|
||||
|
||||
// FILE was found as an argument to --version-script. Read it as a
|
||||
// version script, and store its contents in
|
||||
// FILENAME was found as an argument to --version-script. Read it as
|
||||
// a version script, and store its contents in
|
||||
// cmdline->script_options()->version_script_info().
|
||||
|
||||
bool
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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[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.
|
||||
|
||||
extern "C"
|
||||
|
@ -1963,6 +1995,9 @@ yylex(YYSTYPE* lvalp, void* closurev)
|
|||
case Lex::VERSION_SCRIPT:
|
||||
parsecode = version_script_keywords.keyword_to_parsecode(str, len);
|
||||
break;
|
||||
case Lex::DYNAMIC_LIST:
|
||||
parsecode = dynamic_list_keywords.keyword_to_parsecode(str, len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2339,7 +2374,7 @@ script_start_output_section(void* closurev, const char* name, size_t namelen,
|
|||
// Finish processing entries for an output section.
|
||||
|
||||
extern "C" void
|
||||
script_finish_output_section(void* closurev,
|
||||
script_finish_output_section(void* closurev,
|
||||
const struct Parser_output_section_trailer* trail)
|
||||
{
|
||||
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.
|
||||
|
||||
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
|
||||
// version script, and store its contents in
|
||||
|
@ -407,6 +407,14 @@ read_commandline_script(const char* filename, Command_line*);
|
|||
bool
|
||||
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.
|
||||
|
||||
#endif // !defined(GOLD_SCRIPT_H)
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "target.h"
|
||||
#include "workqueue.h"
|
||||
#include "symtab.h"
|
||||
#include "demangle.h" // needed for --dynamic-list-cpp-new
|
||||
#include "plugin.h"
|
||||
|
||||
namespace gold
|
||||
|
@ -288,6 +289,9 @@ Sized_symbol<size>::allocate_common(Output_data* od, Value_type 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
|
||||
// table.
|
||||
|
||||
|
@ -302,6 +306,48 @@ Symbol::should_add_dynsym_entry() const
|
|||
if (this->is_forced_local())
|
||||
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,
|
||||
// and the symbol is defined in a regular object and is
|
||||
// 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
|
||||
$(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
|
||||
thin_archive_test_1_SOURCES = thin_archive_main.cc
|
||||
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
|
||||
|
||||
# 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@ 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_7.sh ver_test_10.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_4.sh
|
||||
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh dynamic_list.sh
|
||||
|
||||
# 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_matching_test.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@ tls_pic_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@ ver_matching_test.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).
|
||||
@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;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testsuite/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign testsuite/Makefile
|
||||
$(AUTOMAKE) --gnu testsuite/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@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@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@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@ 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_VERSION_SCRIPT
|
||||
%token PARSING_DEFSYM
|
||||
%token PARSING_DYNAMIC_LIST
|
||||
|
||||
/* Non-terminal types, where needed. */
|
||||
|
||||
|
@ -222,6 +223,7 @@ top:
|
|||
PARSING_LINKER_SCRIPT linker_script
|
||||
| PARSING_VERSION_SCRIPT version_script
|
||||
| PARSING_DEFSYM defsym_expr
|
||||
| PARSING_DYNAMIC_LIST dynamic_list_expr
|
||||
;
|
||||
|
||||
/* A file contains a list of commands. */
|
||||
|
@ -836,6 +838,24 @@ defsym_expr:
|
|||
{ 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. */
|
||||
version_script:
|
||||
vers_nodes
|
||||
|
|
Loading…
Reference in a new issue