X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gold%2Fyyscript.y;h=37b2670a67ed33f061152d1e2273a6881e5e85c4;hb=cfd4e875aeacf565f945c2818dbfff47807b6199;hp=ad7670904f4fdcd4cd77ec96b790024a804c7e76;hpb=3802b2dd6b937e2904b6e2de087e224437eab493;p=platform%2Fupstream%2Fbinutils.git diff --git a/gold/yyscript.y b/gold/yyscript.y index ad76709..37b2670 100644 --- a/gold/yyscript.y +++ b/gold/yyscript.y @@ -1,6 +1,6 @@ -/* yyscript.y -- linker script grammer for gold. */ +/* yyscript.y -- linker script grammar for gold. */ -/* Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +/* Copyright (C) 2006-2014 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of gold. @@ -30,6 +30,7 @@ #include #include #include +#include #include "script-c.h" @@ -70,10 +71,13 @@ struct Wildcard_section wildcard_section; /* A list of strings. */ String_list_ptr string_list; + /* Information for a program header. */ + struct Phdr_info phdr_info; /* Used for version scripts and within VERSION {}. */ struct Version_dependency_list* deplist; struct Version_expression_list* versyms; struct Version_tree* versnode; + enum Script_section_type section_type; } /* Operators, including a precedence table for expressions. */ @@ -118,11 +122,13 @@ %token BYTE %token CONSTANT %token CONSTRUCTORS +%token COPY %token CREATE_OBJECT_SYMBOLS %token DATA_SEGMENT_ALIGN %token DATA_SEGMENT_END %token DATA_SEGMENT_RELRO_END %token DEFINED +%token DSECT %token ENTRY %token EXCLUDE_FILE %token EXTERN @@ -134,8 +140,10 @@ %token HLL %token INCLUDE %token INHIBIT_COMMON_ALLOCATION +%token INFO %token INPUT %token KEEP +%token LEN %token LENGTH /* LENGTH, l, len */ %token LOADADDR %token LOCAL /* local */ @@ -147,8 +155,10 @@ %token NEXT %token NOCROSSREFS %token NOFLOAT +%token NOLOAD %token ONLY_IF_RO %token ONLY_IF_RW +%token ORG %token ORIGIN /* ORIGIN, o, org */ %token OUTPUT %token OUTPUT_ARCH @@ -190,20 +200,25 @@ %token PARSING_LINKER_SCRIPT %token PARSING_VERSION_SCRIPT %token PARSING_DEFSYM +%token PARSING_DYNAMIC_LIST /* Non-terminal types, where needed. */ -%type parse_exp exp opt_address_and_section_type +%type parse_exp exp %type opt_at opt_align opt_subalign opt_fill -%type section_header +%type section_header opt_address_and_section_type +%type section_type %type section_trailer %type opt_constraint +%type opt_phdr %type data_length %type input_section_no_keep %type wildcard_sections %type wildcard_file wildcard_section %type exclude_names %type wildcard_name +%type phdr_type memory_attr +%type phdr_info %type vers_defns %type vers_tag %type verdep @@ -216,6 +231,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. */ @@ -226,18 +242,41 @@ linker_script: /* A command which may appear at top level of a linker script. */ file_cmd: - GROUP + EXTERN '(' extern_name_list ')' + | FORCE_COMMON_ALLOCATION + { script_set_common_allocation(closure, 1); } + | GROUP { script_start_group(closure); } '(' input_list ')' { script_end_group(closure); } + | INHIBIT_COMMON_ALLOCATION + { script_set_common_allocation(closure, 0); } + | INPUT '(' input_list ')' + | MEMORY '{' memory_defs '}' | OPTION '(' string ')' { script_parse_option(closure, $3.value, $3.length); } + | OUTPUT_FORMAT '(' string ')' + { + if (!script_check_output_format(closure, $3.value, $3.length, + NULL, 0, NULL, 0)) + YYABORT; + } + | OUTPUT_FORMAT '(' string ',' string ',' string ')' + { + if (!script_check_output_format(closure, $3.value, $3.length, + $5.value, $5.length, + $7.value, $7.length)) + YYABORT; + } + | PHDRS '{' phdrs_defs '}' | SEARCH_DIR '(' string ')' { script_add_search_dir(closure, $3.value, $3.length); } | SECTIONS '{' { script_start_sections(closure); } sections_block '}' { script_finish_sections(closure); } + | TARGET_K '(' string ')' + { script_set_target(closure, $3.value, $3.length); } | VERSIONK '{' { script_push_lex_into_version_mode(closure); } version_script '}' @@ -252,9 +291,26 @@ file_cmd: these is more-or-less OK since most scripts simply explicitly choose the default. */ ignore_cmd: - OUTPUT_FORMAT '(' string ')' - | OUTPUT_FORMAT '(' string ',' string ',' string ')' - | OUTPUT_ARCH '(' string ')' + OUTPUT_ARCH '(' string ')' + ; + +/* A list of external undefined symbols. We put the lexer into + expression mode so that commas separate names; this is what the GNU + linker does. */ + +extern_name_list: + { script_push_lex_into_expression_mode(closure); } + extern_name_list_body + { script_pop_lex_mode(closure); } + ; + +extern_name_list_body: + string + { script_add_extern(closure, $1.value, $1.length); } + | extern_name_list_body string + { script_add_extern(closure, $2.value, $2.length); } + | extern_name_list_body ',' string + { script_add_extern(closure, $3.value, $3.length); } ; /* A list of input file names. */ @@ -267,6 +323,8 @@ input_list: input_list_element: string { script_add_file(closure, $1.value, $1.length); } + | '-' STRING + { script_add_library(closure, $2.value, $2.length); } | AS_NEEDED { script_start_as_needed(closure); } '(' input_list ')' @@ -296,7 +354,8 @@ section_header: { script_pop_lex_mode(closure); } opt_constraint { - $$.address = $2; + $$.address = $2.address; + $$.section_type = $2.section_type; $$.load_address = $3; $$.align = $4; $$.subalign = $5; @@ -309,18 +368,61 @@ section_header: '(' in section_header. */ opt_address_and_section_type: - ':' - { $$ = NULL; } + ':' + { + $$.address = NULL; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | '(' ')' ':' - { $$ = NULL; } + { + $$.address = NULL; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | exp ':' - { $$ = $1; } + { + $$.address = $1; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | exp '(' ')' ':' - { $$ = $1; } - | exp '(' string ')' ':' { - yyerror(closure, "section types are not supported"); - $$ = $1; + $$.address = $1; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } + | '(' section_type ')' ':' + { + $$.address = NULL; + $$.section_type = $2; + } + | exp '(' section_type ')' ':' + { + $$.address = $1; + $$.section_type = $3; + } + ; + +/* We only support NOLOAD. */ +section_type: + NOLOAD + { $$ = SCRIPT_SECTION_TYPE_NOLOAD; } + | DSECT + { + yyerror(closure, "DSECT section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_DSECT; + } + | COPY + { + yyerror(closure, "COPY section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_COPY; + } + | INFO + { + yyerror(closure, "INFO section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_INFO; + } + | OVERLAY + { + yyerror(closure, "OVERLAY section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_OVERLAY; } ; @@ -365,28 +467,30 @@ section_trailer: opt_memspec opt_at_memspec opt_phdr opt_fill opt_comma { $$.fill = $4; + $$.phdrs = $3; } ; /* A memory specification for an output section. */ opt_memspec: '>' string - { yyerror(closure, "memory regions are not supported"); } + { script_set_section_region(closure, $2.value, $2.length, 1); } | /* empty */ ; /* A memory specification for where to load an output section. */ opt_at_memspec: AT '>' string - { yyerror(closure, "memory regions are not supported"); } + { script_set_section_region(closure, $3.value, $3.length, 0); } | /* empty */ ; /* The program segment an output section should go into. */ opt_phdr: opt_phdr ':' string - { yyerror(closure, "program headers are not supported"); } + { $$ = script_string_list_push_back($1, $3.value, $3.length); } | /* empty */ + { $$ = NULL; } ; /* The value to use to fill an output section. FIXME: This does not @@ -424,6 +528,8 @@ section_cmd: nothing, we accept it and ignore it. */ } | SORT_BY_NAME '(' CONSTRUCTORS ')' + | INCLUDE string + { script_include_directive(closure, $2.value, $2.length); } | ';' ; @@ -585,6 +691,110 @@ file_or_sections_cmd: | assignment end | ASSERT_K '(' parse_exp ',' string ')' { script_add_assertion(closure, $3, $5.value, $5.length); } + | INCLUDE string + { script_include_directive(closure, $2.value, $2.length); } + ; + +/* A list of MEMORY definitions. */ +memory_defs: + memory_defs opt_comma memory_def + | /* empty */ + ; + +/* A single MEMORY definition. */ +memory_def: + string memory_attr ':' memory_origin '=' parse_exp opt_comma memory_length '=' parse_exp + { script_add_memory(closure, $1.value, $1.length, $2, $6, $10); } + | + /* LD supports an INCLUDE directive here, currently GOLD does not. */ + INCLUDE string + { script_include_directive(closure, $2.value, $2.length); } + | + ; + +/* The (optional) attributes of a MEMORY region. */ +memory_attr: + '(' string ')' + { $$ = script_parse_memory_attr(closure, $2.value, $2.length, 0); } + | /* Inverted attributes. */ + '(' '!' string ')' + { $$ = script_parse_memory_attr(closure, $3.value, $3.length, 1); } + | /* empty */ + { $$ = 0; } + ; + +memory_origin: + ORIGIN + | + ORG + | + 'o' + ; + +memory_length: + LENGTH + | + LEN + | + 'l' + ; + +/* A list of program header definitions. */ +phdrs_defs: + phdrs_defs phdr_def + | /* empty */ + ; + +/* A program header definition. */ +phdr_def: + string phdr_type phdr_info ';' + { script_add_phdr(closure, $1.value, $1.length, $2, &$3); } + ; + +/* A program header type. The GNU linker accepts a general expression + here, but that would be a pain because we would have to dig into + the expression structure. It's unlikely that anybody uses anything + other than a string or a number here, so that is all we expect. */ +phdr_type: + string + { $$ = script_phdr_string_to_type(closure, $1.value, $1.length); } + | INTEGER + { $$ = $1; } + ; + +/* Additional information for a program header. */ +phdr_info: + /* empty */ + { memset(&$$, 0, sizeof(struct Phdr_info)); } + | string phdr_info + { + $$ = $2; + if ($1.length == 7 && strncmp($1.value, "FILEHDR", 7) == 0) + $$.includes_filehdr = 1; + else + yyerror(closure, "PHDRS syntax error"); + } + | PHDRS phdr_info + { + $$ = $2; + $$.includes_phdrs = 1; + } + | string '(' INTEGER ')' phdr_info + { + $$ = $5; + if ($1.length == 5 && strncmp($1.value, "FLAGS", 5) == 0) + { + $$.is_flags_valid = 1; + $$.flags = $3; + } + else + yyerror(closure, "PHDRS syntax error"); + } + | AT '(' parse_exp ')' phdr_info + { + $$ = $5; + $$.load_address = $3; + } ; /* Set a symbol to a value. */ @@ -708,7 +918,7 @@ exp: | INTEGER { $$ = script_exp_integer($1); } | string - { $$ = script_exp_string($1.value, $1.length); } + { $$ = script_symbol(closure, $1.value, $1.length); } | MAX_K '(' exp ',' exp ')' { $$ = script_exp_function_max($3, $5); } | MIN_K '(' exp ',' exp ')' @@ -726,9 +936,9 @@ exp: | LOADADDR '(' string ')' { $$ = script_exp_function_loadaddr($3.value, $3.length); } | ORIGIN '(' string ')' - { $$ = script_exp_function_origin($3.value, $3.length); } + { $$ = script_exp_function_origin(closure, $3.value, $3.length); } | LENGTH '(' string ')' - { $$ = script_exp_function_length($3.value, $3.length); } + { $$ = script_exp_function_length(closure, $3.value, $3.length); } | CONSTANT '(' string ')' { $$ = script_exp_function_constant($3.value, $3.length); } | ABSOLUTE '(' exp ')' @@ -740,14 +950,24 @@ exp: | BLOCK '(' exp ')' { $$ = script_exp_function_align(script_exp_string(".", 1), $3); } | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' - { $$ = script_exp_function_data_segment_align($3, $5); } + { + script_data_segment_align(closure); + $$ = script_exp_function_data_segment_align($3, $5); + } | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' - { $$ = script_exp_function_data_segment_relro_end($3, $5); } + { + script_data_segment_relro_end(closure); + $$ = script_exp_function_data_segment_relro_end($3, $5); + } | DATA_SEGMENT_END '(' exp ')' { $$ = script_exp_function_data_segment_end($3); } | SEGMENT_START '(' string ',' exp ')' { $$ = script_exp_function_segment_start($3.value, $3.length, $5); + /* We need to take note of any SEGMENT_START expressions + because they change the behaviour of -Ttext, -Tdata and + -Tbss options. */ + script_saw_segment_start_expression(closure); } | ASSERT_K '(' exp ',' string ')' { $$ = script_exp_function_assert($3, $5.value, $5.length); } @@ -759,6 +979,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