X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Fldgram.y;h=36845c4c30447de2c874b75fa7a9d63e0ca23357;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=2df9756aa619eb3e03292d7a69c6a4cbf0aa6c72;hpb=313e35ee7c86c3b28c3c189e463a3de14d7ac2e9;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldgram.y b/ld/ldgram.y index 2df9756aa6..36845c4c30 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,23 +1,23 @@ /* 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 Free Software Foundation, Inc. + Copyright (C) 1991-2020 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 -(at your option) any later version. + 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. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + 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. */ %{ /* @@ -26,10 +26,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define DONTDECLARE_MALLOC -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" -#include "ld.h" +#include "ctf-api.h" +#include "ld.h" #include "ldexp.h" #include "ldver.h" #include "ldlang.h" @@ -46,17 +47,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif static enum section_type sectype; +static lang_memory_region_type *region; -lang_memory_region_type *region; - -boolean ldgram_want_filename = true; -FILE * saved_script_handle = NULL; -boolean force_make_executable = false; - -boolean ldgram_in_script = false; -boolean ldgram_had_equals = false; -boolean ldgram_had_keep = false; -char *ldgram_vers_current_lang = NULL; +static bfd_boolean ldgram_had_keep = FALSE; +static char *ldgram_vers_current_lang = NULL; #define ERROR_NAME_MAX 20 static char *error_names[ERROR_NAME_MAX]; @@ -66,17 +60,25 @@ static int error_index; %} %union { bfd_vma integer; + struct big_int + { + bfd_vma integer; + char *str; + } bigint; + fill_type *fill; char *name; const char *cname; 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 { - boolean filehdr; - boolean phdrs; + bfd_boolean filehdr; + bfd_boolean phdrs; union etree_union *at; union etree_union *flags; } phdr; @@ -88,15 +90,17 @@ static int error_index; } %type exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val -%type opt_exp_without_type -%type fill_opt +%type opt_exp_without_type opt_subalign opt_align +%type fill_opt fill_exp %type exclude_name_list -%type file_NAME_list +%type section_name_list +%type sect_flag_list +%type sect_flags %type memspec_opt casesymlist %type memspec_at_opt %type wildcard_name -%type wildcard_spec -%token INT +%type section_name_spec filename_spec wildcard_maybe_exclude +%token INT %token NAME LNAME %type length %type phdr_qualifiers @@ -104,7 +108,7 @@ static int error_index; %type phdr_opt %type opt_nocrossrefs -%right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ +%right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ %right '?' ':' %left OROR %left ANDAND @@ -119,43 +123,51 @@ static int error_index; %left '*' '/' '%' %right UNARY -%token END +%token END %left '(' %token ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE -%token SECTIONS PHDRS SORT DATA_SEGMENT_ALIGN DATA_SEGMENT_END +%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 INHIBIT_COMMON_ALLOCATION FORCE_GROUP_ALLOCATION +%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 PROVIDE -%type assign_op atype attributes_opt +%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 +%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 %% -file: +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 ; @@ -168,10 +180,11 @@ defsym_expr: NAME '=' exp { ldlex_popstate(); - lang_add_assignment(exp_assop($3,$2,$4)); + lang_add_assignment (exp_defsym ($2, $4)); } + ; -/* SYNTAX WITHIN AN MRI SCRIPT FILE */ +/* SYNTAX WITHIN AN MRI SCRIPT FILE */ mri_script_file: { ldlex_mri_script (); @@ -187,27 +200,27 @@ mri_script_file: mri_script_lines: mri_script_lines mri_script_command NEWLINE - | + | ; mri_script_command: - CHIP exp + CHIP exp | CHIP exp ',' exp - | NAME { - einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1); + | NAME { + einfo(_("%F%P: unrecognised keyword in MRI style script '%s'\n"),$1); } - | LIST { + | LIST { config.map_filename = "-"; } - | ORDER ordernamelist - | ENDWORD - | PUBLIC NAME '=' exp - { mri_public($2, $4); } - | PUBLIC NAME ',' exp - { mri_public($2, $4); } - | PUBLIC NAME exp - { mri_public($2, $3); } - | FORMAT NAME + | ORDER ordernamelist + | ENDWORD + | PUBLIC NAME '=' exp + { mri_public($2, $4); } + | PUBLIC NAME ',' exp + { mri_public($2, $4); } + | PUBLIC NAME exp + { mri_public($2, $3); } + | FORMAT NAME { mri_format($2); } | SECT NAME ',' exp { mri_output_section($2, $4);} @@ -225,16 +238,16 @@ mri_script_command: { mri_alignmod($2,$4); } | ABSOLUTE mri_abs_name_list | LOAD mri_load_name_list - | NAMEWORD NAME - { mri_name($2); } + | NAMEWORD NAME + { mri_name($2); } | ALIAS NAME ',' NAME { mri_alias($2,$4,0);} | ALIAS NAME ',' INT - { mri_alias($2,0,(int) $4);} - | BASE exp + { mri_alias ($2, 0, (int) $4.integer); } + | BASE exp { mri_base($2); } - | TRUNCATE INT - { mri_truncate((unsigned int) $2); } + | TRUNCATE INT + { mri_truncate ((unsigned int) $2.integer); } | CASE casesymlist | EXTERN extern_name_list | INCLUDE filename @@ -242,14 +255,14 @@ mri_script_command: mri_script_lines END { ldlex_popstate (); } | START NAME - { lang_add_entry ($2, false); } - | + { lang_add_entry ($2, FALSE); } + | ; ordernamelist: - ordernamelist ',' NAME { mri_order($3); } - | ordernamelist NAME { mri_order($2); } - | + ordernamelist ',' NAME { mri_order($3); } + | ordernamelist NAME { mri_order($2); } + | ; mri_load_name_list: @@ -259,10 +272,10 @@ mri_load_name_list: ; mri_abs_name_list: - NAME - { mri_only_load($1); } + NAME + { mri_only_load($1); } | mri_abs_name_list ',' NAME - { mri_only_load($3); } + { mri_only_load($3); } ; casesymlist: @@ -271,33 +284,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 @@ -308,32 +321,34 @@ ifile_p1: | floating_point_support | statement_anywhere | version - | ';' + | ';' | TARGET_K '(' NAME ')' { lang_add_target($3); } | SEARCH_DIR '(' filename ')' - { ldfile_add_library_path ($3, false); } + { ldfile_add_library_path ($3, FALSE); } | OUTPUT '(' filename ')' { lang_add_output($3, 1); } - | OUTPUT_FORMAT '(' NAME ')' + | OUTPUT_FORMAT '(' NAME ')' { lang_add_output_format ($3, (char *) NULL, (char *) NULL, 1); } | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')' { lang_add_output_format ($3, $5, $7, 1); } - | OUTPUT_ARCH '(' NAME ')' - { ldfile_set_output_arch($3); } + | OUTPUT_ARCH '(' NAME ')' + { ldfile_set_output_arch ($3, bfd_arch_unknown); } | FORCE_COMMON_ALLOCATION - { command_line.force_common_definition = true ; } + { command_line.force_common_definition = TRUE ; } + | FORCE_GROUP_ALLOCATION + { command_line.force_group_allocation = TRUE ; } | INHIBIT_COMMON_ALLOCATION - { command_line.inhibit_common_definition = true ; } + { link_info.inhibit_common_definition = TRUE ; } | INPUT '(' input_list ')' | GROUP { lang_enter_group (); } '(' input_list ')' { lang_leave_group (); } - | MAP '(' filename ')' + | MAP '(' filename ')' { lang_add_map($3); } - | INCLUDE filename + | INCLUDE filename { ldlex_script (); ldfile_open_command_file($2); } ifile_list END { ldlex_popstate (); } @@ -341,28 +356,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: @@ -377,8 +424,11 @@ sec_or_group_p1: statement_anywhere: ENTRY '(' NAME ')' - { lang_add_entry ($3, false); } + { lang_add_entry ($3, FALSE); } | assignment end + | ASSERT_K {ldlex_expression ();} '(' exp ',' NAME ')' + { ldlex_popstate (); + lang_add_assignment (exp_assert ($4, $6)); } ; /* The '*' and '?' cases are there because the lexer returns them as @@ -398,30 +448,129 @@ wildcard_name: } ; -wildcard_spec: +wildcard_maybe_exclude: wildcard_name { $$.name = $1; - $$.sorted = false; + $$.sorted = none; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } - | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name + | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name { $$.name = $5; - $$.sorted = false; + $$.sorted = none; $$.exclude_name_list = $3; + $$.section_flag_list = NULL; } - | SORT '(' wildcard_name ')' + ; + +filename_spec: + wildcard_maybe_exclude + | SORT_BY_NAME '(' wildcard_maybe_exclude ')' { - $$.name = $3; - $$.sorted = true; - $$.exclude_name_list = NULL; + $$ = $3; + $$.sorted = by_name; } - | SORT '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')' + | SORT_NONE '(' wildcard_maybe_exclude ')' { - $$.name = $7; - $$.sorted = true; - $$.exclude_name_list = $5; + $$ = $3; + $$.sorted = by_none; + } + ; + +section_name_spec: + wildcard_maybe_exclude + | SORT_BY_NAME '(' wildcard_maybe_exclude ')' + { + $$ = $3; + $$.sorted = by_name; + } + | SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' + { + $$ = $3; + $$.sorted = by_alignment; + } + | SORT_NONE '(' wildcard_maybe_exclude ')' + { + $$ = $3; + $$.sorted = by_none; + } + | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')' + { + $$ = $5; + $$.sorted = by_name_alignment; + } + | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')' + { + $$ = $5; + $$.sorted = by_name; + } + | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')' + { + $$ = $5; + $$.sorted = by_alignment_name; + } + | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')' + { + $$ = $5; + $$.sorted = by_alignment; + } + | SORT_BY_INIT_PRIORITY '(' wildcard_maybe_exclude ')' + { + $$ = $3; + $$.sorted = by_init_priority; + } + ; + +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; } ; @@ -432,7 +581,7 @@ exclude_name_list: tmp = (struct name_list *) xmalloc (sizeof *tmp); tmp->name = $2; tmp->next = $1; - $$ = tmp; + $$ = tmp; } | wildcard_name @@ -445,8 +594,8 @@ exclude_name_list: } ; -file_NAME_list: - file_NAME_list opt_comma wildcard_spec +section_name_list: + section_name_list opt_comma section_name_spec { struct wildcard_list *tmp; tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); @@ -455,7 +604,7 @@ file_NAME_list: $$ = tmp; } | - wildcard_spec + section_name_spec { struct wildcard_list *tmp; tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); @@ -471,65 +620,92 @@ input_section_spec_no_keep: struct wildcard_spec tmp; tmp.name = $1; tmp.exclude_name_list = NULL; - tmp.sorted = false; + 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 ']' + | '[' section_name_list ']' { lang_add_wild (NULL, $2, ldgram_had_keep); } - | wildcard_spec '(' file_NAME_list ')' + | sect_flags '[' section_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); + } + | filename_spec '(' section_name_list ')' { lang_add_wild (&$1, $3, ldgram_had_keep); } + | sect_flags filename_spec '(' section_name_list ')' + { + $2.section_flag_list = $1; + lang_add_wild (&$2, $4, ldgram_had_keep); + } ; input_section_spec: input_section_spec_no_keep | KEEP '(' - { ldgram_had_keep = true; } + { ldgram_had_keep = TRUE; } input_section_spec_no_keep ')' - { ldgram_had_keep = false; } + { ldgram_had_keep = FALSE; } ; statement: - assignment end + assignment end | CREATE_OBJECT_SYMBOLS { - lang_add_attribute(lang_object_symbols_statement_enum); - } - | ';' - | CONSTRUCTORS + lang_add_attribute(lang_object_symbols_statement_enum); + } + | ';' + | CONSTRUCTORS { - - lang_add_attribute(lang_constructors_statement_enum); + + lang_add_attribute(lang_constructors_statement_enum); } - | SORT '(' CONSTRUCTORS ')' + | SORT_BY_NAME '(' CONSTRUCTORS ')' { - constructors_sorted = true; + constructors_sorted = TRUE; lang_add_attribute (lang_constructors_statement_enum); } | input_section_spec - | length '(' mustbe_exp ')' - { - lang_add_data((int) $1,$3); - } - - | FILL '(' mustbe_exp ')' - { - lang_add_fill - (exp_get_value_int($3, - 0, - "fill value", - lang_first_phase_enum)); - } + | length '(' mustbe_exp ')' + { + lang_add_data ((int) $1, $3); + } + + | FILL '(' fill_exp ')' + { + 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: statement_list statement - | statement + | statement ; - + statement_list_opt: /* empty */ | statement_list @@ -542,41 +718,41 @@ length: { $$ = $1; } | LONG { $$ = $1; } - | SHORT + | SHORT { $$ = $1; } | BYTE { $$ = $1; } ; -fill_opt: - '=' mustbe_exp +fill_exp: + mustbe_exp { - $$ = exp_get_value_int($2, - 0, - "fill value", - lang_first_phase_enum); + $$ = exp_get_fill ($1, 0, "fill value"); } - | { $$ = 0; } ; - +fill_opt: + '=' fill_exp + { $$ = $2; } + | { $$ = (fill_type *) 0; } + ; assign_op: PLUSEQ { $$ = '+'; } | MINUSEQ { $$ = '-'; } - | MULTEQ + | MULTEQ { $$ = '*'; } - | DIVEQ + | DIVEQ { $$ = '/'; } - | LSHIFTEQ + | LSHIFTEQ { $$ = LSHIFT; } - | RSHIFTEQ + | RSHIFTEQ { $$ = RSHIFT; } - | ANDEQ + | ANDEQ { $$ = '&'; } - | OREQ + | OREQ { $$ = '|'; } ; @@ -588,19 +764,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)); } ; @@ -610,37 +794,39 @@ 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 ; -memory_spec: NAME - { region = lang_memory_region_lookup($1); } +memory_spec: NAME + { region = lang_memory_region_lookup ($1, TRUE); } 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; + } ; length_spec: - LENGTH '=' mustbe_exp - { region->length = exp_get_vma($3, - ~((bfd_vma)0), - "length", - lang_first_phase_enum); + LENGTH '=' mustbe_exp + { + region->length_exp = $3; } ; @@ -691,11 +877,11 @@ low_level_library: floating_point_support: FLOAT - { lang_float(true); } + { lang_float(TRUE); } | NOFLOAT - { lang_float(false); } + { lang_float(FALSE); } ; - + nocrossref_list: /* empty */ { @@ -721,131 +907,181 @@ nocrossref_list: } ; -mustbe_exp: { ldlex_expression(); } +mustbe_exp: { ldlex_expression (); } exp - { ldlex_popstate(); $$=$2;} + { ldlex_popstate (); $$=$2;} ; exp : '-' exp %prec UNARY - { $$ = exp_unop('-', $2); } + { $$ = exp_unop ('-', $2); } | '(' exp ')' { $$ = $2; } | NEXT '(' exp ')' %prec UNARY - { $$ = exp_unop((int) $1,$3); } + { $$ = exp_unop ((int) $1,$3); } | '!' exp %prec UNARY - { $$ = exp_unop('!', $2); } + { $$ = exp_unop ('!', $2); } | '+' exp %prec UNARY { $$ = $2; } | '~' exp %prec UNARY - { $$ = exp_unop('~', $2);} + { $$ = exp_unop ('~', $2);} | exp '*' exp - { $$ = exp_binop('*', $1, $3); } + { $$ = exp_binop ('*', $1, $3); } | exp '/' exp - { $$ = exp_binop('/', $1, $3); } + { $$ = exp_binop ('/', $1, $3); } | exp '%' exp - { $$ = exp_binop('%', $1, $3); } + { $$ = exp_binop ('%', $1, $3); } | exp '+' exp - { $$ = exp_binop('+', $1, $3); } + { $$ = exp_binop ('+', $1, $3); } | exp '-' exp - { $$ = exp_binop('-' , $1, $3); } + { $$ = exp_binop ('-' , $1, $3); } | exp LSHIFT exp - { $$ = exp_binop(LSHIFT , $1, $3); } + { $$ = exp_binop (LSHIFT , $1, $3); } | exp RSHIFT exp - { $$ = exp_binop(RSHIFT , $1, $3); } + { $$ = exp_binop (RSHIFT , $1, $3); } | exp EQ exp - { $$ = exp_binop(EQ , $1, $3); } + { $$ = exp_binop (EQ , $1, $3); } | exp NE exp - { $$ = exp_binop(NE , $1, $3); } + { $$ = exp_binop (NE , $1, $3); } | exp LE exp - { $$ = exp_binop(LE , $1, $3); } - | exp GE exp - { $$ = exp_binop(GE , $1, $3); } + { $$ = exp_binop (LE , $1, $3); } + | exp GE exp + { $$ = exp_binop (GE , $1, $3); } | exp '<' exp - { $$ = exp_binop('<' , $1, $3); } + { $$ = exp_binop ('<' , $1, $3); } | exp '>' exp - { $$ = exp_binop('>' , $1, $3); } + { $$ = exp_binop ('>' , $1, $3); } | exp '&' exp - { $$ = exp_binop('&' , $1, $3); } + { $$ = exp_binop ('&' , $1, $3); } | exp '^' exp - { $$ = exp_binop('^' , $1, $3); } + { $$ = exp_binop ('^' , $1, $3); } | exp '|' exp - { $$ = exp_binop('|' , $1, $3); } + { $$ = exp_binop ('|' , $1, $3); } | exp '?' exp ':' exp - { $$ = exp_trinop('?' , $1, $3, $5); } + { $$ = exp_trinop ('?' , $1, $3, $5); } | exp ANDAND exp - { $$ = exp_binop(ANDAND , $1, $3); } + { $$ = exp_binop (ANDAND , $1, $3); } | exp OROR exp - { $$ = exp_binop(OROR , $1, $3); } + { $$ = exp_binop (OROR , $1, $3); } | DEFINED '(' NAME ')' - { $$ = exp_nameop(DEFINED, $3); } + { $$ = exp_nameop (DEFINED, $3); } | INT - { $$ = exp_intop($1); } - | SIZEOF_HEADERS - { $$ = exp_nameop(SIZEOF_HEADERS,0); } + { $$ = exp_bigintop ($1.integer, $1.str); } + | SIZEOF_HEADERS + { $$ = exp_nameop (SIZEOF_HEADERS,0); } + | ALIGNOF '(' NAME ')' + { $$ = exp_nameop (ALIGNOF,$3); } | SIZEOF '(' NAME ')' - { $$ = exp_nameop(SIZEOF,$3); } + { $$ = exp_nameop (SIZEOF,$3); } | ADDR '(' NAME ')' - { $$ = exp_nameop(ADDR,$3); } + { $$ = exp_nameop (ADDR,$3); } | LOADADDR '(' NAME ')' - { $$ = exp_nameop(LOADADDR,$3); } + { $$ = exp_nameop (LOADADDR,$3); } + | CONSTANT '(' NAME ')' + { $$ = exp_nameop (CONSTANT,$3); } | ABSOLUTE '(' exp ')' - { $$ = exp_unop(ABSOLUTE, $3); } + { $$ = exp_unop (ABSOLUTE, $3); } | ALIGN_K '(' exp ')' - { $$ = exp_unop(ALIGN_K,$3); } + { $$ = exp_unop (ALIGN_K,$3); } + | ALIGN_K '(' exp ',' exp ')' + { $$ = exp_binop (ALIGN_K,$3,$5); } | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); } + | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' + { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); } | DATA_SEGMENT_END '(' exp ')' - { $$ = exp_unop(DATA_SEGMENT_END, $3); } + { $$ = exp_unop (DATA_SEGMENT_END, $3); } + | SEGMENT_START '(' NAME ',' exp ')' + { /* The operands to the expression node are + placed in the opposite order from the way + in which they appear in the script as + that allows us to reuse more code in + fold_binary. */ + $$ = exp_binop (SEGMENT_START, + $5, + exp_nameop (NAME, $3)); } | BLOCK '(' exp ')' - { $$ = exp_unop(ALIGN_K,$3); } + { $$ = exp_unop (ALIGN_K,$3); } | NAME - { $$ = exp_nameop(NAME,$1); } + { $$ = exp_nameop (NAME,$1); } | MAX_K '(' exp ',' exp ')' { $$ = exp_binop (MAX_K, $3, $5 ); } | MIN_K '(' exp ',' exp ')' { $$ = exp_binop (MIN_K, $3, $5 ); } | ASSERT_K '(' exp ',' NAME ')' { $$ = exp_assert ($3, $5); } + | ORIGIN '(' NAME ')' + { $$ = exp_nameop (ORIGIN, $3); } + | LENGTH '(' NAME ')' + { $$ = exp_nameop (LENGTH, $3); } + | LOG2CEIL '(' exp ')' + { $$ = exp_unop (LOG2CEIL, $3); } ; memspec_at_opt: - AT '>' NAME { $$ = $3; } - | { $$ = "*default*"; } - ; + AT '>' NAME { $$ = $3; } + | { $$ = 0; } + ; opt_at: AT '(' exp ')' { $$ = $3; } | { $$ = 0; } ; -section: NAME { ldlex_expression(); } - opt_exp_with_type - opt_at { ldlex_popstate (); ldlex_script (); } +opt_align: + ALIGN_K '(' exp ')' { $$ = $3; } + | { $$ = 0; } + ; + +opt_align_with_input: + ALIGN_WITH_INPUT { $$ = ALIGN_WITH_INPUT; } + | { $$ = 0; } + ; + +opt_subalign: + SUBALIGN '(' exp ')' { $$ = $3; } + | { $$ = 0; } + ; + +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, 0, 0, $4); + $5, $7, $4, $9, $6); } - statement_list_opt - '}' { ldlex_popstate (); ldlex_expression (); } + statement_list_opt + '}' { ldlex_popstate (); ldlex_expression (); } memspec_opt memspec_at_opt phdr_opt fill_opt { ldlex_popstate (); - lang_leave_output_section_statement ($14, $11, $13, $12); + lang_leave_output_section_statement ($18, $15, $17, $16); } opt_comma + {} | OVERLAY { ldlex_expression (); } - opt_exp_without_type opt_nocrossrefs opt_at + opt_exp_without_type opt_nocrossrefs opt_at opt_subalign { ldlex_popstate (); ldlex_script (); } - '{' + '{' { - lang_enter_overlay ($3, $5, (int) $4); + lang_enter_overlay ($3, $6); } overlay_section '}' @@ -853,7 +1089,8 @@ section: NAME { ldlex_expression(); } memspec_opt memspec_at_opt phdr_opt fill_opt { ldlex_popstate (); - lang_leave_overlay ($15, $12, $14, $13); + lang_leave_overlay ($5, (int) $4, + $16, $13, $15, $14); } opt_comma | /* The GROUP case is just enough to support the gcc @@ -864,23 +1101,27 @@ 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: - '(' type ')' - | /* EMPTY */ { sectype = normal_section; } - | '(' ')' { sectype = normal_section; } + '(' type ')' + | /* EMPTY */ { sectype = normal_section; } + | '(' ')' { sectype = normal_section; } ; opt_exp_with_type: @@ -910,7 +1151,7 @@ opt_nocrossrefs: memspec_opt: '>' NAME { $$ = $2; } - | { $$ = "*default*"; } + | { $$ = DEFAULT_MEMORY_REGION; } ; phdr_opt: @@ -925,7 +1166,7 @@ phdr_opt: n = ((struct lang_output_section_phdr_list *) xmalloc (sizeof *n)); n->name = $3; - n->used = false; + n->used = FALSE; n->next = $1; $$ = n; } @@ -982,7 +1223,7 @@ phdr_type: { "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", "PT_SHLIB", - "PT_PHDR" + "PT_PHDR", "PT_TLS" }; s = $1->name.name; @@ -994,6 +1235,20 @@ phdr_type: $$ = exp_intop (i); break; } + if (i == sizeof phdr_types / sizeof phdr_types[0]) + { + if (strcmp (s, "PT_GNU_EH_FRAME") == 0) + $$ = exp_intop (0x6474e550); + else if (strcmp (s, "PT_GNU_STACK") == 0) + $$ = exp_intop (0x6474e551); + else + { + einfo (_("\ +%X%P:%pS: unknown phdr type `%s' (try integer literal)\n"), + NULL, s); + $$ = exp_intop (0); + } + } } } ; @@ -1007,13 +1262,14 @@ phdr_qualifiers: { $$ = $3; if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL) - $$.filehdr = true; + $$.filehdr = TRUE; else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL) - $$.phdrs = true; + $$.phdrs = TRUE; 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:%pS: PHDRS syntax error at `%s'\n"), + NULL, $1); } | AT '(' exp ')' phdr_qualifiers { @@ -1033,6 +1289,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 (current_dynamic_list_p, $1); + } + ; + /* This syntax is used within an external version script file. */ version_script_file: @@ -1116,34 +1400,84 @@ 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 '{' + { + $$ = ldgram_vers_current_lang; + ldgram_vers_current_lang = $4; + } + 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; + } | EXTERN NAME '{' { $$ = ldgram_vers_current_lang; ldgram_vers_current_lang = $2; } - vers_defns '}' + vers_defns opt_semicolon '}' { $$ = $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: + /* empty */ + | ';' ; %% void -yyerror(arg) +yyerror(arg) const char *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 ("%F%P:%pS: %s in %s\n", NULL, arg, error_names[error_index - 1]); else - einfo ("%P%F:%S: %s\n", arg); + einfo ("%F%P:%pS: %s\n", NULL, arg); }