mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-10 01:42:21 +08:00
From Craig Silverstein: Handle quoted strings differently in version
scripts, and handle extern "C++" in the middle of a block.
This commit is contained in:
@ -125,6 +125,7 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
|
|||||||
{
|
{
|
||||||
unsigned int debug_shndx;
|
unsigned int debug_shndx;
|
||||||
for (debug_shndx = 0; debug_shndx < object->shnum(); ++debug_shndx)
|
for (debug_shndx = 0; debug_shndx < object->shnum(); ++debug_shndx)
|
||||||
|
// FIXME: do this more efficiently: section_name() isn't super-fast
|
||||||
if (object->section_name(debug_shndx) == ".debug_line")
|
if (object->section_name(debug_shndx) == ".debug_line")
|
||||||
{
|
{
|
||||||
section_size_type buffer_size;
|
section_size_type buffer_size;
|
||||||
|
@ -233,7 +233,11 @@ script_add_vers_depend(void* closure,
|
|||||||
extern struct Version_expression_list *
|
extern struct Version_expression_list *
|
||||||
script_new_vers_pattern(void* closure,
|
script_new_vers_pattern(void* closure,
|
||||||
struct Version_expression_list *,
|
struct Version_expression_list *,
|
||||||
const char *, int);
|
const char *, int, int);
|
||||||
|
|
||||||
|
extern struct Version_expression_list *
|
||||||
|
script_merge_expressions(struct Version_expression_list *a,
|
||||||
|
struct Version_expression_list *b);
|
||||||
|
|
||||||
extern struct Version_tree *
|
extern struct Version_tree *
|
||||||
script_new_vers_node(void* closure,
|
script_new_vers_node(void* closure,
|
||||||
|
@ -1517,7 +1517,7 @@ yylex(YYSTYPE* lvalp, void* closurev)
|
|||||||
|
|
||||||
case Token::TOKEN_QUOTED_STRING:
|
case Token::TOKEN_QUOTED_STRING:
|
||||||
lvalp->string.value = token->string_value(&lvalp->string.length);
|
lvalp->string.value = token->string_value(&lvalp->string.length);
|
||||||
return STRING;
|
return QUOTED_STRING;
|
||||||
|
|
||||||
case Token::TOKEN_OPERATOR:
|
case Token::TOKEN_OPERATOR:
|
||||||
return token->operator_value();
|
return token->operator_value();
|
||||||
@ -1713,11 +1713,14 @@ script_pop_lex_mode(void* closurev)
|
|||||||
// pattern and language should be from the stringpool
|
// pattern and language should be from the stringpool
|
||||||
struct Version_expression {
|
struct Version_expression {
|
||||||
Version_expression(const std::string& pattern,
|
Version_expression(const std::string& pattern,
|
||||||
const std::string& language)
|
const std::string& language,
|
||||||
: pattern(pattern), language(language) {}
|
bool exact_match)
|
||||||
|
: pattern(pattern), language(language), exact_match(exact_match) {}
|
||||||
|
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
std::string language;
|
std::string language;
|
||||||
|
// If false, we use glob() to match pattern. If true, we use strcmp().
|
||||||
|
bool exact_match;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1789,14 +1792,15 @@ Version_script_info::get_symbol_version_helper(const char* symbol_name,
|
|||||||
for (size_t j = 0; j < version_trees_.size(); ++j)
|
for (size_t j = 0; j < version_trees_.size(); ++j)
|
||||||
{
|
{
|
||||||
// Is it a global symbol for this version?
|
// Is it a global symbol for this version?
|
||||||
const Version_expression_list* exp =
|
const Version_expression_list* explist =
|
||||||
check_global ? version_trees_[j]->global : version_trees_[j]->local;
|
check_global ? version_trees_[j]->global : version_trees_[j]->local;
|
||||||
if (exp != NULL)
|
if (explist != NULL)
|
||||||
for (size_t k = 0; k < exp->expressions.size(); ++k)
|
for (size_t k = 0; k < explist->expressions.size(); ++k)
|
||||||
{
|
{
|
||||||
const char* name_to_match = symbol_name;
|
const char* name_to_match = symbol_name;
|
||||||
|
const struct Version_expression& exp = explist->expressions[k];
|
||||||
char* demangled_name = NULL;
|
char* demangled_name = NULL;
|
||||||
if (exp->expressions[k].language == "C++")
|
if (exp.language == "C++")
|
||||||
{
|
{
|
||||||
demangled_name = cplus_demangle(symbol_name,
|
demangled_name = cplus_demangle(symbol_name,
|
||||||
DMGL_ANSI | DMGL_PARAMS);
|
DMGL_ANSI | DMGL_PARAMS);
|
||||||
@ -1805,7 +1809,7 @@ Version_script_info::get_symbol_version_helper(const char* symbol_name,
|
|||||||
continue;
|
continue;
|
||||||
name_to_match = demangled_name;
|
name_to_match = demangled_name;
|
||||||
}
|
}
|
||||||
else if (exp->expressions[k].language == "Java")
|
else if (exp.language == "Java")
|
||||||
{
|
{
|
||||||
demangled_name = cplus_demangle(symbol_name,
|
demangled_name = cplus_demangle(symbol_name,
|
||||||
(DMGL_ANSI | DMGL_PARAMS
|
(DMGL_ANSI | DMGL_PARAMS
|
||||||
@ -1815,8 +1819,12 @@ Version_script_info::get_symbol_version_helper(const char* symbol_name,
|
|||||||
continue;
|
continue;
|
||||||
name_to_match = demangled_name;
|
name_to_match = demangled_name;
|
||||||
}
|
}
|
||||||
bool matched = fnmatch(exp->expressions[k].pattern.c_str(),
|
bool matched;
|
||||||
name_to_match, FNM_NOESCAPE) == 0;
|
if (exp.exact_match)
|
||||||
|
matched = strcmp(exp.pattern.c_str(), name_to_match) == 0;
|
||||||
|
else
|
||||||
|
matched = fnmatch(exp.pattern.c_str(), name_to_match,
|
||||||
|
FNM_NOESCAPE) == 0;
|
||||||
if (demangled_name != NULL)
|
if (demangled_name != NULL)
|
||||||
free(demangled_name);
|
free(demangled_name);
|
||||||
if (matched)
|
if (matched)
|
||||||
@ -1893,17 +1901,32 @@ script_add_vers_depend(void* closurev,
|
|||||||
extern "C" struct Version_expression_list *
|
extern "C" struct Version_expression_list *
|
||||||
script_new_vers_pattern(void* closurev,
|
script_new_vers_pattern(void* closurev,
|
||||||
struct Version_expression_list *expressions,
|
struct Version_expression_list *expressions,
|
||||||
const char *pattern, int patlen)
|
const char *pattern, int patlen, int exact_match)
|
||||||
{
|
{
|
||||||
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
|
||||||
if (expressions == NULL)
|
if (expressions == NULL)
|
||||||
expressions = closure->version_script()->allocate_expression_list();
|
expressions = closure->version_script()->allocate_expression_list();
|
||||||
expressions->expressions.push_back(
|
expressions->expressions.push_back(
|
||||||
Version_expression(std::string(pattern, patlen),
|
Version_expression(std::string(pattern, patlen),
|
||||||
closure->get_current_language()));
|
closure->get_current_language(),
|
||||||
|
static_cast<bool>(exact_match)));
|
||||||
return expressions;
|
return expressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attaches b to the end of a, and clears b. So a = a + b and b = {}.
|
||||||
|
|
||||||
|
extern "C" struct Version_expression_list*
|
||||||
|
script_merge_expressions(struct Version_expression_list *a,
|
||||||
|
struct Version_expression_list *b)
|
||||||
|
{
|
||||||
|
a->expressions.insert(a->expressions.end(),
|
||||||
|
b->expressions.begin(), b->expressions.end());
|
||||||
|
// We could delete b and remove it from expressions_lists_, but
|
||||||
|
// that's a lot of work. This works just as well.
|
||||||
|
b->expressions.clear();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
// Combine the global and local expressions into a a Version_tree.
|
// Combine the global and local expressions into a a Version_tree.
|
||||||
|
|
||||||
extern "C" struct Version_tree *
|
extern "C" struct Version_tree *
|
||||||
|
@ -28,6 +28,10 @@ void foo1() {} // local
|
|||||||
void bar() {} // V1
|
void bar() {} // V1
|
||||||
void bar1() {} // global
|
void bar1() {} // global
|
||||||
|
|
||||||
|
void baz(int*) {} // V1
|
||||||
|
void baz(int*, char) {} // global
|
||||||
|
void baz(char*, int) {} // global
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void bar2() {} // V1
|
void bar2() {} // V1
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,12 @@ check ver_matching_test.stdout "Base *bla$"
|
|||||||
check ver_matching_test.stdout "V2 *blaz$"
|
check ver_matching_test.stdout "V2 *blaz$"
|
||||||
check ver_matching_test.stdout "V2 *blazb$"
|
check ver_matching_test.stdout "V2 *blazb$"
|
||||||
|
|
||||||
|
# Stuff inside quotes is matched literally, so "baz(int*, char)" should
|
||||||
|
# not match the "baz(int *)" entry in the version table.
|
||||||
|
check ver_matching_test.stdout "V1 *baz(int\\*)$"
|
||||||
|
check_missing ver_matching_test.stdout "V1 *baz(int\\*, char)$"
|
||||||
|
check_missing ver_matching_test.stdout "V1 *baz(char\\*, int)$"
|
||||||
|
|
||||||
# TODO: foo1 should be a local symbol and not show up in the .dynsym
|
# TODO: foo1 should be a local symbol and not show up in the .dynsym
|
||||||
# dump, but we haven't figured out how to suppress it yet.
|
# dump, but we haven't figured out how to suppress it yet.
|
||||||
# check_missing ver_matching_test.stdout "foo1"
|
# check_missing ver_matching_test.stdout "foo1"
|
||||||
|
@ -3,11 +3,16 @@ V1 {
|
|||||||
extern "C++"
|
extern "C++"
|
||||||
{
|
{
|
||||||
"bar()";
|
"bar()";
|
||||||
myns::*;
|
"baz(int*)";
|
||||||
};
|
};
|
||||||
foo;
|
foo;
|
||||||
blaza*;
|
blaza*;
|
||||||
bar*;
|
bar*;
|
||||||
|
# Make sure we parse "extern" when it's not first thing in the section.
|
||||||
|
extern "C++"
|
||||||
|
{
|
||||||
|
myns::*;
|
||||||
|
};
|
||||||
# Would be a keyword in a linker script.
|
# Would be a keyword in a linker script.
|
||||||
SECTIONS;
|
SECTIONS;
|
||||||
sizeof_headers;
|
sizeof_headers;
|
||||||
|
114
gold/yyscript.y
114
gold/yyscript.y
@ -82,6 +82,7 @@
|
|||||||
/* Constants. */
|
/* Constants. */
|
||||||
|
|
||||||
%token <string> STRING
|
%token <string> STRING
|
||||||
|
%token <string> QUOTED_STRING
|
||||||
%token <integer> INTEGER
|
%token <integer> INTEGER
|
||||||
|
|
||||||
/* Keywords. This list is taken from ldgram.y and ldlex.l in the old
|
/* Keywords. This list is taken from ldgram.y and ldlex.l in the old
|
||||||
@ -185,6 +186,7 @@
|
|||||||
%type <versyms> vers_defns
|
%type <versyms> vers_defns
|
||||||
%type <versnode> vers_tag
|
%type <versnode> vers_tag
|
||||||
%type <deplist> verdep
|
%type <deplist> verdep
|
||||||
|
%type <string> string
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -207,7 +209,7 @@ file_cmd:
|
|||||||
{ script_start_group(closure); }
|
{ script_start_group(closure); }
|
||||||
'(' input_list ')'
|
'(' input_list ')'
|
||||||
{ script_end_group(closure); }
|
{ script_end_group(closure); }
|
||||||
| OPTION '(' STRING ')'
|
| OPTION '(' string ')'
|
||||||
{ script_parse_option(closure, $3.value, $3.length); }
|
{ script_parse_option(closure, $3.value, $3.length); }
|
||||||
| VERSIONK '{'
|
| VERSIONK '{'
|
||||||
{ script_push_lex_into_version_mode(closure); }
|
{ script_push_lex_into_version_mode(closure); }
|
||||||
@ -222,9 +224,9 @@ file_cmd:
|
|||||||
these is more-or-less OK since most scripts simply explicitly
|
these is more-or-less OK since most scripts simply explicitly
|
||||||
choose the default. */
|
choose the default. */
|
||||||
ignore_cmd:
|
ignore_cmd:
|
||||||
OUTPUT_FORMAT '(' STRING ')'
|
OUTPUT_FORMAT '(' string ')'
|
||||||
| OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')'
|
| OUTPUT_FORMAT '(' string ',' string ',' string ')'
|
||||||
| OUTPUT_ARCH '(' STRING ')'
|
| OUTPUT_ARCH '(' string ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
/* A list of input file names. */
|
/* A list of input file names. */
|
||||||
@ -235,7 +237,7 @@ input_list:
|
|||||||
|
|
||||||
/* An input file name. */
|
/* An input file name. */
|
||||||
input_list_element:
|
input_list_element:
|
||||||
STRING
|
string
|
||||||
{ script_add_file(closure, $1.value, $1.length); }
|
{ script_add_file(closure, $1.value, $1.length); }
|
||||||
| AS_NEEDED
|
| AS_NEEDED
|
||||||
{ script_start_as_needed(closure); }
|
{ script_start_as_needed(closure); }
|
||||||
@ -246,66 +248,66 @@ input_list_element:
|
|||||||
/* A command which may appear at the top level of a linker script, or
|
/* A command which may appear at the top level of a linker script, or
|
||||||
within a SECTIONS block. */
|
within a SECTIONS block. */
|
||||||
file_or_sections_cmd:
|
file_or_sections_cmd:
|
||||||
ENTRY '(' STRING ')'
|
ENTRY '(' string ')'
|
||||||
{ script_set_entry(closure, $3.value, $3.length); }
|
{ script_set_entry(closure, $3.value, $3.length); }
|
||||||
| assignment end
|
| assignment end
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Set a symbol to a value. */
|
/* Set a symbol to a value. */
|
||||||
assignment:
|
assignment:
|
||||||
STRING '=' parse_exp
|
string '=' parse_exp
|
||||||
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
||||||
| STRING PLUSEQ parse_exp
|
| string PLUSEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_add(s, $3);
|
Expression_ptr e = script_exp_binary_add(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING MINUSEQ parse_exp
|
| string MINUSEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_sub(s, $3);
|
Expression_ptr e = script_exp_binary_sub(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING MULTEQ parse_exp
|
| string MULTEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_mult(s, $3);
|
Expression_ptr e = script_exp_binary_mult(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING DIVEQ parse_exp
|
| string DIVEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_div(s, $3);
|
Expression_ptr e = script_exp_binary_div(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING LSHIFTEQ parse_exp
|
| string LSHIFTEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_lshift(s, $3);
|
Expression_ptr e = script_exp_binary_lshift(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING RSHIFTEQ parse_exp
|
| string RSHIFTEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_rshift(s, $3);
|
Expression_ptr e = script_exp_binary_rshift(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING ANDEQ parse_exp
|
| string ANDEQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_bitwise_and(s, $3);
|
Expression_ptr e = script_exp_binary_bitwise_and(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| STRING OREQ parse_exp
|
| string OREQ parse_exp
|
||||||
{
|
{
|
||||||
Expression_ptr s = script_exp_string($1.value, $1.length);
|
Expression_ptr s = script_exp_string($1.value, $1.length);
|
||||||
Expression_ptr e = script_exp_binary_bitwise_or(s, $3);
|
Expression_ptr e = script_exp_binary_bitwise_or(s, $3);
|
||||||
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
|
||||||
}
|
}
|
||||||
| PROVIDE '(' STRING '=' parse_exp ')'
|
| PROVIDE '(' string '=' parse_exp ')'
|
||||||
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 0); }
|
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 0); }
|
||||||
| PROVIDE_HIDDEN '(' STRING '=' parse_exp ')'
|
| PROVIDE_HIDDEN '(' string '=' parse_exp ')'
|
||||||
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 1); }
|
{ script_set_symbol(closure, $3.value, $3.length, $5, 1, 1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -373,27 +375,29 @@ exp:
|
|||||||
{ $$ = script_exp_integer($1); }
|
{ $$ = script_exp_integer($1); }
|
||||||
| STRING
|
| STRING
|
||||||
{ $$ = script_exp_string($1.value, $1.length); }
|
{ $$ = script_exp_string($1.value, $1.length); }
|
||||||
|
| QUOTED_STRING
|
||||||
|
{ $$ = script_exp_string($1.value, $1.length); }
|
||||||
| MAX_K '(' exp ',' exp ')'
|
| MAX_K '(' exp ',' exp ')'
|
||||||
{ $$ = script_exp_function_max($3, $5); }
|
{ $$ = script_exp_function_max($3, $5); }
|
||||||
| MIN_K '(' exp ',' exp ')'
|
| MIN_K '(' exp ',' exp ')'
|
||||||
{ $$ = script_exp_function_min($3, $5); }
|
{ $$ = script_exp_function_min($3, $5); }
|
||||||
| DEFINED '(' STRING ')'
|
| DEFINED '(' string ')'
|
||||||
{ $$ = script_exp_function_defined($3.value, $3.length); }
|
{ $$ = script_exp_function_defined($3.value, $3.length); }
|
||||||
| SIZEOF_HEADERS
|
| SIZEOF_HEADERS
|
||||||
{ $$ = script_exp_function_sizeof_headers(); }
|
{ $$ = script_exp_function_sizeof_headers(); }
|
||||||
| ALIGNOF '(' STRING ')'
|
| ALIGNOF '(' string ')'
|
||||||
{ $$ = script_exp_function_alignof($3.value, $3.length); }
|
{ $$ = script_exp_function_alignof($3.value, $3.length); }
|
||||||
| SIZEOF '(' STRING ')'
|
| SIZEOF '(' string ')'
|
||||||
{ $$ = script_exp_function_sizeof($3.value, $3.length); }
|
{ $$ = script_exp_function_sizeof($3.value, $3.length); }
|
||||||
| ADDR '(' STRING ')'
|
| ADDR '(' string ')'
|
||||||
{ $$ = script_exp_function_addr($3.value, $3.length); }
|
{ $$ = script_exp_function_addr($3.value, $3.length); }
|
||||||
| LOADADDR '(' STRING ')'
|
| LOADADDR '(' string ')'
|
||||||
{ $$ = script_exp_function_loadaddr($3.value, $3.length); }
|
{ $$ = script_exp_function_loadaddr($3.value, $3.length); }
|
||||||
| ORIGIN '(' STRING ')'
|
| ORIGIN '(' string ')'
|
||||||
{ $$ = script_exp_function_origin($3.value, $3.length); }
|
{ $$ = script_exp_function_origin($3.value, $3.length); }
|
||||||
| LENGTH '(' STRING ')'
|
| LENGTH '(' string ')'
|
||||||
{ $$ = script_exp_function_length($3.value, $3.length); }
|
{ $$ = script_exp_function_length($3.value, $3.length); }
|
||||||
| CONSTANT '(' STRING ')'
|
| CONSTANT '(' string ')'
|
||||||
{ $$ = script_exp_function_constant($3.value, $3.length); }
|
{ $$ = script_exp_function_constant($3.value, $3.length); }
|
||||||
| ABSOLUTE '(' exp ')'
|
| ABSOLUTE '(' exp ')'
|
||||||
{ $$ = script_exp_function_absolute($3); }
|
{ $$ = script_exp_function_absolute($3); }
|
||||||
@ -409,17 +413,17 @@ exp:
|
|||||||
{ $$ = script_exp_function_data_segment_relro_end($3, $5); }
|
{ $$ = script_exp_function_data_segment_relro_end($3, $5); }
|
||||||
| DATA_SEGMENT_END '(' exp ')'
|
| DATA_SEGMENT_END '(' exp ')'
|
||||||
{ $$ = script_exp_function_data_segment_end($3); }
|
{ $$ = script_exp_function_data_segment_end($3); }
|
||||||
| SEGMENT_START '(' STRING ',' exp ')'
|
| SEGMENT_START '(' string ',' exp ')'
|
||||||
{
|
{
|
||||||
$$ = script_exp_function_segment_start($3.value, $3.length, $5);
|
$$ = script_exp_function_segment_start($3.value, $3.length, $5);
|
||||||
}
|
}
|
||||||
| ASSERT_K '(' exp ',' STRING ')'
|
| ASSERT_K '(' exp ',' string ')'
|
||||||
{ $$ = script_exp_function_assert($3, $5.value, $5.length); }
|
{ $$ = script_exp_function_assert($3, $5.value, $5.length); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Handle the --defsym option. */
|
/* Handle the --defsym option. */
|
||||||
defsym_expr:
|
defsym_expr:
|
||||||
STRING '=' parse_exp
|
string '=' parse_exp
|
||||||
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
{ script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -438,23 +442,23 @@ vers_node:
|
|||||||
{
|
{
|
||||||
script_register_vers_node (closure, NULL, 0, $2, NULL);
|
script_register_vers_node (closure, NULL, 0, $2, NULL);
|
||||||
}
|
}
|
||||||
| STRING '{' vers_tag '}' ';'
|
| string '{' vers_tag '}' ';'
|
||||||
{
|
{
|
||||||
script_register_vers_node (closure, $1.value, $1.length, $3,
|
script_register_vers_node (closure, $1.value, $1.length, $3,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
| STRING '{' vers_tag '}' verdep ';'
|
| string '{' vers_tag '}' verdep ';'
|
||||||
{
|
{
|
||||||
script_register_vers_node (closure, $1.value, $1.length, $3, $5);
|
script_register_vers_node (closure, $1.value, $1.length, $3, $5);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
verdep:
|
verdep:
|
||||||
STRING
|
string
|
||||||
{
|
{
|
||||||
$$ = script_add_vers_depend (closure, NULL, $1.value, $1.length);
|
$$ = script_add_vers_depend (closure, NULL, $1.value, $1.length);
|
||||||
}
|
}
|
||||||
| verdep STRING
|
| verdep string
|
||||||
{
|
{
|
||||||
$$ = script_add_vers_depend (closure, $1, $2.value, $2.length);
|
$$ = script_add_vers_depend (closure, $1, $2.value, $2.length);
|
||||||
}
|
}
|
||||||
@ -473,36 +477,70 @@ vers_tag:
|
|||||||
{ $$ = script_new_vers_node (closure, $3, $7); }
|
{ $$ = script_new_vers_node (closure, $3, $7); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* Here is one of the rare places we care about the distinction
|
||||||
|
between STRING and QUOTED_STRING. For QUOTED_STRING, we do exact
|
||||||
|
matching on the pattern, so we pass in true for the exact_match
|
||||||
|
parameter. For STRING, we do glob matching and pass in false. */
|
||||||
vers_defns:
|
vers_defns:
|
||||||
STRING
|
STRING
|
||||||
{
|
{
|
||||||
$$ = script_new_vers_pattern (closure, NULL, $1.value,
|
$$ = script_new_vers_pattern (closure, NULL, $1.value,
|
||||||
$1.length);
|
$1.length, 0);
|
||||||
|
}
|
||||||
|
| QUOTED_STRING
|
||||||
|
{
|
||||||
|
$$ = script_new_vers_pattern (closure, NULL, $1.value,
|
||||||
|
$1.length, 1);
|
||||||
}
|
}
|
||||||
| vers_defns ';' STRING
|
| vers_defns ';' STRING
|
||||||
{
|
{
|
||||||
$$ = script_new_vers_pattern (closure, $1, $3.value, $3.length);
|
$$ = script_new_vers_pattern (closure, $1, $3.value,
|
||||||
|
$3.length, 0);
|
||||||
}
|
}
|
||||||
| /* Push STRING on the language stack. */
|
| vers_defns ';' QUOTED_STRING
|
||||||
EXTERN STRING '{'
|
{
|
||||||
|
$$ = script_new_vers_pattern (closure, $1, $3.value,
|
||||||
|
$3.length, 1);
|
||||||
|
}
|
||||||
|
| /* Push string on the language stack. */
|
||||||
|
EXTERN string '{'
|
||||||
{ version_script_push_lang (closure, $2.value, $2.length); }
|
{ version_script_push_lang (closure, $2.value, $2.length); }
|
||||||
vers_defns opt_semicolon '}'
|
vers_defns opt_semicolon '}'
|
||||||
{
|
{
|
||||||
$$ = $5;
|
$$ = $5;
|
||||||
version_script_pop_lang(closure);
|
version_script_pop_lang(closure);
|
||||||
}
|
}
|
||||||
|
| /* Push string on the language stack. This is more complicated
|
||||||
|
than the other cases because we need to merge the linked-list
|
||||||
|
state from the pre-EXTERN defns and the post-EXTERN defns. */
|
||||||
|
vers_defns ';' EXTERN string '{'
|
||||||
|
{ version_script_push_lang (closure, $4.value, $4.length); }
|
||||||
|
vers_defns opt_semicolon '}'
|
||||||
|
{
|
||||||
|
$$ = script_merge_expressions ($1, $7);
|
||||||
|
version_script_pop_lang(closure);
|
||||||
|
}
|
||||||
| EXTERN // "extern" as a symbol name
|
| EXTERN // "extern" as a symbol name
|
||||||
{
|
{
|
||||||
$$ = script_new_vers_pattern (closure, NULL, "extern",
|
$$ = script_new_vers_pattern (closure, NULL, "extern",
|
||||||
sizeof("extern") - 1);
|
sizeof("extern") - 1, 1);
|
||||||
}
|
}
|
||||||
| vers_defns ';' EXTERN
|
| vers_defns ';' EXTERN
|
||||||
{
|
{
|
||||||
$$ = script_new_vers_pattern (closure, $1, "extern",
|
$$ = script_new_vers_pattern (closure, $1, "extern",
|
||||||
sizeof("extern") - 1);
|
sizeof("extern") - 1, 1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* A string can be either a STRING or a QUOTED_STRING. Almost all the
|
||||||
|
time we don't care, and we use this rule. */
|
||||||
|
string:
|
||||||
|
STRING
|
||||||
|
{ $$ = $1; }
|
||||||
|
| QUOTED_STRING
|
||||||
|
{ $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
/* Some statements require a terminator, which may be a semicolon or a
|
/* Some statements require a terminator, which may be a semicolon or a
|
||||||
comma. */
|
comma. */
|
||||||
end:
|
end:
|
||||||
|
Reference in New Issue
Block a user