X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fldgram.y;h=9973b07fcc7b33537a5505985bf500d3970882b0;hb=ff20cab8a222c43de501a340016e11cae6a272a7;hp=49f274d259de49cfb1773fe7ccb955b0b3640c76;hpb=3ec5763260bc86f8b87d3ad985336665120edf0b;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldgram.y b/ld/ldgram.y index 49f274d259..9973b07fcc 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,13 +1,12 @@ /* A YACC grammar to parse a superset of the AT&T linker scripting language. - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1991-2016 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). - This file is part of GNU ld. + This file is part of the GNU Binutils. 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 2 of the License, or + 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, @@ -17,7 +16,8 @@ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ %{ /* @@ -26,8 +26,8 @@ #define DONTDECLARE_MALLOC -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "ld.h" #include "ldexp.h" @@ -46,15 +46,8 @@ #endif static enum section_type sectype; +static lang_memory_region_type *region; -lang_memory_region_type *region; - -bfd_boolean ldgram_want_filename = TRUE; -FILE *saved_script_handle = NULL; -bfd_boolean force_make_executable = FALSE; - -bfd_boolean ldgram_in_script = FALSE; -bfd_boolean ldgram_had_equals = FALSE; bfd_boolean ldgram_had_keep = FALSE; char *ldgram_vers_current_lang = NULL; @@ -77,6 +70,8 @@ static int error_index; struct wildcard_spec wildcard; struct wildcard_list *wildcard_list; struct name_list *name_list; + struct flag_info_list *flag_info_list; + struct flag_info *flag_info; int token; union etree_union *etree; struct phdr_info @@ -94,10 +89,12 @@ static int error_index; } %type exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val -%type opt_exp_without_type opt_subalign +%type opt_exp_without_type opt_subalign opt_align %type fill_opt fill_exp %type exclude_name_list %type file_NAME_list +%type sect_flag_list +%type sect_flags %type memspec_opt casesymlist %type memspec_at_opt %type wildcard_name @@ -128,35 +125,40 @@ static int error_index; %token END %left '(' %token ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE -%token SECTIONS PHDRS DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END -%token SORT_BY_NAME SORT_BY_ALIGNMENT +%token SECTIONS PHDRS INSERT_K AFTER BEFORE +%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END +%token SORT_BY_NAME SORT_BY_ALIGNMENT SORT_NONE +%token SORT_BY_INIT_PRIORITY %token '{' '}' %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token INHIBIT_COMMON_ALLOCATION -%token SIZEOF_HEADERS %token SEGMENT_START %token INCLUDE -%token MEMORY DEFSYMEND +%token MEMORY +%token REGION_ALIAS +%token LD_FEATURE %token NOLOAD DSECT COPY INFO OVERLAY -%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY +%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY %token NEXT -%token SIZEOF ADDR LOADADDR MAX_K MIN_K -%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS +%token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K +%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS NOCROSSREFS_TO %token ORIGIN FILL %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS -%token ALIGNMOD AT SUBALIGN PROVIDE -%type assign_op atype attributes_opt sect_constraint +%token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED +%type assign_op atype attributes_opt sect_constraint opt_align_with_input %type filename %token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K -%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL +%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START %token VERS_TAG VERS_IDENTIFIER %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT -%token KEEP ONLY_IF_RO ONLY_IF_RW +%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT %token EXCLUDE_FILE +%token CONSTANT %type vers_defns %type vers_tag %type verdep +%token INPUT_DYNAMIC_LIST %% @@ -164,6 +166,7 @@ file: INPUT_SCRIPT script_file | INPUT_MRI_SCRIPT mri_script_file | INPUT_VERSION_SCRIPT version_script_file + | INPUT_DYNAMIC_LIST dynamic_list_file | INPUT_DEFSYM defsym_expr ; @@ -176,7 +179,7 @@ defsym_expr: NAME '=' exp { ldlex_popstate(); - lang_add_assignment(exp_assop($3,$2,$4)); + lang_add_assignment (exp_defsym ($2, $4)); } ; @@ -280,33 +283,33 @@ casesymlist: | casesymlist ',' NAME ; +/* Parsed as expressions so that commas separate entries */ extern_name_list: + { ldlex_expression (); } + extern_name_list_body + { ldlex_popstate (); } + +extern_name_list_body: NAME - { ldlang_add_undef ($1); } - | extern_name_list NAME - { ldlang_add_undef ($2); } - | extern_name_list ',' NAME - { ldlang_add_undef ($3); } + { ldlang_add_undef ($1, FALSE); } + | extern_name_list_body NAME + { ldlang_add_undef ($2, FALSE); } + | extern_name_list_body ',' NAME + { ldlang_add_undef ($3, FALSE); } ; script_file: - { - ldlex_both(); - } - ifile_list - { - ldlex_popstate(); - } + { ldlex_both(); } + ifile_list + { ldlex_popstate(); } ; - ifile_list: - ifile_list ifile_p1 + ifile_list ifile_p1 | ; - ifile_p1: memory | sections @@ -350,28 +353,60 @@ ifile_p1: { lang_add_nocrossref ($3); } + | NOCROSSREFS_TO '(' nocrossref_list ')' + { + lang_add_nocrossref_to ($3); + } | EXTERN '(' extern_name_list ')' + | INSERT_K AFTER NAME + { lang_add_insert ($3, 0); } + | INSERT_K BEFORE NAME + { lang_add_insert ($3, 1); } + | REGION_ALIAS '(' NAME ',' NAME ')' + { lang_memory_region_alias ($3, $5); } + | LD_FEATURE '(' NAME ')' + { lang_ld_feature ($3); } ; input_list: + { ldlex_inputlist(); } + input_list1 + { ldlex_popstate(); } + +input_list1: NAME { lang_add_input_file($1,lang_input_file_is_search_file_enum, (char *)NULL); } - | input_list ',' NAME + | input_list1 ',' NAME { lang_add_input_file($3,lang_input_file_is_search_file_enum, (char *)NULL); } - | input_list NAME + | input_list1 NAME { lang_add_input_file($2,lang_input_file_is_search_file_enum, (char *)NULL); } | LNAME { lang_add_input_file($1,lang_input_file_is_l_enum, (char *)NULL); } - | input_list ',' LNAME + | input_list1 ',' LNAME { lang_add_input_file($3,lang_input_file_is_l_enum, (char *)NULL); } - | input_list LNAME + | input_list1 LNAME { lang_add_input_file($2,lang_input_file_is_l_enum, (char *)NULL); } + | AS_NEEDED '(' + { $$ = input_flags.add_DT_NEEDED_for_regular; + input_flags.add_DT_NEEDED_for_regular = TRUE; } + input_list1 ')' + { input_flags.add_DT_NEEDED_for_regular = $3; } + | input_list1 ',' AS_NEEDED '(' + { $$ = input_flags.add_DT_NEEDED_for_regular; + input_flags.add_DT_NEEDED_for_regular = TRUE; } + input_list1 ')' + { input_flags.add_DT_NEEDED_for_regular = $5; } + | input_list1 AS_NEEDED '(' + { $$ = input_flags.add_DT_NEEDED_for_regular; + input_flags.add_DT_NEEDED_for_regular = TRUE; } + input_list1 ')' + { input_flags.add_DT_NEEDED_for_regular = $4; } ; sections: @@ -416,54 +451,128 @@ wildcard_spec: $$.name = $1; $$.sorted = none; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name { $$.name = $5; $$.sorted = none; $$.exclude_name_list = $3; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' wildcard_name ')' { $$.name = $3; $$.sorted = by_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' wildcard_name ')' { $$.name = $3; $$.sorted = by_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; + } + | SORT_NONE '(' wildcard_name ')' + { + $$.name = $3; + $$.sorted = by_none; + $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_name_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_alignment_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')' { $$.name = $7; $$.sorted = by_name; $$.exclude_name_list = $5; + $$.section_flag_list = NULL; + } + | SORT_BY_INIT_PRIORITY '(' wildcard_name ')' + { + $$.name = $3; + $$.sorted = by_init_priority; + $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; + } + ; + +sect_flag_list: NAME + { + struct flag_info_list *n; + n = ((struct flag_info_list *) xmalloc (sizeof *n)); + if ($1[0] == '!') + { + n->with = without_flags; + n->name = &$1[1]; + } + else + { + n->with = with_flags; + n->name = $1; + } + n->valid = FALSE; + n->next = NULL; + $$ = n; + } + | sect_flag_list '&' NAME + { + struct flag_info_list *n; + n = ((struct flag_info_list *) xmalloc (sizeof *n)); + if ($3[0] == '!') + { + n->with = without_flags; + n->name = &$3[1]; + } + else + { + n->with = with_flags; + n->name = $3; + } + n->valid = FALSE; + n->next = $1; + $$ = n; + } + ; + +sect_flags: + INPUT_SECTION_FLAGS '(' sect_flag_list ')' + { + struct flag_info *n; + n = ((struct flag_info *) xmalloc (sizeof *n)); + n->flag_list = $3; + n->flags_initialized = FALSE; + n->not_with_flags = 0; + n->only_with_flags = 0; + $$ = n; } ; @@ -514,16 +623,40 @@ input_section_spec_no_keep: tmp.name = $1; tmp.exclude_name_list = NULL; tmp.sorted = none; + tmp.section_flag_list = NULL; + lang_add_wild (&tmp, NULL, ldgram_had_keep); + } + | sect_flags NAME + { + struct wildcard_spec tmp; + tmp.name = $2; + tmp.exclude_name_list = NULL; + tmp.sorted = none; + tmp.section_flag_list = $1; lang_add_wild (&tmp, NULL, ldgram_had_keep); } | '[' file_NAME_list ']' { lang_add_wild (NULL, $2, ldgram_had_keep); } + | sect_flags '[' file_NAME_list ']' + { + struct wildcard_spec tmp; + tmp.name = NULL; + tmp.exclude_name_list = NULL; + tmp.sorted = none; + tmp.section_flag_list = $1; + lang_add_wild (&tmp, $3, ldgram_had_keep); + } | wildcard_spec '(' file_NAME_list ')' { lang_add_wild (&$1, $3, ldgram_had_keep); } + | sect_flags wildcard_spec '(' file_NAME_list ')' + { + $2.section_flag_list = $1; + lang_add_wild (&$2, $4, ldgram_had_keep); + } ; input_section_spec: @@ -561,6 +694,13 @@ statement: { lang_add_fill ($3); } + | ASSERT_K {ldlex_expression ();} '(' exp ',' NAME ')' end + { ldlex_popstate (); + lang_add_assignment (exp_assert ($4, $6)); } + | INCLUDE filename + { ldlex_script (); ldfile_open_command_file($2); } + statement_list_opt END + { ldlex_popstate (); } ; statement_list: @@ -589,10 +729,7 @@ length: fill_exp: mustbe_exp { - $$ = exp_get_fill ($1, - 0, - "fill value", - lang_first_phase_enum); + $$ = exp_get_fill ($1, 0, "fill value"); } ; @@ -629,19 +766,27 @@ end: ';' | ',' assignment: NAME '=' mustbe_exp { - lang_add_assignment (exp_assop ($2, $1, $3)); + lang_add_assignment (exp_assign ($1, $3, FALSE)); } | NAME assign_op mustbe_exp { - lang_add_assignment (exp_assop ('=', $1, - exp_binop ($2, - exp_nameop (NAME, - $1), - $3))); + lang_add_assignment (exp_assign ($1, + exp_binop ($2, + exp_nameop (NAME, + $1), + $3), FALSE)); + } + | HIDDEN '(' NAME '=' mustbe_exp ')' + { + lang_add_assignment (exp_assign ($3, $5, TRUE)); } | PROVIDE '(' NAME '=' mustbe_exp ')' { - lang_add_assignment (exp_provide ($3, $5)); + lang_add_assignment (exp_provide ($3, $5, FALSE)); + } + | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')' + { + lang_add_assignment (exp_provide ($3, $5, TRUE)); } ; @@ -651,13 +796,14 @@ opt_comma: memory: - MEMORY '{' memory_spec memory_spec_list '}' + MEMORY '{' memory_spec_list_opt '}' ; +memory_spec_list_opt: memory_spec_list | ; + memory_spec_list: - memory_spec_list memory_spec - | memory_spec_list ',' memory_spec - | + memory_spec_list opt_comma memory_spec + | memory_spec ; @@ -666,22 +812,24 @@ memory_spec: NAME attributes_opt ':' origin_spec opt_comma length_spec {} + | INCLUDE filename + { ldlex_script (); ldfile_open_command_file($2); } + memory_spec_list_opt END + { ldlex_popstate (); } ; origin_spec: ORIGIN '=' mustbe_exp - { region->current = - region->origin = - exp_get_vma($3, 0L,"origin", lang_first_phase_enum); -} + { + region->origin_exp = $3; + region->current = region->origin; + } ; length_spec: LENGTH '=' mustbe_exp - { region->length = exp_get_vma($3, - ~((bfd_vma)0), - "length", - lang_first_phase_enum); + { + region->length_exp = $3; } ; @@ -826,12 +974,16 @@ exp : | SIZEOF_HEADERS { $$ = exp_nameop (SIZEOF_HEADERS,0); } + | ALIGNOF '(' NAME ')' + { $$ = exp_nameop (ALIGNOF,$3); } | SIZEOF '(' NAME ')' { $$ = exp_nameop (SIZEOF,$3); } | ADDR '(' NAME ')' { $$ = exp_nameop (ADDR,$3); } | LOADADDR '(' NAME ')' { $$ = exp_nameop (LOADADDR,$3); } + | CONSTANT '(' NAME ')' + { $$ = exp_nameop (CONSTANT,$3); } | ABSOLUTE '(' exp ')' { $$ = exp_unop (ABSOLUTE, $3); } | ALIGN_K '(' exp ')' @@ -867,6 +1019,8 @@ exp : { $$ = exp_nameop (ORIGIN, $3); } | LENGTH '(' NAME ')' { $$ = exp_nameop (LENGTH, $3); } + | LOG2CEIL '(' exp ')' + { $$ = exp_unop (LOG2CEIL, $3); } ; @@ -880,6 +1034,16 @@ opt_at: | { $$ = 0; } ; +opt_align: + ALIGN_K '(' exp ')' { $$ = $3; } + | { $$ = 0; } + ; + +opt_align_with_input: + ALIGN_WITH_INPUT { $$ = ALIGN_WITH_INPUT; } + | { $$ = 0; } + ; + opt_subalign: SUBALIGN '(' exp ')' { $$ = $3; } | { $$ = 0; } @@ -888,26 +1052,29 @@ opt_subalign: sect_constraint: ONLY_IF_RO { $$ = ONLY_IF_RO; } | ONLY_IF_RW { $$ = ONLY_IF_RW; } + | SPECIAL { $$ = SPECIAL; } | { $$ = 0; } ; section: NAME { ldlex_expression(); } opt_exp_with_type opt_at + opt_align + opt_align_with_input opt_subalign { ldlex_popstate (); ldlex_script (); } sect_constraint '{' { lang_enter_output_section_statement($1, $3, sectype, - 0, $5, $4, $7); + $5, $7, $4, $9, $6); } statement_list_opt '}' { ldlex_popstate (); ldlex_expression (); } memspec_opt memspec_at_opt phdr_opt fill_opt { ldlex_popstate (); - lang_leave_output_section_statement ($16, $13, $15, $14); + lang_leave_output_section_statement ($18, $15, $17, $16); } opt_comma {} @@ -937,17 +1104,21 @@ section: NAME { ldlex_expression(); } opt_exp_with_type { ldlex_popstate (); - lang_add_assignment (exp_assop ('=', ".", $3)); + lang_add_assignment (exp_assign (".", $3, FALSE)); } '{' sec_or_group_p1 '}' + | INCLUDE filename + { ldlex_script (); ldfile_open_command_file($2); } + sec_or_group_p1 END + { ldlex_popstate (); } ; type: NOLOAD { sectype = noload_section; } - | DSECT { sectype = dsect_section; } - | COPY { sectype = copy_section; } - | INFO { sectype = info_section; } - | OVERLAY { sectype = overlay_section; } + | DSECT { sectype = noalloc_section; } + | COPY { sectype = noalloc_section; } + | INFO { sectype = noalloc_section; } + | OVERLAY { sectype = noalloc_section; } ; atype: @@ -1077,7 +1248,7 @@ phdr_type: { einfo (_("\ %X%P:%S: unknown phdr type `%s' (try integer literal)\n"), - s); + NULL, s); $$ = exp_intop (0); } } @@ -1100,7 +1271,8 @@ phdr_qualifiers: else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL) $$.flags = $2; else - einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), $1); + einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), + NULL, $1); } | AT '(' exp ')' phdr_qualifiers { @@ -1120,6 +1292,34 @@ phdr_val: } ; +dynamic_list_file: + { + ldlex_version_file (); + PUSH_ERROR (_("dynamic list")); + } + dynamic_list_nodes + { + ldlex_popstate (); + POP_ERROR (); + } + ; + +dynamic_list_nodes: + dynamic_list_node + | dynamic_list_nodes dynamic_list_node + ; + +dynamic_list_node: + '{' dynamic_list_tag '}' ';' + ; + +dynamic_list_tag: + vers_defns ';' + { + lang_append_dynamic_list ($1); + } + ; + /* This syntax is used within an external version script file. */ version_script_file: @@ -1203,11 +1403,19 @@ vers_tag: vers_defns: VERS_IDENTIFIER { - $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang); + $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE); + } + | NAME + { + $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE); } | vers_defns ';' VERS_IDENTIFIER { - $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang); + $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE); + } + | vers_defns ';' NAME + { + $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE); } | vers_defns ';' EXTERN NAME '{' { @@ -1216,6 +1424,9 @@ vers_defns: } vers_defns opt_semicolon '}' { + struct bfd_elf_version_expr *pat; + for (pat = $7; pat->next != NULL; pat = pat->next); + pat->next = $1; $$ = $7; ldgram_vers_current_lang = $6; } @@ -1229,6 +1440,30 @@ vers_defns: $$ = $5; ldgram_vers_current_lang = $4; } + | GLOBAL + { + $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE); + } + | vers_defns ';' GLOBAL + { + $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE); + } + | LOCAL + { + $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE); + } + | vers_defns ';' LOCAL + { + $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE); + } + | EXTERN + { + $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE); + } + | vers_defns ';' EXTERN + { + $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE); + } ; opt_semicolon: @@ -1243,9 +1478,9 @@ yyerror(arg) { if (ldfile_assumed_script) einfo (_("%P:%s: file format not recognized; treating as linker script\n"), - ldfile_input_filename); + ldlex_filename ()); if (error_index > 0 && error_index < ERROR_NAME_MAX) - einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]); + einfo ("%P%F:%S: %s in %s\n", NULL, arg, error_names[error_index - 1]); else - einfo ("%P%F:%S: %s\n", arg); + einfo ("%P%F:%S: %s\n", NULL, arg); }