/* 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, 2005, 2006 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 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,
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. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
%{
/*
#define DONTDECLARE_MALLOC
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "ld.h"
#include "ldexp.h"
static enum section_type sectype;
static lang_memory_region_type *region;
-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;
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
%type <fill> fill_opt fill_exp
%type <name_list> exclude_name_list
%type <wildcard_list> file_NAME_list
+%type <flag_info_list> sect_flag_list
+%type <flag_info> sect_flags
%type <name> memspec_opt casesymlist
%type <name> memspec_at_opt
%type <cname> wildcard_name
%token END
%left <token> '('
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
-%token SECTIONS PHDRS DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END 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
+%token SORT_BY_INIT_PRIORITY
%token '{' '}'
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
%token INHIBIT_COMMON_ALLOCATION
%token SEGMENT_START
%token INCLUDE
%token MEMORY
+%token REGION_ALIAS
+%token LD_FEATURE
%token NOLOAD DSECT COPY INFO OVERLAY
%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
%token <integer> NEXT
-%token SIZEOF ADDR LOADADDR MAX_K MIN_K
+%token SIZEOF ALIGNOF 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 INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token <name> VERS_TAG VERS_IDENTIFIER
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
-%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS
%token EXCLUDE_FILE
%token CONSTANT
%type <versyms> vers_defns
NAME '=' exp
{
ldlex_popstate();
- lang_add_assignment(exp_assop($3,$2,$4));
+ lang_add_assignment (exp_defsym ($2, $4));
}
;
| 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
lang_add_nocrossref ($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:
{ lang_add_input_file($2,lang_input_file_is_l_enum,
(char *)NULL); }
| AS_NEEDED '('
- { $<integer>$ = as_needed; as_needed = TRUE; }
+ { $<integer>$ = add_DT_NEEDED_for_regular; add_DT_NEEDED_for_regular = TRUE; }
input_list ')'
- { as_needed = $<integer>3; }
+ { add_DT_NEEDED_for_regular = $<integer>3; }
| input_list ',' AS_NEEDED '('
- { $<integer>$ = as_needed; as_needed = TRUE; }
+ { $<integer>$ = add_DT_NEEDED_for_regular; add_DT_NEEDED_for_regular = TRUE; }
input_list ')'
- { as_needed = $<integer>5; }
+ { add_DT_NEEDED_for_regular = $<integer>5; }
| input_list AS_NEEDED '('
- { $<integer>$ = as_needed; as_needed = TRUE; }
+ { $<integer>$ = add_DT_NEEDED_for_regular; add_DT_NEEDED_for_regular = TRUE; }
input_list ')'
- { as_needed = $<integer>4; }
+ { add_DT_NEEDED_for_regular = $<integer>4; }
;
sections:
$$.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_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;
}
;
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 (NULL, $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:
{
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:
assignment:
NAME '=' mustbe_exp
{
- lang_add_assignment (exp_assop ($2, $1, $3));
+ lang_add_assignment (exp_assign ($1, $3));
}
| 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)));
}
| PROVIDE '(' NAME '=' mustbe_exp ')'
{
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
;
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:
| SIZEOF_HEADERS
{ $$ = exp_nameop (SIZEOF_HEADERS,0); }
+ | ALIGNOF '(' NAME ')'
+ { $$ = exp_nameop (ALIGNOF,$3); }
| SIZEOF '(' NAME ')'
{ $$ = exp_nameop (SIZEOF,$3); }
| ADDR '(' NAME ')'
opt_exp_with_type
{
ldlex_popstate ();
- lang_add_assignment (exp_assop ('=', ".", $3));
+ lang_add_assignment (exp_assign (".", $3));
}
'{' sec_or_group_p1 '}'
+ | INCLUDE filename
+ { ldlex_script (); ldfile_open_command_file($2); }
+ sec_or_group_p1 END
+ { ldlex_popstate (); }
;
type: