]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/ldgram.y
2.41 Release sources
[thirdparty/binutils-gdb.git] / ld / ldgram.y
index 4910e17ab4a9fabbb5b71784f327e3b7de47c4cd..081176ba0f133658e4dec7c9e7b6a76bba0e90b3 100644 (file)
@@ -1,5 +1,5 @@
 /* A YACC grammar to parse a superset of the AT&T linker scripting language.
-   Copyright (C) 1991-2021 Free Software Foundation, Inc.
+   Copyright (C) 1991-2023 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
 
    This file is part of the GNU Binutils.
@@ -47,6 +47,7 @@
 #endif
 
 static enum section_type sectype;
+static etree_type *sectype_value;
 static lang_memory_region_type *region;
 
 static bool ldgram_had_keep = false;
@@ -124,8 +125,8 @@ static int error_index;
 %right UNARY
 %token END
 %left <token> '('
-%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
-%token SECTIONS PHDRS INSERT_K AFTER BEFORE
+%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE ASCIZ
+%token SECTIONS PHDRS INSERT_K AFTER BEFORE LINKER_VERSION
 %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
@@ -139,6 +140,7 @@ static int error_index;
 %token LD_FEATURE
 %token NOLOAD DSECT COPY INFO OVERLAY
 %token READONLY
+%token TYPE
 %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
 %token <integer> NEXT
 %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
@@ -248,9 +250,8 @@ mri_script_command:
        |       CASE casesymlist
        |       EXTERN extern_name_list
        |       INCLUDE filename
-               { ldlex_script (); ldfile_open_command_file($2); }
+               { ldfile_open_command_file ($2); }
                mri_script_lines END
-               { ldlex_popstate (); }
        |       START NAME
                { lang_add_entry ($2, false); }
        |
@@ -281,18 +282,12 @@ 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
+       NAME
                        { ldlang_add_undef ($1, false); }
-       | extern_name_list_body NAME
+       | extern_name_list NAME
                        { ldlang_add_undef ($2, false); }
-       | extern_name_list_body ',' NAME
+       | extern_name_list ',' NAME
                        { ldlang_add_undef ($3, false); }
        ;
 
@@ -346,9 +341,8 @@ ifile_p1:
        |       MAP '(' filename ')'
                { lang_add_map($3); }
        |       INCLUDE filename
-               { ldlex_script (); ldfile_open_command_file($2); }
+               { ldfile_open_command_file ($2); }
                ifile_list END
-               { ldlex_popstate (); }
        |       NOCROSSREFS '(' nocrossref_list ')'
                {
                  lang_add_nocrossref ($3);
@@ -357,7 +351,8 @@ ifile_p1:
                {
                  lang_add_nocrossref_to ($3);
                }
-       |       EXTERN '(' extern_name_list ')'
+       |       EXTERN '(' { ldlex_expression (); } extern_name_list ')'
+                       { ldlex_popstate (); }
        |       INSERT_K AFTER NAME
                { lang_add_insert ($3, 0); }
        |       INSERT_K BEFORE NAME
@@ -428,21 +423,11 @@ statement_anywhere:
                  lang_add_assignment (exp_assert ($4, $6)); }
        ;
 
-/* The '*' and '?' cases are there because the lexer returns them as
-   separate tokens rather than as NAME.  */
 wildcard_name:
                NAME
                        {
                          $$ = $1;
                        }
-       |       '*'
-                       {
-                         $$ = "*";
-                       }
-       |       '?'
-                       {
-                         $$ = "?";
-                       }
        ;
 
 wildcard_maybe_exclude:
@@ -683,11 +668,18 @@ statement:
                {
                  lang_add_data ((int) $1, $3);
                }
-
+       | ASCIZ NAME
+               {
+                 lang_add_string ($2);
+               }
        | FILL '(' fill_exp ')'
                {
                  lang_add_fill ($3);
                }
+       | LINKER_VERSION
+               {
+                 lang_add_version_string ();
+               }
        | ASSERT_K
                { ldlex_expression (); }
          '(' exp ',' NAME ')' separator
@@ -697,11 +689,9 @@ statement:
                }
        | INCLUDE filename
                {
-                 ldlex_script ();
                  ldfile_open_command_file ($2);
                }
          statement_list_opt END
-               { ldlex_popstate (); }
        ;
 
 statement_list:
@@ -730,7 +720,7 @@ length:
 fill_exp:
        mustbe_exp
                {
-                 $$ = exp_get_fill ($1, 0, "fill value");
+                 $$ = exp_get_fill ($1, 0, _("fill value"));
                }
        ;
 
