X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fldgram.y;h=718981281576188e9ca4d6d0ec1e99df39c901cf;hb=d1bcade6ba573fe30ebc48d71cbc53e4085a9502;hp=d9a6bff6a6af0d3432340451e5afda0b99ba16c3;hpb=5735ac9e57fe37d7984e6f71d551f9b0ebd87721;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldgram.y b/ld/ldgram.y index d9a6bff6a6..7189812815 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,5 +1,6 @@ /* A YACC grammer to parse a superset of the AT&T linker scripting languaue. - Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of GNU ld. @@ -37,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ldmisc.h" #include "ldmain.h" #include "mri.h" +#include "ldctor.h" #include "ldlex.h" #ifndef YYDEBUG @@ -47,15 +49,15 @@ static enum section_type sectype; lang_memory_region_type *region; - -char *current_file; +struct wildcard_spec current_file; boolean ldgram_want_filename = true; boolean had_script = false; 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; #define ERROR_NAME_MAX 20 static char *error_names[ERROR_NAME_MAX]; @@ -66,6 +68,9 @@ static int error_index; %union { bfd_vma integer; char *name; + const char *cname; + struct wildcard_spec wildcard; + struct name_list *name_list; int token; union etree_union *etree; struct phdr_info @@ -76,16 +81,27 @@ static int error_index; union etree_union *flags; } phdr; struct lang_nocrossref *nocrossref; + struct lang_output_section_phdr_list *section_phdr; + struct bfd_elf_version_deps *deflist; + struct bfd_elf_version_expr *versyms; + struct bfd_elf_version_tree *versnode; } %type exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val +%type opt_exp_without_type %type fill_opt +%type exclude_name_list %type memspec_opt casesymlist +%type memspec_at_opt +%type wildcard_name +%type wildcard_spec %token INT %token NAME LNAME %type length %type phdr_qualifiers %type nocrossref_list +%type phdr_opt +%type opt_nocrossrefs %right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ %right '?' ':' @@ -104,8 +120,8 @@ static int error_index; %right UNARY %token END %left '(' -%token ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE -%token SECTIONS PHDRS +%token ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE +%token SECTIONS PHDRS SORT %token '{' '}' %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token SIZEOF_HEADERS @@ -113,22 +129,31 @@ static int error_index; %token MEMORY DEFSYMEND %token NOLOAD DSECT COPY INFO OVERLAY %token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY -%token SIZEOF NEXT ADDR LOADADDR +%token NEXT +%token SIZEOF ADDR LOADADDR MAX_K MIN_K %token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS %token ORIGIN FILL %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS %token ALIGNMOD AT PROVIDE -%type assign_op atype +%type assign_op atype attributes_opt %type filename -%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD +%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K %token 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 EXCLUDE_FILE +%type vers_defns +%type vers_tag +%type verdep %% file: INPUT_SCRIPT script_file | INPUT_MRI_SCRIPT mri_script_file + | INPUT_VERSION_SCRIPT version_script_file | INPUT_DEFSYM defsym_expr ; @@ -148,7 +173,7 @@ defsym_expr: mri_script_file: { ldlex_mri_script (); - PUSH_ERROR ("MRI style script"); + PUSH_ERROR (_("MRI style script")); } mri_script_lines { @@ -167,7 +192,7 @@ mri_script_command: CHIP exp | CHIP exp ',' exp | NAME { - einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1); + einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1); } | LIST { config.map_filename = "-"; @@ -245,6 +270,8 @@ casesymlist: extern_name_list: NAME { ldlang_add_undef ($1); } + | extern_name_list NAME + { ldlang_add_undef ($2); } | extern_name_list ',' NAME { ldlang_add_undef ($3); } ; @@ -276,6 +303,7 @@ ifile_p1: | low_level_library | floating_point_support | statement_anywhere + | version | ';' | TARGET_K '(' NAME ')' { lang_add_target($3); } @@ -305,6 +333,7 @@ ifile_p1: { lang_add_nocrossref ($3); } + | EXTERN '(' extern_name_list ')' ; input_list: @@ -346,51 +375,117 @@ statement_anywhere: /* The '*' and '?' cases are there because the lexer returns them as separate tokens rather than as NAME. */ -file_NAME_list: +wildcard_name: NAME - { lang_add_wild ($1, current_file); } + { + $$ = $1; + } | '*' - { lang_add_wild ("*", current_file); } + { + $$ = "*"; + } | '?' - { lang_add_wild ("?", current_file); } - | file_NAME_list opt_comma NAME - { lang_add_wild ($3, current_file); } - | file_NAME_list opt_comma '*' - { lang_add_wild ("*", current_file); } - | file_NAME_list opt_comma '?' - { lang_add_wild ("?", current_file); } + { + $$ = "?"; + } ; -input_section_spec: - NAME - { - lang_add_wild((char *)NULL, $1); - } - | '[' +wildcard_spec: + wildcard_name { - current_file = (char *)NULL; + $$.name = $1; + $$.sorted = false; + $$.exclude_name_list = NULL; } - file_NAME_list - ']' - | NAME + | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name { - current_file = $1; + $$.name = $5; + $$.sorted = false; + $$.exclude_name_list = $3; } - '(' file_NAME_list ')' - | '?' - /* This case is needed because the lexer returns a - single question mark as '?' rather than NAME. */ + | SORT '(' wildcard_name ')' { - current_file = "?"; + $$.name = $3; + $$.sorted = true; + $$.exclude_name_list = NULL; } - '(' file_NAME_list ')' - | '*' + | SORT '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')' { - current_file = (char *)NULL; + $$.name = $7; + $$.sorted = true; + $$.exclude_name_list = $5; + } + ; + + + +exclude_name_list: + exclude_name_list ',' wildcard_name + { + struct name_list *tmp; + tmp = (struct name_list *) xmalloc (sizeof *tmp); + tmp->name = $3; + tmp->next = $1; + $$ = tmp; + } + | + wildcard_name + { + struct name_list *tmp; + tmp = (struct name_list *) xmalloc (sizeof *tmp); + tmp->name = $1; + tmp->next = NULL; + $$ = tmp; + } + ; + +file_NAME_list: + wildcard_spec + { + lang_add_wild ($1.name, $1.sorted, + current_file.name, + current_file.sorted, + ldgram_had_keep, $1.exclude_name_list); + } + | file_NAME_list opt_comma wildcard_spec + { + lang_add_wild ($3.name, $3.sorted, + current_file.name, + current_file.sorted, + ldgram_had_keep, $3.exclude_name_list); + } + ; + +input_section_spec_no_keep: + NAME + { + lang_add_wild (NULL, false, $1, false, + ldgram_had_keep, NULL); + } + | '[' + { + current_file.name = NULL; + current_file.sorted = false; + } + file_NAME_list ']' + | wildcard_spec + { + current_file = $1; + /* '*' matches any file name. */ + if (strcmp (current_file.name, "*") == 0) + current_file.name = NULL; } '(' file_NAME_list ')' ; +input_section_spec: + input_section_spec_no_keep + | KEEP '(' + { ldgram_had_keep = true; } + input_section_spec_no_keep ')' + { ldgram_had_keep = false; } + ; + statement: assignment end | CREATE_OBJECT_SYMBOLS @@ -403,6 +498,11 @@ statement: lang_add_attribute(lang_constructors_statement_enum); } + | SORT '(' CONSTRUCTORS ')' + { + constructors_sorted = true; + lang_add_attribute (lang_constructors_statement_enum); + } | input_section_spec | length '(' mustbe_exp ')' { @@ -432,6 +532,8 @@ statement_list_opt: length: QUAD { $$ = $1; } + | SQUAD + { $$ = $1; } | LONG { $$ = $1; } | SHORT @@ -523,22 +625,33 @@ memory_spec: NAME region->origin = exp_get_vma($3, 0L,"origin", lang_first_phase_enum); } - ; length_spec: + ; + +length_spec: LENGTH '=' mustbe_exp { region->length = exp_get_vma($3, ~((bfd_vma)0), "length", lang_first_phase_enum); } - + ; attributes_opt: - '(' NAME ')' - { - lang_set_flags(®ion->flags, $2); - } - | - + /* empty */ + { /* dummy action to avoid bison 1.25 error message */ } + | '(' attributes_list ')' + ; + +attributes_list: + attributes_string + | attributes_list attributes_string + ; + +attributes_string: + NAME + { lang_set_flags (region, $1, 0); } + | '!' NAME + { lang_set_flags (region, $2, 1); } ; startup: @@ -678,9 +791,20 @@ exp : { $$ = exp_unop(ALIGN_K,$3); } | NAME { $$ = 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); } ; +memspec_at_opt: + AT '>' NAME { $$ = $3; } + | { $$ = "*default*"; } + ; + opt_at: AT '(' exp ')' { $$ = $3; } | { $$ = 0; } @@ -697,12 +821,29 @@ section: NAME { ldlex_expression(); } } statement_list_opt '}' { ldlex_popstate (); ldlex_expression (); } - memspec_opt phdr_opt fill_opt + memspec_opt memspec_at_opt phdr_opt fill_opt { - ldlex_popstate(); - lang_leave_output_section_statement($13, $11); + ldlex_popstate (); + lang_leave_output_section_statement ($14, $11, $13, $12); } opt_comma + | OVERLAY + { ldlex_expression (); } + opt_exp_without_type opt_nocrossrefs opt_at + { ldlex_popstate (); ldlex_script (); } + '{' + { + lang_enter_overlay ($3, $5, (int) $4); + } + overlay_section + '}' + { ldlex_popstate (); ldlex_expression (); } + memspec_opt memspec_at_opt phdr_opt fill_opt + { + ldlex_popstate (); + lang_leave_overlay ($15, $12, $14, $13); + } + opt_comma | /* The GROUP case is just enough to support the gcc svr3.ifile script. It is not intended to be full support. I'm not even sure what GROUP is supposed @@ -727,6 +868,7 @@ type: atype: '(' type ')' | /* EMPTY */ { sectype = normal_section; } + | '(' ')' { sectype = normal_section; } ; opt_exp_with_type: @@ -741,6 +883,18 @@ opt_exp_with_type: { $$ = $3; } ; +opt_exp_without_type: + exp ':' { $$ = $1; } + | ':' { $$ = (etree_type *) NULL; } + ; + +opt_nocrossrefs: + /* empty */ + { $$ = 0; } + | NOCROSSREFS + { $$ = 1; } + ; + memspec_opt: '>' NAME { $$ = $2; } @@ -749,12 +903,40 @@ memspec_opt: phdr_opt: /* empty */ + { + $$ = NULL; + } | phdr_opt ':' NAME { - lang_section_in_phdr ($3); + struct lang_output_section_phdr_list *n; + + n = ((struct lang_output_section_phdr_list *) + xmalloc (sizeof *n)); + n->name = $3; + n->used = false; + n->next = $1; + $$ = n; } ; +overlay_section: + /* empty */ + | overlay_section + NAME + { + ldlex_script (); + lang_enter_overlay_section ($2); + } + '{' statement_list_opt '}' + { ldlex_popstate (); ldlex_expression (); } + phdr_opt fill_opt + { + ldlex_popstate (); + lang_leave_overlay_section ($9, $8); + } + opt_comma + ; + phdrs: PHDRS '{' phdr_list '}' ; @@ -819,7 +1001,7 @@ 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"), $1); } | AT '(' exp ')' phdr_qualifiers { @@ -839,13 +1021,109 @@ phdr_val: } ; +/* This syntax is used within an external version script file. */ + +version_script_file: + { + ldlex_version_file (); + PUSH_ERROR (_("VERSION script")); + } + vers_nodes + { + ldlex_popstate (); + POP_ERROR (); + } + ; + +/* This is used within a normal linker script file. */ + +version: + { + ldlex_version_script (); + } + VERSIONK '{' vers_nodes '}' + { + ldlex_popstate (); + } + ; + +vers_nodes: + vers_node + | vers_nodes vers_node + ; + +vers_node: + VERS_TAG '{' vers_tag '}' ';' + { + lang_register_vers_node ($1, $3, NULL); + } + | VERS_TAG '{' vers_tag '}' verdep ';' + { + lang_register_vers_node ($1, $3, $5); + } + ; + +verdep: + VERS_TAG + { + $$ = lang_add_vers_depend (NULL, $1); + } + | verdep VERS_TAG + { + $$ = lang_add_vers_depend ($1, $2); + } + ; + +vers_tag: + /* empty */ + { + $$ = lang_new_vers_node (NULL, NULL); + } + | vers_defns ';' + { + $$ = lang_new_vers_node ($1, NULL); + } + | GLOBAL ':' vers_defns ';' + { + $$ = lang_new_vers_node ($3, NULL); + } + | LOCAL ':' vers_defns ';' + { + $$ = lang_new_vers_node (NULL, $3); + } + | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';' + { + $$ = lang_new_vers_node ($3, $7); + } + ; + +vers_defns: + VERS_IDENTIFIER + { + $$ = lang_new_vers_regex (NULL, $1, ldgram_vers_current_lang); + } + | vers_defns ';' VERS_IDENTIFIER + { + $$ = lang_new_vers_regex ($1, $3, ldgram_vers_current_lang); + } + | EXTERN NAME '{' + { + $$ = ldgram_vers_current_lang; + ldgram_vers_current_lang = $2; + } + vers_defns '}' + { + ldgram_vers_current_lang = $4; + } + ; + %% void yyerror(arg) const char *arg; { if (ldfile_assumed_script) - einfo ("%P:%s: file format not recognized; treating as linker script\n", + einfo (_("%P:%s: file format not recognized; treating as linker script\n"), ldfile_input_filename); if (error_index > 0 && error_index < ERROR_NAME_MAX) einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);