Support assignments and expressions in linker scripts.
[deliverable/binutils-gdb.git] / gold / yyscript.y
1 /* yyscript.y -- linker script grammer for gold. */
2
3 /* Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor <iant@google.com>.
5
6 This file is part of gold.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 /* This is a bison grammar to parse a subset of the original GNU ld
24 linker script language. */
25
26 %{
27
28 #include "config.h"
29
30 #include <stddef.h>
31 #include <stdint.h>
32
33 #include "script-c.h"
34
35 %}
36
37 /* We need to use a pure parser because we might be multi-threaded.
38 We pass some arguments through the parser to the lexer. */
39
40 %pure-parser
41
42 %parse-param {void* closure}
43 %lex-param {void* closure}
44
45 /* Since we require bison anyhow, we take advantage of it. */
46
47 %error-verbose
48
49 /* The values associated with tokens. */
50
51 %union {
52 /* A string. */
53 struct Parser_string string;
54 /* A number. */
55 uint64_t integer;
56 /* An expression. */
57 Expression_ptr expr;
58 }
59
60 /* Operators, including a precedence table for expressions. */
61
62 %right PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
63 %right '?' ':'
64 %left OROR
65 %left ANDAND
66 %left '|'
67 %left '^'
68 %left '&'
69 %left EQ NE
70 %left '<' '>' LE GE
71 %left LSHIFT RSHIFT
72 %left '+' '-'
73 %left '*' '/' '%'
74
75 /* A fake operator used to indicate unary operator precedence. */
76 %right UNARY
77
78 /* Constants. */
79
80 %token <string> STRING
81 %token <integer> INTEGER
82
83 /* Keywords. This list is taken from ldgram.y and ldlex.l in the old
84 GNU linker, with the keywords which only appear in MRI mode
85 removed. Not all these keywords are actually used in this grammar.
86 In most cases the keyword is recognized as the token name in upper
87 case. The comments indicate where this is not the case. */
88
89 %token ABSOLUTE
90 %token ADDR
91 %token ALIGN_K /* ALIGN */
92 %token ALIGNOF
93 %token ASSERT_K /* ASSERT */
94 %token AS_NEEDED
95 %token AT
96 %token BIND
97 %token BLOCK
98 %token BYTE
99 %token CONSTANT
100 %token CONSTRUCTORS
101 %token COPY
102 %token CREATE_OBJECT_SYMBOLS
103 %token DATA_SEGMENT_ALIGN
104 %token DATA_SEGMENT_END
105 %token DATA_SEGMENT_RELRO_END
106 %token DEFINED
107 %token DSECT
108 %token ENTRY
109 %token EXCLUDE_FILE
110 %token EXTERN
111 %token FILL
112 %token FLOAT
113 %token FORCE_COMMON_ALLOCATION
114 %token GLOBAL /* global */
115 %token GROUP
116 %token HLL
117 %token INCLUDE
118 %token INFO
119 %token INHIBIT_COMMON_ALLOCATION
120 %token INPUT
121 %token KEEP
122 %token LENGTH /* LENGTH, l, len */
123 %token LOADADDR
124 %token LOCAL /* local */
125 %token LONG
126 %token MAP
127 %token MAX_K /* MAX */
128 %token MEMORY
129 %token MIN_K /* MIN */
130 %token NEXT
131 %token NOCROSSREFS
132 %token NOFLOAT
133 %token NOLOAD
134 %token ONLY_IF_RO
135 %token ONLY_IF_RW
136 %token ORIGIN /* ORIGIN, o, org */
137 %token OUTPUT
138 %token OUTPUT_ARCH
139 %token OUTPUT_FORMAT
140 %token OVERLAY
141 %token PHDRS
142 %token PROVIDE
143 %token PROVIDE_HIDDEN
144 %token QUAD
145 %token SEARCH_DIR
146 %token SECTIONS
147 %token SEGMENT_START
148 %token SHORT
149 %token SIZEOF
150 %token SIZEOF_HEADERS /* SIZEOF_HEADERS, sizeof_headers */
151 %token SORT_BY_ALIGNMENT
152 %token SORT_BY_NAME
153 %token SPECIAL
154 %token SQUAD
155 %token STARTUP
156 %token SUBALIGN
157 %token SYSLIB
158 %token TARGET_K /* TARGET */
159 %token TRUNCATE
160 %token VERSIONK /* VERSION */
161
162 /* Keywords, part 2. These are keywords that are unique to gold,
163 and not present in the old GNU linker. As before, unless the
164 comments say otherwise, the keyword is recognized as the token
165 name in upper case. */
166
167 %token OPTION
168
169 /* Special tokens used to tell the grammar what type of tokens we are
170 parsing. The token stream always begins with one of these tokens.
171 We do this because version scripts can appear embedded within
172 linker scripts, and because --defsym uses the expression
173 parser. */
174 %token PARSING_LINKER_SCRIPT
175 %token PARSING_VERSION_SCRIPT
176 %token PARSING_DEFSYM
177
178 /* Non-terminal types, where needed. */
179
180 %type <expr> parse_exp exp
181
182 %%
183
184 /* Read the special token to see what to read next. */
185 top:
186 PARSING_LINKER_SCRIPT linker_script
187 | PARSING_VERSION_SCRIPT version_script
188 | PARSING_DEFSYM defsym_expr
189 ;
190
191 /* A file contains a list of commands. */
192 linker_script:
193 linker_script file_cmd
194 | /* empty */
195 ;
196
197 /* A command which may appear at top level of a linker script. */
198 file_cmd:
199 GROUP
200 { script_start_group(closure); }
201 '(' input_list ')'
202 { script_end_group(closure); }
203 | OPTION '(' STRING ')'
204 { script_parse_option(closure, $3.value, $3.length); }
205 | file_or_sections_cmd
206 | ignore_cmd
207 ;
208
209 /* Top level commands which we ignore. The GNU linker uses these to
210 select the output format, but we don't offer a choice. Ignoring
211 these is more-or-less OK since most scripts simply explicitly
212 choose the default. */
213 ignore_cmd:
214 OUTPUT_FORMAT '(' STRING ')'
215 | OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')'
216 | OUTPUT_ARCH '(' STRING ')'
217 ;
218
219 /* A list of input file names. */
220 input_list:
221 input_list_element
222 | input_list opt_comma input_list_element
223 ;
224
225 /* An input file name. */
226 input_list_element:
227 STRING
228 { script_add_file(closure, $1.value, $1.length); }
229 | AS_NEEDED
230 { script_start_as_needed(closure); }
231 '(' input_list ')'
232 { script_end_as_needed(closure); }
233 ;
234
235 /* A command which may appear at the top level of a linker script, or
236 within a SECTIONS block. */
237 file_or_sections_cmd:
238 ENTRY '(' STRING ')'
239 { script_set_entry(closure, $3.value, $3.length); }
240 | assignment end
241 ;
242
243 /* Set a symbol to a value. */
244 assignment:
245 STRING '=' parse_exp
246 { script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
247 | STRING PLUSEQ parse_exp
248 {
249 Expression_ptr s = script_exp_string($1.value, $1.length);
250 Expression_ptr e = script_exp_binary_add(s, $3);
251 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
252 }
253 | STRING MINUSEQ parse_exp
254 {
255 Expression_ptr s = script_exp_string($1.value, $1.length);
256 Expression_ptr e = script_exp_binary_sub(s, $3);
257 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
258 }
259 | STRING MULTEQ parse_exp
260 {
261 Expression_ptr s = script_exp_string($1.value, $1.length);
262 Expression_ptr e = script_exp_binary_mult(s, $3);
263 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
264 }
265 | STRING DIVEQ parse_exp
266 {
267 Expression_ptr s = script_exp_string($1.value, $1.length);
268 Expression_ptr e = script_exp_binary_div(s, $3);
269 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
270 }
271 | STRING LSHIFTEQ parse_exp
272 {
273 Expression_ptr s = script_exp_string($1.value, $1.length);
274 Expression_ptr e = script_exp_binary_lshift(s, $3);
275 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
276 }
277 | STRING RSHIFTEQ parse_exp
278 {
279 Expression_ptr s = script_exp_string($1.value, $1.length);
280 Expression_ptr e = script_exp_binary_rshift(s, $3);
281 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
282 }
283 | STRING ANDEQ parse_exp
284 {
285 Expression_ptr s = script_exp_string($1.value, $1.length);
286 Expression_ptr e = script_exp_binary_bitwise_and(s, $3);
287 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
288 }
289 | STRING OREQ parse_exp
290 {
291 Expression_ptr s = script_exp_string($1.value, $1.length);
292 Expression_ptr e = script_exp_binary_bitwise_or(s, $3);
293 script_set_symbol(closure, $1.value, $1.length, e, 0, 0);
294 }
295 | PROVIDE '(' STRING '=' parse_exp ')'
296 { script_set_symbol(closure, $3.value, $3.length, $5, 1, 0); }
297 | PROVIDE_HIDDEN '(' STRING '=' parse_exp ')'
298 { script_set_symbol(closure, $3.value, $3.length, $5, 1, 1); }
299 ;
300
301 /* Parse an expression, putting the lexer into the right mode. */
302 parse_exp:
303 { script_push_lex_into_expression_mode(closure); }
304 exp
305 {
306 script_pop_lex_mode(closure);
307 $$ = $2;
308 }
309 ;
310
311 /* An expression. */
312 exp:
313 '(' exp ')'
314 { $$ = $2; }
315 | '-' exp %prec UNARY
316 { $$ = script_exp_unary_minus($2); }
317 | '!' exp %prec UNARY
318 { $$ = script_exp_unary_logical_not($2); }
319 | '~' exp %prec UNARY
320 { $$ = script_exp_unary_bitwise_not($2); }
321 | '+' exp %prec UNARY
322 { $$ = $2; }
323 | exp '*' exp
324 { $$ = script_exp_binary_mult($1, $3); }
325 | exp '/' exp
326 { $$ = script_exp_binary_div($1, $3); }
327 | exp '%' exp
328 { $$ = script_exp_binary_mod($1, $3); }
329 | exp '+' exp
330 { $$ = script_exp_binary_add($1, $3); }
331 | exp '-' exp
332 { $$ = script_exp_binary_sub($1, $3); }
333 | exp LSHIFT exp
334 { $$ = script_exp_binary_lshift($1, $3); }
335 | exp RSHIFT exp
336 { $$ = script_exp_binary_rshift($1, $3); }
337 | exp EQ exp
338 { $$ = script_exp_binary_eq($1, $3); }
339 | exp NE exp
340 { $$ = script_exp_binary_ne($1, $3); }
341 | exp LE exp
342 { $$ = script_exp_binary_le($1, $3); }
343 | exp GE exp
344 { $$ = script_exp_binary_ge($1, $3); }
345 | exp '<' exp
346 { $$ = script_exp_binary_lt($1, $3); }
347 | exp '>' exp
348 { $$ = script_exp_binary_gt($1, $3); }
349 | exp '&' exp
350 { $$ = script_exp_binary_bitwise_and($1, $3); }
351 | exp '^' exp
352 { $$ = script_exp_binary_bitwise_xor($1, $3); }
353 | exp '|' exp
354 { $$ = script_exp_binary_bitwise_or($1, $3); }
355 | exp ANDAND exp
356 { $$ = script_exp_binary_logical_and($1, $3); }
357 | exp OROR exp
358 { $$ = script_exp_binary_logical_or($1, $3); }
359 | exp '?' exp ':' exp
360 { $$ = script_exp_trinary_cond($1, $3, $5); }
361 | INTEGER
362 { $$ = script_exp_integer($1); }
363 | STRING
364 { $$ = script_exp_string($1.value, $1.length); }
365 | MAX_K '(' exp ',' exp ')'
366 { $$ = script_exp_function_max($3, $5); }
367 | MIN_K '(' exp ',' exp ')'
368 { $$ = script_exp_function_min($3, $5); }
369 | DEFINED '(' STRING ')'
370 { $$ = script_exp_function_defined($3.value, $3.length); }
371 | SIZEOF_HEADERS
372 { $$ = script_exp_function_sizeof_headers(); }
373 | ALIGNOF '(' STRING ')'
374 { $$ = script_exp_function_alignof($3.value, $3.length); }
375 | SIZEOF '(' STRING ')'
376 { $$ = script_exp_function_sizeof($3.value, $3.length); }
377 | ADDR '(' STRING ')'
378 { $$ = script_exp_function_addr($3.value, $3.length); }
379 | LOADADDR '(' STRING ')'
380 { $$ = script_exp_function_loadaddr($3.value, $3.length); }
381 | ORIGIN '(' STRING ')'
382 { $$ = script_exp_function_origin($3.value, $3.length); }
383 | LENGTH '(' STRING ')'
384 { $$ = script_exp_function_length($3.value, $3.length); }
385 | CONSTANT '(' STRING ')'
386 { $$ = script_exp_function_constant($3.value, $3.length); }
387 | ABSOLUTE '(' exp ')'
388 { $$ = script_exp_function_absolute($3); }
389 | ALIGN_K '(' exp ')'
390 { $$ = script_exp_function_align(script_exp_string(".", 1), $3); }
391 | ALIGN_K '(' exp ',' exp ')'
392 { $$ = script_exp_function_align($3, $5); }
393 | BLOCK '(' exp ')'
394 { $$ = script_exp_function_align(script_exp_string(".", 1), $3); }
395 | DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
396 { $$ = script_exp_function_data_segment_align($3, $5); }
397 | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
398 { $$ = script_exp_function_data_segment_relro_end($3, $5); }
399 | DATA_SEGMENT_END '(' exp ')'
400 { $$ = script_exp_function_data_segment_end($3); }
401 | SEGMENT_START '(' STRING ',' exp ')'
402 {
403 $$ = script_exp_function_segment_start($3.value, $3.length, $5);
404 }
405 | ASSERT_K '(' exp ',' STRING ')'
406 { $$ = script_exp_function_assert($3, $5.value, $5.length); }
407 ;
408
409 /* Handle the --defsym option. */
410 defsym_expr:
411 STRING '=' parse_exp
412 { script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); }
413 ;
414
415 /* A version script. Not yet implemented. */
416 version_script:
417 ;
418
419 /* Some statements require a terminator, which may be a semicolon or a
420 comma. */
421 end:
422 ';'
423 | ','
424 ;
425
426 /* An optional comma. */
427 opt_comma:
428 ','
429 | /* empty */
430 ;
431
432 %%
This page took 0.038769 seconds and 5 git commands to generate.