@@ -814,9 +804,8 @@ memory_spec:        NAME
                origin_spec opt_comma length_spec
                {}
        |       INCLUDE filename
-               { ldlex_script (); ldfile_open_command_file($2); }
+               { ldfile_open_command_file ($2); }
                memory_spec_list_opt END
-               { ldlex_popstate (); }
        ;
 
 origin_spec:
@@ -829,6 +818,11 @@ origin_spec:
 length_spec:
             LENGTH '=' mustbe_exp
                {
+                 if (yychar == NAME)
+                   {
+                     yyclearin;
+                     ldlex_backup ();
+                   }
                  region->length_exp = $3;
                }
        ;
@@ -1073,9 +1067,8 @@ section:  NAME
                        {
                          ldlex_popstate ();
                          ldlex_wild ();
-                         lang_enter_output_section_statement($1, $3, sectype,
-                                                             $5, $7, $4,
-                                                             $8, $6);
+                         lang_enter_output_section_statement ($1, $3, sectype,
+                                       sectype_value, $5, $7, $4, $8, $6);
                        }
                '{'
                statement_list_opt
@@ -1083,6 +1076,18 @@ section: NAME
                        { ldlex_popstate (); }
                memspec_opt memspec_at_opt phdr_opt fill_opt
                        {
+                         /* fill_opt may have switched the lexer into
+                            expression state, and back again, but in
+                            order to find the end of the fill
+                            expression the parser must look ahead one
+                            token.  If it is a NAME, throw it away as
+                            it will have been lexed in the wrong
+                            state.  */
+                         if (yychar == NAME)
+                           {
+                             yyclearin;
+                             ldlex_backup ();
+                           }
                          lang_leave_output_section_statement ($17, $14,
                                                               $16, $15);
                        }
@@ -1099,6 +1104,11 @@ section: NAME
                '}'
                memspec_opt memspec_at_opt phdr_opt fill_opt
                        {
+                         if (yychar == NAME)
+                           {
+                             yyclearin;
+                             ldlex_backup ();
+                           }
                          lang_leave_overlay ($5, (int) $4,
                                              $15, $12, $14, $13);
                        }
@@ -1117,11 +1127,9 @@ section: NAME
                '{' sec_or_group_p1 '}'
        |       INCLUDE filename
                        {
-                         ldlex_script ();
                          ldfile_open_command_file ($2);
                        }
                sec_or_group_p1 END
-                       { ldlex_popstate (); }
        ;
 
 type:
@@ -1130,8 +1138,10 @@ type:
        |  COPY    { sectype = noalloc_section; }
        |  INFO    { sectype = noalloc_section; }
        |  OVERLAY { sectype = noalloc_section; }
+        |  READONLY '(' TYPE '=' exp ')' { sectype = typed_readonly_section; sectype_value = $5; }
        |  READONLY { sectype = readonly_section; }
-       ;
+       |  TYPE '=' exp { sectype = type_section; sectype_value = $3; }
+        ;
 
 atype:
                '(' type ')'
@@ -1201,6 +1211,11 @@ overlay_section:
                        { ldlex_popstate (); }
                phdr_opt fill_opt
                        {
+                         if (yychar == NAME)
+                           {
+                             yyclearin;
+                             ldlex_backup ();
+                           }
                          lang_leave_overlay_section ($9, $8);
                        }
                opt_comma
@@ -1257,6 +1272,10 @@ phdr_type:
                            $$ = exp_intop (0x6474e550);
                          else if (strcmp (s, "PT_GNU_STACK") == 0)
                            $$ = exp_intop (0x6474e551);
+                         else if (strcmp (s, "PT_GNU_RELRO") == 0)
+                           $$ = exp_intop (0x6474e552);
+                         else if (strcmp (s, "PT_GNU_PROPERTY") == 0)
+                           $$ = exp_intop (0x6474e553);
                          else
                            {
                              einfo (_("\
@@ -1493,7 +1512,7 @@ yyerror(arg)
     einfo (_("%P:%s: file format not recognized; treating as linker script\n"),
           ldlex_filename ());
   if (error_index > 0 && error_index < ERROR_NAME_MAX)
-    einfo ("%F%P:%pS: %s in %s\n", NULL, arg, error_names[error_index - 1]);
+    einfo (_("%F%P:%pS: %s in %s\n"), NULL, arg, error_names[error_index - 1]);
   else
     einfo ("%F%P:%pS: %s\n", NULL, arg);
 }