ldgram.y revision 1.2
1/* A YACC grammer to parse a superset of the AT&T linker scripting languaue.
2   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3   Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
4
5This file is part of GNU ld.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21%{
22/*
23
24 */
25
26#define DONTDECLARE_MALLOC
27
28#include "bfd.h"
29#include "sysdep.h"
30#include "bfdlink.h"
31#include "ld.h"
32#include "ldexp.h"
33#include "ldver.h"
34#include "ldlang.h"
35#include "ldemul.h"
36#include "ldfile.h"
37#include "ldmisc.h"
38#include "ldmain.h"
39#include "mri.h"
40#include "ldlex.h"
41
42#ifndef YYDEBUG
43#define YYDEBUG 1
44#endif
45
46static int typebits;
47
48lang_memory_region_type *region;
49
50
51char *current_file;
52boolean ldgram_want_filename = true;
53boolean had_script = false;
54boolean force_make_executable = false;
55
56boolean ldgram_in_script = false;
57boolean ldgram_had_equals = false;
58
59
60#define ERROR_NAME_MAX 20
61static char *error_names[ERROR_NAME_MAX];
62static int error_index;
63#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
64#define POP_ERROR()   error_index--;
65%}
66%union {
67  bfd_vma integer;
68  char *name;
69  int token;
70  union etree_union *etree;
71  struct phdr_info
72    {
73      boolean filehdr;
74      boolean phdrs;
75      union etree_union *at;
76      union etree_union *flags;
77    } phdr;
78}
79
80%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
81%type <integer> fill_opt
82%type <name> memspec_opt casesymlist
83%token <integer> INT
84%token <name> NAME LNAME
85%type  <integer> length
86%type <phdr> phdr_qualifiers
87
88%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ  '=' LSHIFTEQ RSHIFTEQ   ANDEQ OREQ
89%right <token> '?' ':'
90%left <token> OROR
91%left <token>  ANDAND
92%left <token> '|'
93%left <token>  '^'
94%left  <token> '&'
95%left <token>  EQ NE
96%left  <token> '<' '>' LE GE
97%left  <token> LSHIFT RSHIFT
98
99%left  <token> '+' '-'
100%left  <token> '*' '/' '%'
101
102%right UNARY
103%token END
104%left <token> '('
105%token <token> ALIGN_K BLOCK QUAD LONG SHORT BYTE
106%token SECTIONS PHDRS
107%token '{' '}'
108%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
109%token SIZEOF_HEADERS
110%token INCLUDE
111%token MEMORY DEFSYMEND
112%token NOLOAD DSECT COPY INFO OVERLAY
113%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY
114%token <integer> SIZEOF NEXT ADDR
115%token STARTUP HLL SYSLIB FLOAT NOFLOAT
116%token ORIGIN FILL
117%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
118%token ALIGNMOD AT PROVIDE
119%type <token> assign_op atype
120%type <name>  filename
121%token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD
122%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
123%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
124
125%%
126
127file:
128		INPUT_SCRIPT script_file
129	|	INPUT_MRI_SCRIPT mri_script_file
130	|	INPUT_DEFSYM defsym_expr
131	;
132
133
134filename:  NAME;
135
136
137defsym_expr:
138		{ ldlex_defsym(); }
139		NAME '=' exp
140		{
141		  ldlex_popstate();
142		  lang_add_assignment(exp_assop($3,$2,$4));
143		}
144
145/* SYNTAX WITHIN AN MRI SCRIPT FILE */
146mri_script_file:
147		{
148		  ldlex_mri_script ();
149		  PUSH_ERROR ("MRI style script");
150		}
151	     mri_script_lines
152		{
153		  ldlex_popstate ();
154		  mri_draw_tree ();
155		  POP_ERROR ();
156		}
157	;
158
159mri_script_lines:
160		mri_script_lines mri_script_command NEWLINE
161          |
162	;
163
164mri_script_command:
165		CHIP  exp
166	|	CHIP  exp ',' exp
167	|	NAME 	{
168			einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1);
169			}
170	|	LIST  	{
171			config.map_filename = "-";
172			}
173        |       ORDER ordernamelist
174	|       ENDWORD
175        |       PUBLIC NAME '=' exp
176 			{ mri_public($2, $4); }
177        |       PUBLIC NAME ',' exp
178 			{ mri_public($2, $4); }
179        |       PUBLIC NAME  exp
180 			{ mri_public($2, $3); }
181	| 	FORMAT NAME
182			{ mri_format($2); }
183	|	SECT NAME ',' exp
184			{ mri_output_section($2, $4);}
185	|	SECT NAME  exp
186			{ mri_output_section($2, $3);}
187	|	SECT NAME '=' exp
188			{ mri_output_section($2, $4);}
189	|	ALIGN_K NAME '=' exp
190			{ mri_align($2,$4); }
191	|	ALIGN_K NAME ',' exp
192			{ mri_align($2,$4); }
193	|	ALIGNMOD NAME '=' exp
194			{ mri_alignmod($2,$4); }
195	|	ALIGNMOD NAME ',' exp
196			{ mri_alignmod($2,$4); }
197	|	ABSOLUTE mri_abs_name_list
198	|	LOAD	 mri_load_name_list
199	|       NAMEWORD NAME
200			{ mri_name($2); }
201	|	ALIAS NAME ',' NAME
202			{ mri_alias($2,$4,0);}
203	|	ALIAS NAME ',' INT
204			{ mri_alias($2,0,(int) $4);}
205	|	BASE     exp
206			{ mri_base($2); }
207        |       TRUNCATE INT
208		{  mri_truncate((unsigned int) $2); }
209	|	CASE casesymlist
210	|	EXTERN extern_name_list
211	|	INCLUDE filename
212		{ ldfile_open_command_file ($2); } mri_script_lines END
213	|	START NAME
214		{ lang_add_entry ($2, false); }
215        |
216	;
217
218ordernamelist:
219	      ordernamelist ',' NAME         { mri_order($3); }
220	|     ordernamelist  NAME         { mri_order($2); }
221      	|
222	;
223
224mri_load_name_list:
225		NAME
226			{ mri_load($1); }
227	|	mri_load_name_list ',' NAME { mri_load($3); }
228	;
229
230mri_abs_name_list:
231 		NAME
232 			{ mri_only_load($1); }
233	|	mri_abs_name_list ','  NAME
234 			{ mri_only_load($3); }
235	;
236
237casesymlist:
238	  /* empty */ { $$ = NULL; }
239	| NAME
240	| casesymlist ',' NAME
241	;
242
243extern_name_list:
244	  NAME
245			{ ldlang_add_undef ($1); }
246	| extern_name_list ',' NAME
247			{ ldlang_add_undef ($3); }
248	;
249
250script_file:
251	{
252	 ldlex_both();
253	}
254       ifile_list
255	{
256	ldlex_popstate();
257	}
258        ;
259
260
261ifile_list:
262       ifile_list ifile_p1
263        |
264	;
265
266
267
268ifile_p1:
269		memory
270	|	sections
271	|	phdrs
272	|	startup
273	|	high_level_library
274	|	low_level_library
275	|	floating_point_support
276	|	statement_anywhere
277        |	 ';'
278	|	TARGET_K '(' NAME ')'
279		{ lang_add_target($3); }
280	|	SEARCH_DIR '(' filename ')'
281		{ ldfile_add_library_path ($3, false); }
282	|	OUTPUT '(' filename ')'
283		{ lang_add_output($3, 1); }
284        |	OUTPUT_FORMAT '(' NAME ')'
285		  { lang_add_output_format ($3, (char *) NULL,
286					    (char *) NULL, 1); }
287	|	OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
288		  { lang_add_output_format ($3, $5, $7, 1); }
289        |	OUTPUT_ARCH '(' NAME ')'
290		  { ldfile_set_output_arch($3); }
291	|	FORCE_COMMON_ALLOCATION
292		{ command_line.force_common_definition = true ; }
293	|	INPUT '(' input_list ')'
294	|	GROUP
295		  { lang_enter_group (); }
296		    '(' input_list ')'
297		  { lang_leave_group (); }
298     	|	MAP '(' filename ')'
299		{ lang_add_map($3); }
300	|	INCLUDE filename
301		{ ldfile_open_command_file($2); } ifile_list END
302	;
303
304input_list:
305		NAME
306		{ lang_add_input_file($1,lang_input_file_is_search_file_enum,
307				 (char *)NULL); }
308	|	input_list ',' NAME
309		{ lang_add_input_file($3,lang_input_file_is_search_file_enum,
310				 (char *)NULL); }
311	|	input_list NAME
312		{ lang_add_input_file($2,lang_input_file_is_search_file_enum,
313				 (char *)NULL); }
314	|	LNAME
315		{ lang_add_input_file($1,lang_input_file_is_l_enum,
316				 (char *)NULL); }
317	|	input_list ',' LNAME
318		{ lang_add_input_file($3,lang_input_file_is_l_enum,
319				 (char *)NULL); }
320	|	input_list LNAME
321		{ lang_add_input_file($2,lang_input_file_is_l_enum,
322				 (char *)NULL); }
323	;
324
325sections:
326		SECTIONS '{' sec_or_group_p1 '}'
327	;
328
329sec_or_group_p1:
330		sec_or_group_p1 section
331	|	sec_or_group_p1 statement_anywhere
332	|
333	;
334
335statement_anywhere:
336		ENTRY '(' NAME ')'
337		{ lang_add_entry ($3, false); }
338	|	assignment end
339	;
340
341file_NAME_list:
342		NAME
343			{ lang_add_wild($1, current_file); }
344	|	file_NAME_list opt_comma NAME
345			{ lang_add_wild($3, current_file); }
346	;
347
348input_section_spec:
349		NAME
350		{
351		lang_add_wild((char *)NULL, $1);
352		}
353        |	'['
354			{
355			current_file = (char *)NULL;
356			}
357			file_NAME_list
358		']'
359	|	NAME
360			{
361			current_file =$1;
362			}
363		'(' file_NAME_list ')'
364	|	'*'
365			{
366			current_file = (char *)NULL;
367			}
368		'(' file_NAME_list ')'
369	;
370
371statement:
372	  	assignment end
373	|	CREATE_OBJECT_SYMBOLS
374		{
375 		lang_add_attribute(lang_object_symbols_statement_enum);
376	      	}
377        |	';'
378        |	CONSTRUCTORS
379		{
380
381		  lang_add_attribute(lang_constructors_statement_enum);
382		}
383	| input_section_spec
384        | length '(' exp ')'
385        	        {
386			lang_add_data((int) $1,$3);
387			}
388
389	| FILL '(' exp ')'
390			{
391			  lang_add_fill
392			    (exp_get_value_int($3,
393					       0,
394					       "fill value",
395					       lang_first_phase_enum));
396			}
397	;
398
399statement_list:
400		statement_list statement
401  	|  	statement
402	;
403
404statement_list_opt:
405		/* empty */
406	|	statement_list
407	;
408
409length:
410		QUAD
411			{ $$ = $1; }
412	|	LONG
413			{ $$ = $1; }
414	| 	SHORT
415			{ $$ = $1; }
416	|	BYTE
417			{ $$ = $1; }
418	;
419
420fill_opt:
421          '=' mustbe_exp
422		{
423		  $$ =	 exp_get_value_int($2,
424					   0,
425					   "fill value",
426					   lang_first_phase_enum);
427		}
428	| 	{ $$ = 0; }
429	;
430
431
432
433assign_op:
434		PLUSEQ
435			{ $$ = '+'; }
436	|	MINUSEQ
437			{ $$ = '-'; }
438	| 	MULTEQ
439			{ $$ = '*'; }
440	| 	DIVEQ
441			{ $$ = '/'; }
442	| 	LSHIFTEQ
443			{ $$ = LSHIFT; }
444	| 	RSHIFTEQ
445			{ $$ = RSHIFT; }
446	| 	ANDEQ
447			{ $$ = '&'; }
448	| 	OREQ
449			{ $$ = '|'; }
450
451	;
452
453end:	';' | ','
454	;
455
456
457assignment:
458		NAME '=' mustbe_exp
459		{
460		  lang_add_assignment (exp_assop ($2, $1, $3));
461		}
462	|	NAME assign_op mustbe_exp
463		{
464		  lang_add_assignment (exp_assop ('=', $1,
465						  exp_binop ($2,
466							     exp_nameop (NAME,
467									 $1),
468							     $3)));
469		}
470	|	PROVIDE '(' NAME '=' mustbe_exp ')'
471		{
472		  lang_add_assignment (exp_provide ($3, $5));
473		}
474	;
475
476
477opt_comma:
478		','	|	;
479
480
481memory:
482		MEMORY '{' memory_spec memory_spec_list '}'
483	;
484
485memory_spec_list:
486		memory_spec_list memory_spec
487	|	memory_spec_list ',' memory_spec
488	|
489	;
490
491
492memory_spec: 		NAME
493			{ region = lang_memory_region_lookup($1); }
494		attributes_opt ':'
495		origin_spec opt_comma length_spec
496
497	; origin_spec:
498	ORIGIN '=' mustbe_exp
499		{ region->current =
500		 region->origin =
501		 exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
502}
503	; length_spec:
504             LENGTH '=' mustbe_exp
505               { region->length = exp_get_vma($3,
506					       ~((bfd_vma)0),
507					       "length",
508					       lang_first_phase_enum);
509		}
510
511
512attributes_opt:
513		  '(' NAME ')'
514			{
515			lang_set_flags(&region->flags, $2);
516			}
517	|
518
519	;
520
521startup:
522	STARTUP '(' filename ')'
523		{ lang_startup($3); }
524	;
525
526high_level_library:
527		HLL '(' high_level_library_NAME_list ')'
528	|	HLL '(' ')'
529			{ ldemul_hll((char *)NULL); }
530	;
531
532high_level_library_NAME_list:
533		high_level_library_NAME_list opt_comma filename
534			{ ldemul_hll($3); }
535	|	filename
536			{ ldemul_hll($1); }
537
538	;
539
540low_level_library:
541	SYSLIB '(' low_level_library_NAME_list ')'
542	; low_level_library_NAME_list:
543		low_level_library_NAME_list opt_comma filename
544			{ ldemul_syslib($3); }
545	|
546	;
547
548floating_point_support:
549		FLOAT
550			{ lang_float(true); }
551	|	NOFLOAT
552			{ lang_float(false); }
553	;
554
555
556mustbe_exp:		 { ldlex_expression(); }
557		exp
558			 { ldlex_popstate(); $$=$2;}
559	;
560
561exp	:
562		'-' exp %prec UNARY
563			{ $$ = exp_unop('-', $2); }
564	|	'(' exp ')'
565			{ $$ = $2; }
566	|	NEXT '(' exp ')' %prec UNARY
567			{ $$ = exp_unop((int) $1,$3); }
568	|	'!' exp %prec UNARY
569			{ $$ = exp_unop('!', $2); }
570	|	'+' exp %prec UNARY
571			{ $$ = $2; }
572	|	'~' exp %prec UNARY
573			{ $$ = exp_unop('~', $2);}
574
575	|	exp '*' exp
576			{ $$ = exp_binop('*', $1, $3); }
577	|	exp '/' exp
578			{ $$ = exp_binop('/', $1, $3); }
579	|	exp '%' exp
580			{ $$ = exp_binop('%', $1, $3); }
581	|	exp '+' exp
582			{ $$ = exp_binop('+', $1, $3); }
583	|	exp '-' exp
584			{ $$ = exp_binop('-' , $1, $3); }
585	|	exp LSHIFT exp
586			{ $$ = exp_binop(LSHIFT , $1, $3); }
587	|	exp RSHIFT exp
588			{ $$ = exp_binop(RSHIFT , $1, $3); }
589	|	exp EQ exp
590			{ $$ = exp_binop(EQ , $1, $3); }
591	|	exp NE exp
592			{ $$ = exp_binop(NE , $1, $3); }
593	|	exp LE exp
594			{ $$ = exp_binop(LE , $1, $3); }
595  	|	exp GE exp
596			{ $$ = exp_binop(GE , $1, $3); }
597	|	exp '<' exp
598			{ $$ = exp_binop('<' , $1, $3); }
599	|	exp '>' exp
600			{ $$ = exp_binop('>' , $1, $3); }
601	|	exp '&' exp
602			{ $$ = exp_binop('&' , $1, $3); }
603	|	exp '^' exp
604			{ $$ = exp_binop('^' , $1, $3); }
605	|	exp '|' exp
606			{ $$ = exp_binop('|' , $1, $3); }
607	|	exp '?' exp ':' exp
608			{ $$ = exp_trinop('?' , $1, $3, $5); }
609	|	exp ANDAND exp
610			{ $$ = exp_binop(ANDAND , $1, $3); }
611	|	exp OROR exp
612			{ $$ = exp_binop(OROR , $1, $3); }
613	|	DEFINED '(' NAME ')'
614			{ $$ = exp_nameop(DEFINED, $3); }
615	|	INT
616			{ $$ = exp_intop($1); }
617        |	SIZEOF_HEADERS
618			{ $$ = exp_nameop(SIZEOF_HEADERS,0); }
619
620	|	SIZEOF '(' NAME ')'
621			{ $$ = exp_nameop(SIZEOF,$3); }
622	|	ADDR '(' NAME ')'
623			{ $$ = exp_nameop(ADDR,$3); }
624	|	ABSOLUTE '(' exp ')'
625			{ $$ = exp_unop(ABSOLUTE, $3); }
626	|	ALIGN_K '(' exp ')'
627			{ $$ = exp_unop(ALIGN_K,$3); }
628	|	BLOCK '(' exp ')'
629			{ $$ = exp_unop(ALIGN_K,$3); }
630	|	NAME
631			{ $$ = exp_nameop(NAME,$1); }
632	;
633
634
635opt_at:
636		AT '(' exp ')' { $$ = $3; }
637	|	{ $$ = 0; }
638	;
639
640section:	NAME 		{ ldlex_expression(); }
641		opt_exp_with_type
642		opt_at   	{ ldlex_popstate(); }
643		'{'
644			{
645			lang_enter_output_section_statement($1,$3,typebits,0,0,0,$4);
646			}
647		statement_list_opt
648 		'}' {ldlex_expression();} memspec_opt phdr_opt fill_opt
649		{
650		  ldlex_popstate();
651		  lang_leave_output_section_statement($13, $11);
652		}
653		opt_comma
654	;
655
656type:
657	   NOLOAD  { typebits = SEC_NEVER_LOAD; }
658	|  DSECT   { typebits = 0; }
659	|  COPY    { typebits = 0; }
660	|  INFO    { typebits = 0; }
661	|  OVERLAY { typebits = 0; }
662	;
663
664atype:
665	 	'(' type ')'
666  	| 	/* EMPTY */ { typebits = 0; }
667	;
668
669
670opt_exp_with_type:
671		exp atype ':'		{ $$ = $1; ;}
672	|	atype ':'		{ $$= (etree_type *)NULL;  }
673	;
674
675memspec_opt:
676		'>' NAME
677		{ $$ = $2; }
678	|	{ $$ = "*default*"; }
679	;
680
681phdr_opt:
682		/* empty */
683	|	phdr_opt ':' NAME
684		{
685		  lang_section_in_phdr ($3);
686		}
687	;
688
689phdrs:
690		PHDRS '{' phdr_list '}'
691	;
692
693phdr_list:
694		/* empty */
695	|	phdr_list phdr
696	;
697
698phdr:
699		NAME { ldlex_expression (); }
700		  phdr_type phdr_qualifiers { ldlex_popstate (); }
701		  ';'
702		{
703		  lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
704				 $4.flags);
705		}
706	;
707
708phdr_type:
709		exp
710		{
711		  $$ = $1;
712
713		  if ($1->type.node_class == etree_name
714		      && $1->type.node_code == NAME)
715		    {
716		      const char *s;
717		      unsigned int i;
718		      static const char * const phdr_types[] =
719			{
720			  "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
721			  "PT_INTERP", "PT_NOTE", "PT_SHLIB",
722			  "PT_PHDR"
723			};
724
725		      s = $1->name.name;
726		      for (i = 0;
727			   i < sizeof phdr_types / sizeof phdr_types[0];
728			   i++)
729			if (strcmp (s, phdr_types[i]) == 0)
730			  {
731			    $$ = exp_intop (i);
732			    break;
733			  }
734		    }
735		}
736	;
737
738phdr_qualifiers:
739		/* empty */
740		{
741		  memset (&$$, 0, sizeof (struct phdr_info));
742		}
743	|	NAME phdr_val phdr_qualifiers
744		{
745		  $$ = $3;
746		  if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
747		    $$.filehdr = true;
748		  else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
749		    $$.phdrs = true;
750		  else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
751		    $$.flags = $2;
752		  else
753		    einfo ("%X%P:%S: PHDRS syntax error at `%s'\n", $1);
754		}
755	|	AT '(' exp ')' phdr_qualifiers
756		{
757		  $$ = $5;
758		  $$.at = $3;
759		}
760	;
761
762phdr_val:
763		/* empty */
764		{
765		  $$ = NULL;
766		}
767	| '(' exp ')'
768		{
769		  $$ = $2;
770		}
771	;
772
773%%
774void
775yyerror(arg)
776     const char *arg;
777{
778  if (ldfile_assumed_script)
779    einfo ("%P:%s: file format not recognized; treating as linker script\n",
780	   ldfile_input_filename);
781  if (error_index > 0 && error_index < ERROR_NAME_MAX)
782     einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
783  else
784     einfo ("%P%F:%S: %s\n", arg);
785}
786