ldgram.y revision 89857
1209616Sjfv/* A YACC grammar to parse a superset of the AT&T linker scripting language. 2209616Sjfv Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3269196Sjfv 2001 Free Software Foundation, Inc. 4209616Sjfv Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). 5209616Sjfv 6209616SjfvThis file is part of GNU ld. 7209616Sjfv 8209616SjfvThis program is free software; you can redistribute it and/or modify 9209616Sjfvit under the terms of the GNU General Public License as published by 10209616Sjfvthe Free Software Foundation; either version 2 of the License, or 11209616Sjfv(at your option) any later version. 12209616Sjfv 13209616SjfvThis program is distributed in the hope that it will be useful, 14209616Sjfvbut WITHOUT ANY WARRANTY; without even the implied warranty of 15209616SjfvMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16209616SjfvGNU General Public License for more details. 17209616Sjfv 18209616SjfvYou should have received a copy of the GNU General Public License 19209616Sjfvalong with this program; if not, write to the Free Software 20209616SjfvFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21209616Sjfv 22209616Sjfv%{ 23209616Sjfv/* 24209616Sjfv 25209616Sjfv */ 26209616Sjfv 27209616Sjfv#define DONTDECLARE_MALLOC 28209616Sjfv 29209616Sjfv#include "bfd.h" 30209616Sjfv#include "sysdep.h" 31209616Sjfv#include "bfdlink.h" 32209616Sjfv#include "ld.h" 33209616Sjfv#include "ldexp.h" 34209616Sjfv#include "ldver.h" 35209616Sjfv#include "ldlang.h" 36209616Sjfv#include "ldfile.h" 37209616Sjfv#include "ldemul.h" 38209616Sjfv#include "ldmisc.h" 39209616Sjfv#include "ldmain.h" 40209616Sjfv#include "mri.h" 41269196Sjfv#include "ldctor.h" 42269196Sjfv#include "ldlex.h" 43269196Sjfv 44269196Sjfv#ifndef YYDEBUG 45269196Sjfv#define YYDEBUG 1 46269196Sjfv#endif 47269196Sjfv 48269196Sjfvstatic enum section_type sectype; 49209616Sjfv 50209616Sjfvlang_memory_region_type *region; 51269196Sjfv 52269196Sjfvboolean ldgram_want_filename = true; 53269196SjfvFILE * saved_script_handle = NULL; 54269196Sjfvboolean force_make_executable = false; 55269196Sjfv 56209616Sjfvboolean ldgram_in_script = false; 57209616Sjfvboolean ldgram_had_equals = false; 58269196Sjfvboolean ldgram_had_keep = false; 59209616Sjfvchar *ldgram_vers_current_lang = NULL; 60269196Sjfv 61209616Sjfv#define ERROR_NAME_MAX 20 62269196Sjfvstatic char *error_names[ERROR_NAME_MAX]; 63209616Sjfvstatic int error_index; 64209616Sjfv#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++; 65209616Sjfv#define POP_ERROR() error_index--; 66209616Sjfv%} 67209616Sjfv%union { 68269196Sjfv bfd_vma integer; 69269196Sjfv char *name; 70269196Sjfv const char *cname; 71269196Sjfv struct wildcard_spec wildcard; 72269196Sjfv struct wildcard_list *wildcard_list; 73269196Sjfv struct name_list *name_list; 74269196Sjfv int token; 75269196Sjfv union etree_union *etree; 76269196Sjfv struct phdr_info 77209616Sjfv { 78269196Sjfv boolean filehdr; 79269196Sjfv boolean phdrs; 80269196Sjfv union etree_union *at; 81209616Sjfv union etree_union *flags; 82269196Sjfv } phdr; 83269196Sjfv struct lang_nocrossref *nocrossref; 84269196Sjfv struct lang_output_section_phdr_list *section_phdr; 85269196Sjfv struct bfd_elf_version_deps *deflist; 86269196Sjfv struct bfd_elf_version_expr *versyms; 87269196Sjfv struct bfd_elf_version_tree *versnode; 88269196Sjfv} 89209616Sjfv 90269196Sjfv%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val 91209616Sjfv%type <etree> opt_exp_without_type 92269196Sjfv%type <integer> fill_opt 93269196Sjfv%type <name_list> exclude_name_list 94209616Sjfv%type <wildcard_list> file_NAME_list 95209616Sjfv%type <name> memspec_opt casesymlist 96209616Sjfv%type <name> memspec_at_opt 97209616Sjfv%type <cname> wildcard_name 98209616Sjfv%type <wildcard> wildcard_spec 99209616Sjfv%token <integer> INT 100209616Sjfv%token <name> NAME LNAME 101209616Sjfv%type <integer> length 102209616Sjfv%type <phdr> phdr_qualifiers 103209616Sjfv%type <nocrossref> nocrossref_list 104209616Sjfv%type <section_phdr> phdr_opt 105209616Sjfv%type <integer> opt_nocrossrefs 106209616Sjfv 107%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ 108%right <token> '?' ':' 109%left <token> OROR 110%left <token> ANDAND 111%left <token> '|' 112%left <token> '^' 113%left <token> '&' 114%left <token> EQ NE 115%left <token> '<' '>' LE GE 116%left <token> LSHIFT RSHIFT 117 118%left <token> '+' '-' 119%left <token> '*' '/' '%' 120 121%right UNARY 122%token END 123%left <token> '(' 124%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE 125%token SECTIONS PHDRS SORT 126%token '{' '}' 127%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH 128%token INHIBIT_COMMON_ALLOCATION 129%token SIZEOF_HEADERS 130%token INCLUDE 131%token MEMORY DEFSYMEND 132%token NOLOAD DSECT COPY INFO OVERLAY 133%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY 134%token <integer> NEXT 135%token SIZEOF ADDR LOADADDR MAX_K MIN_K 136%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS 137%token ORIGIN FILL 138%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS 139%token ALIGNMOD AT PROVIDE 140%type <token> assign_op atype attributes_opt 141%type <name> filename 142%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K 143%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL 144%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START 145%token <name> VERS_TAG VERS_IDENTIFIER 146%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT 147%token KEEP 148%token EXCLUDE_FILE 149%type <versyms> vers_defns 150%type <versnode> vers_tag 151%type <deflist> verdep 152 153%% 154 155file: 156 INPUT_SCRIPT script_file 157 | INPUT_MRI_SCRIPT mri_script_file 158 | INPUT_VERSION_SCRIPT version_script_file 159 | INPUT_DEFSYM defsym_expr 160 ; 161 162 163filename: NAME; 164 165 166defsym_expr: 167 { ldlex_defsym(); } 168 NAME '=' exp 169 { 170 ldlex_popstate(); 171 lang_add_assignment(exp_assop($3,$2,$4)); 172 } 173 174/* SYNTAX WITHIN AN MRI SCRIPT FILE */ 175mri_script_file: 176 { 177 ldlex_mri_script (); 178 PUSH_ERROR (_("MRI style script")); 179 } 180 mri_script_lines 181 { 182 ldlex_popstate (); 183 mri_draw_tree (); 184 POP_ERROR (); 185 } 186 ; 187 188mri_script_lines: 189 mri_script_lines mri_script_command NEWLINE 190 | 191 ; 192 193mri_script_command: 194 CHIP exp 195 | CHIP exp ',' exp 196 | NAME { 197 einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1); 198 } 199 | LIST { 200 config.map_filename = "-"; 201 } 202 | ORDER ordernamelist 203 | ENDWORD 204 | PUBLIC NAME '=' exp 205 { mri_public($2, $4); } 206 | PUBLIC NAME ',' exp 207 { mri_public($2, $4); } 208 | PUBLIC NAME exp 209 { mri_public($2, $3); } 210 | FORMAT NAME 211 { mri_format($2); } 212 | SECT NAME ',' exp 213 { mri_output_section($2, $4);} 214 | SECT NAME exp 215 { mri_output_section($2, $3);} 216 | SECT NAME '=' exp 217 { mri_output_section($2, $4);} 218 | ALIGN_K NAME '=' exp 219 { mri_align($2,$4); } 220 | ALIGN_K NAME ',' exp 221 { mri_align($2,$4); } 222 | ALIGNMOD NAME '=' exp 223 { mri_alignmod($2,$4); } 224 | ALIGNMOD NAME ',' exp 225 { mri_alignmod($2,$4); } 226 | ABSOLUTE mri_abs_name_list 227 | LOAD mri_load_name_list 228 | NAMEWORD NAME 229 { mri_name($2); } 230 | ALIAS NAME ',' NAME 231 { mri_alias($2,$4,0);} 232 | ALIAS NAME ',' INT 233 { mri_alias($2,0,(int) $4);} 234 | BASE exp 235 { mri_base($2); } 236 | TRUNCATE INT 237 { mri_truncate((unsigned int) $2); } 238 | CASE casesymlist 239 | EXTERN extern_name_list 240 | INCLUDE filename 241 { ldlex_script (); ldfile_open_command_file($2); } 242 mri_script_lines END 243 { ldlex_popstate (); } 244 | START NAME 245 { lang_add_entry ($2, false); } 246 | 247 ; 248 249ordernamelist: 250 ordernamelist ',' NAME { mri_order($3); } 251 | ordernamelist NAME { mri_order($2); } 252 | 253 ; 254 255mri_load_name_list: 256 NAME 257 { mri_load($1); } 258 | mri_load_name_list ',' NAME { mri_load($3); } 259 ; 260 261mri_abs_name_list: 262 NAME 263 { mri_only_load($1); } 264 | mri_abs_name_list ',' NAME 265 { mri_only_load($3); } 266 ; 267 268casesymlist: 269 /* empty */ { $$ = NULL; } 270 | NAME 271 | casesymlist ',' NAME 272 ; 273 274extern_name_list: 275 NAME 276 { ldlang_add_undef ($1); } 277 | extern_name_list NAME 278 { ldlang_add_undef ($2); } 279 | extern_name_list ',' NAME 280 { ldlang_add_undef ($3); } 281 ; 282 283script_file: 284 { 285 ldlex_both(); 286 } 287 ifile_list 288 { 289 ldlex_popstate(); 290 } 291 ; 292 293 294ifile_list: 295 ifile_list ifile_p1 296 | 297 ; 298 299 300 301ifile_p1: 302 memory 303 | sections 304 | phdrs 305 | startup 306 | high_level_library 307 | low_level_library 308 | floating_point_support 309 | statement_anywhere 310 | version 311 | ';' 312 | TARGET_K '(' NAME ')' 313 { lang_add_target($3); } 314 | SEARCH_DIR '(' filename ')' 315 { ldfile_add_library_path ($3, false); } 316 | OUTPUT '(' filename ')' 317 { lang_add_output($3, 1); } 318 | OUTPUT_FORMAT '(' NAME ')' 319 { lang_add_output_format ($3, (char *) NULL, 320 (char *) NULL, 1); } 321 | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')' 322 { lang_add_output_format ($3, $5, $7, 1); } 323 | OUTPUT_ARCH '(' NAME ')' 324 { ldfile_set_output_arch($3); } 325 | FORCE_COMMON_ALLOCATION 326 { command_line.force_common_definition = true ; } 327 | INHIBIT_COMMON_ALLOCATION 328 { command_line.inhibit_common_definition = true ; } 329 | INPUT '(' input_list ')' 330 | GROUP 331 { lang_enter_group (); } 332 '(' input_list ')' 333 { lang_leave_group (); } 334 | MAP '(' filename ')' 335 { lang_add_map($3); } 336 | INCLUDE filename 337 { ldlex_script (); ldfile_open_command_file($2); } 338 ifile_list END 339 { ldlex_popstate (); } 340 | NOCROSSREFS '(' nocrossref_list ')' 341 { 342 lang_add_nocrossref ($3); 343 } 344 | EXTERN '(' extern_name_list ')' 345 ; 346 347input_list: 348 NAME 349 { lang_add_input_file($1,lang_input_file_is_search_file_enum, 350 (char *)NULL); } 351 | input_list ',' NAME 352 { lang_add_input_file($3,lang_input_file_is_search_file_enum, 353 (char *)NULL); } 354 | input_list NAME 355 { lang_add_input_file($2,lang_input_file_is_search_file_enum, 356 (char *)NULL); } 357 | LNAME 358 { lang_add_input_file($1,lang_input_file_is_l_enum, 359 (char *)NULL); } 360 | input_list ',' LNAME 361 { lang_add_input_file($3,lang_input_file_is_l_enum, 362 (char *)NULL); } 363 | input_list LNAME 364 { lang_add_input_file($2,lang_input_file_is_l_enum, 365 (char *)NULL); } 366 ; 367 368sections: 369 SECTIONS '{' sec_or_group_p1 '}' 370 ; 371 372sec_or_group_p1: 373 sec_or_group_p1 section 374 | sec_or_group_p1 statement_anywhere 375 | 376 ; 377 378statement_anywhere: 379 ENTRY '(' NAME ')' 380 { lang_add_entry ($3, false); } 381 | assignment end 382 ; 383 384/* The '*' and '?' cases are there because the lexer returns them as 385 separate tokens rather than as NAME. */ 386wildcard_name: 387 NAME 388 { 389 $$ = $1; 390 } 391 | '*' 392 { 393 $$ = "*"; 394 } 395 | '?' 396 { 397 $$ = "?"; 398 } 399 ; 400 401wildcard_spec: 402 wildcard_name 403 { 404 $$.name = $1; 405 $$.sorted = false; 406 $$.exclude_name_list = NULL; 407 } 408 | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name 409 { 410 $$.name = $5; 411 $$.sorted = false; 412 $$.exclude_name_list = $3; 413 } 414 | SORT '(' wildcard_name ')' 415 { 416 $$.name = $3; 417 $$.sorted = true; 418 $$.exclude_name_list = NULL; 419 } 420 | SORT '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')' 421 { 422 $$.name = $7; 423 $$.sorted = true; 424 $$.exclude_name_list = $5; 425 } 426 ; 427 428exclude_name_list: 429 exclude_name_list wildcard_name 430 { 431 struct name_list *tmp; 432 tmp = (struct name_list *) xmalloc (sizeof *tmp); 433 tmp->name = $2; 434 tmp->next = $1; 435 $$ = tmp; 436 } 437 | 438 wildcard_name 439 { 440 struct name_list *tmp; 441 tmp = (struct name_list *) xmalloc (sizeof *tmp); 442 tmp->name = $1; 443 tmp->next = NULL; 444 $$ = tmp; 445 } 446 ; 447 448file_NAME_list: 449 file_NAME_list opt_comma wildcard_spec 450 { 451 struct wildcard_list *tmp; 452 tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); 453 tmp->next = $1; 454 tmp->spec = $3; 455 $$ = tmp; 456 } 457 | 458 wildcard_spec 459 { 460 struct wildcard_list *tmp; 461 tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); 462 tmp->next = NULL; 463 tmp->spec = $1; 464 $$ = tmp; 465 } 466 ; 467 468input_section_spec_no_keep: 469 NAME 470 { 471 struct wildcard_spec tmp; 472 tmp.name = $1; 473 tmp.exclude_name_list = NULL; 474 tmp.sorted = false; 475 lang_add_wild (&tmp, NULL, ldgram_had_keep); 476 } 477 | '[' file_NAME_list ']' 478 { 479 lang_add_wild (NULL, $2, ldgram_had_keep); 480 } 481 | wildcard_spec '(' file_NAME_list ')' 482 { 483 lang_add_wild (&$1, $3, ldgram_had_keep); 484 } 485 ; 486 487input_section_spec: 488 input_section_spec_no_keep 489 | KEEP '(' 490 { ldgram_had_keep = true; } 491 input_section_spec_no_keep ')' 492 { ldgram_had_keep = false; } 493 ; 494 495statement: 496 assignment end 497 | CREATE_OBJECT_SYMBOLS 498 { 499 lang_add_attribute(lang_object_symbols_statement_enum); 500 } 501 | ';' 502 | CONSTRUCTORS 503 { 504 505 lang_add_attribute(lang_constructors_statement_enum); 506 } 507 | SORT '(' CONSTRUCTORS ')' 508 { 509 constructors_sorted = true; 510 lang_add_attribute (lang_constructors_statement_enum); 511 } 512 | input_section_spec 513 | length '(' mustbe_exp ')' 514 { 515 lang_add_data((int) $1,$3); 516 } 517 518 | FILL '(' mustbe_exp ')' 519 { 520 lang_add_fill 521 (exp_get_value_int($3, 522 0, 523 "fill value", 524 lang_first_phase_enum)); 525 } 526 ; 527 528statement_list: 529 statement_list statement 530 | statement 531 ; 532 533statement_list_opt: 534 /* empty */ 535 | statement_list 536 ; 537 538length: 539 QUAD 540 { $$ = $1; } 541 | SQUAD 542 { $$ = $1; } 543 | LONG 544 { $$ = $1; } 545 | SHORT 546 { $$ = $1; } 547 | BYTE 548 { $$ = $1; } 549 ; 550 551fill_opt: 552 '=' mustbe_exp 553 { 554 $$ = exp_get_value_int($2, 555 0, 556 "fill value", 557 lang_first_phase_enum); 558 } 559 | { $$ = 0; } 560 ; 561 562 563 564assign_op: 565 PLUSEQ 566 { $$ = '+'; } 567 | MINUSEQ 568 { $$ = '-'; } 569 | MULTEQ 570 { $$ = '*'; } 571 | DIVEQ 572 { $$ = '/'; } 573 | LSHIFTEQ 574 { $$ = LSHIFT; } 575 | RSHIFTEQ 576 { $$ = RSHIFT; } 577 | ANDEQ 578 { $$ = '&'; } 579 | OREQ 580 { $$ = '|'; } 581 582 ; 583 584end: ';' | ',' 585 ; 586 587 588assignment: 589 NAME '=' mustbe_exp 590 { 591 lang_add_assignment (exp_assop ($2, $1, $3)); 592 } 593 | NAME assign_op mustbe_exp 594 { 595 lang_add_assignment (exp_assop ('=', $1, 596 exp_binop ($2, 597 exp_nameop (NAME, 598 $1), 599 $3))); 600 } 601 | PROVIDE '(' NAME '=' mustbe_exp ')' 602 { 603 lang_add_assignment (exp_provide ($3, $5)); 604 } 605 ; 606 607 608opt_comma: 609 ',' | ; 610 611 612memory: 613 MEMORY '{' memory_spec memory_spec_list '}' 614 ; 615 616memory_spec_list: 617 memory_spec_list memory_spec 618 | memory_spec_list ',' memory_spec 619 | 620 ; 621 622 623memory_spec: NAME 624 { region = lang_memory_region_lookup($1); } 625 attributes_opt ':' 626 origin_spec opt_comma length_spec 627 628 ; 629 630origin_spec: 631 ORIGIN '=' mustbe_exp 632 { region->current = 633 region->origin = 634 exp_get_vma($3, 0L,"origin", lang_first_phase_enum); 635} 636 ; 637 638length_spec: 639 LENGTH '=' mustbe_exp 640 { region->length = exp_get_vma($3, 641 ~((bfd_vma)0), 642 "length", 643 lang_first_phase_enum); 644 } 645 ; 646 647attributes_opt: 648 /* empty */ 649 { /* dummy action to avoid bison 1.25 error message */ } 650 | '(' attributes_list ')' 651 ; 652 653attributes_list: 654 attributes_string 655 | attributes_list attributes_string 656 ; 657 658attributes_string: 659 NAME 660 { lang_set_flags (region, $1, 0); } 661 | '!' NAME 662 { lang_set_flags (region, $2, 1); } 663 ; 664 665startup: 666 STARTUP '(' filename ')' 667 { lang_startup($3); } 668 ; 669 670high_level_library: 671 HLL '(' high_level_library_NAME_list ')' 672 | HLL '(' ')' 673 { ldemul_hll((char *)NULL); } 674 ; 675 676high_level_library_NAME_list: 677 high_level_library_NAME_list opt_comma filename 678 { ldemul_hll($3); } 679 | filename 680 { ldemul_hll($1); } 681 682 ; 683 684low_level_library: 685 SYSLIB '(' low_level_library_NAME_list ')' 686 ; low_level_library_NAME_list: 687 low_level_library_NAME_list opt_comma filename 688 { ldemul_syslib($3); } 689 | 690 ; 691 692floating_point_support: 693 FLOAT 694 { lang_float(true); } 695 | NOFLOAT 696 { lang_float(false); } 697 ; 698 699nocrossref_list: 700 /* empty */ 701 { 702 $$ = NULL; 703 } 704 | NAME nocrossref_list 705 { 706 struct lang_nocrossref *n; 707 708 n = (struct lang_nocrossref *) xmalloc (sizeof *n); 709 n->name = $1; 710 n->next = $2; 711 $$ = n; 712 } 713 | NAME ',' nocrossref_list 714 { 715 struct lang_nocrossref *n; 716 717 n = (struct lang_nocrossref *) xmalloc (sizeof *n); 718 n->name = $1; 719 n->next = $3; 720 $$ = n; 721 } 722 ; 723 724mustbe_exp: { ldlex_expression(); } 725 exp 726 { ldlex_popstate(); $$=$2;} 727 ; 728 729exp : 730 '-' exp %prec UNARY 731 { $$ = exp_unop('-', $2); } 732 | '(' exp ')' 733 { $$ = $2; } 734 | NEXT '(' exp ')' %prec UNARY 735 { $$ = exp_unop((int) $1,$3); } 736 | '!' exp %prec UNARY 737 { $$ = exp_unop('!', $2); } 738 | '+' exp %prec UNARY 739 { $$ = $2; } 740 | '~' exp %prec UNARY 741 { $$ = exp_unop('~', $2);} 742 743 | exp '*' exp 744 { $$ = exp_binop('*', $1, $3); } 745 | exp '/' exp 746 { $$ = exp_binop('/', $1, $3); } 747 | exp '%' exp 748 { $$ = exp_binop('%', $1, $3); } 749 | exp '+' exp 750 { $$ = exp_binop('+', $1, $3); } 751 | exp '-' exp 752 { $$ = exp_binop('-' , $1, $3); } 753 | exp LSHIFT exp 754 { $$ = exp_binop(LSHIFT , $1, $3); } 755 | exp RSHIFT exp 756 { $$ = exp_binop(RSHIFT , $1, $3); } 757 | exp EQ exp 758 { $$ = exp_binop(EQ , $1, $3); } 759 | exp NE exp 760 { $$ = exp_binop(NE , $1, $3); } 761 | exp LE exp 762 { $$ = exp_binop(LE , $1, $3); } 763 | exp GE exp 764 { $$ = exp_binop(GE , $1, $3); } 765 | exp '<' exp 766 { $$ = exp_binop('<' , $1, $3); } 767 | exp '>' exp 768 { $$ = exp_binop('>' , $1, $3); } 769 | exp '&' exp 770 { $$ = exp_binop('&' , $1, $3); } 771 | exp '^' exp 772 { $$ = exp_binop('^' , $1, $3); } 773 | exp '|' exp 774 { $$ = exp_binop('|' , $1, $3); } 775 | exp '?' exp ':' exp 776 { $$ = exp_trinop('?' , $1, $3, $5); } 777 | exp ANDAND exp 778 { $$ = exp_binop(ANDAND , $1, $3); } 779 | exp OROR exp 780 { $$ = exp_binop(OROR , $1, $3); } 781 | DEFINED '(' NAME ')' 782 { $$ = exp_nameop(DEFINED, $3); } 783 | INT 784 { $$ = exp_intop($1); } 785 | SIZEOF_HEADERS 786 { $$ = exp_nameop(SIZEOF_HEADERS,0); } 787 788 | SIZEOF '(' NAME ')' 789 { $$ = exp_nameop(SIZEOF,$3); } 790 | ADDR '(' NAME ')' 791 { $$ = exp_nameop(ADDR,$3); } 792 | LOADADDR '(' NAME ')' 793 { $$ = exp_nameop(LOADADDR,$3); } 794 | ABSOLUTE '(' exp ')' 795 { $$ = exp_unop(ABSOLUTE, $3); } 796 | ALIGN_K '(' exp ')' 797 { $$ = exp_unop(ALIGN_K,$3); } 798 | BLOCK '(' exp ')' 799 { $$ = exp_unop(ALIGN_K,$3); } 800 | NAME 801 { $$ = exp_nameop(NAME,$1); } 802 | MAX_K '(' exp ',' exp ')' 803 { $$ = exp_binop (MAX_K, $3, $5 ); } 804 | MIN_K '(' exp ',' exp ')' 805 { $$ = exp_binop (MIN_K, $3, $5 ); } 806 | ASSERT_K '(' exp ',' NAME ')' 807 { $$ = exp_assert ($3, $5); } 808 ; 809 810 811memspec_at_opt: 812 AT '>' NAME { $$ = $3; } 813 | { $$ = "*default*"; } 814 ; 815 816opt_at: 817 AT '(' exp ')' { $$ = $3; } 818 | { $$ = 0; } 819 ; 820 821section: NAME { ldlex_expression(); } 822 opt_exp_with_type 823 opt_at { ldlex_popstate (); ldlex_script (); } 824 '{' 825 { 826 lang_enter_output_section_statement($1, $3, 827 sectype, 828 0, 0, 0, $4); 829 } 830 statement_list_opt 831 '}' { ldlex_popstate (); ldlex_expression (); } 832 memspec_opt memspec_at_opt phdr_opt fill_opt 833 { 834 ldlex_popstate (); 835 lang_leave_output_section_statement ($14, $11, $13, $12); 836 } 837 opt_comma 838 | OVERLAY 839 { ldlex_expression (); } 840 opt_exp_without_type opt_nocrossrefs opt_at 841 { ldlex_popstate (); ldlex_script (); } 842 '{' 843 { 844 lang_enter_overlay ($3, $5, (int) $4); 845 } 846 overlay_section 847 '}' 848 { ldlex_popstate (); ldlex_expression (); } 849 memspec_opt memspec_at_opt phdr_opt fill_opt 850 { 851 ldlex_popstate (); 852 lang_leave_overlay ($15, $12, $14, $13); 853 } 854 opt_comma 855 | /* The GROUP case is just enough to support the gcc 856 svr3.ifile script. It is not intended to be full 857 support. I'm not even sure what GROUP is supposed 858 to mean. */ 859 GROUP { ldlex_expression (); } 860 opt_exp_with_type 861 { 862 ldlex_popstate (); 863 lang_add_assignment (exp_assop ('=', ".", $3)); 864 } 865 '{' sec_or_group_p1 '}' 866 ; 867 868type: 869 NOLOAD { sectype = noload_section; } 870 | DSECT { sectype = dsect_section; } 871 | COPY { sectype = copy_section; } 872 | INFO { sectype = info_section; } 873 | OVERLAY { sectype = overlay_section; } 874 ; 875 876atype: 877 '(' type ')' 878 | /* EMPTY */ { sectype = normal_section; } 879 | '(' ')' { sectype = normal_section; } 880 ; 881 882opt_exp_with_type: 883 exp atype ':' { $$ = $1; } 884 | atype ':' { $$ = (etree_type *)NULL; } 885 | /* The BIND cases are to support the gcc svr3.ifile 886 script. They aren't intended to implement full 887 support for the BIND keyword. I'm not even sure 888 what BIND is supposed to mean. */ 889 BIND '(' exp ')' atype ':' { $$ = $3; } 890 | BIND '(' exp ')' BLOCK '(' exp ')' atype ':' 891 { $$ = $3; } 892 ; 893 894opt_exp_without_type: 895 exp ':' { $$ = $1; } 896 | ':' { $$ = (etree_type *) NULL; } 897 ; 898 899opt_nocrossrefs: 900 /* empty */ 901 { $$ = 0; } 902 | NOCROSSREFS 903 { $$ = 1; } 904 ; 905 906memspec_opt: 907 '>' NAME 908 { $$ = $2; } 909 | { $$ = "*default*"; } 910 ; 911 912phdr_opt: 913 /* empty */ 914 { 915 $$ = NULL; 916 } 917 | phdr_opt ':' NAME 918 { 919 struct lang_output_section_phdr_list *n; 920 921 n = ((struct lang_output_section_phdr_list *) 922 xmalloc (sizeof *n)); 923 n->name = $3; 924 n->used = false; 925 n->next = $1; 926 $$ = n; 927 } 928 ; 929 930overlay_section: 931 /* empty */ 932 | overlay_section 933 NAME 934 { 935 ldlex_script (); 936 lang_enter_overlay_section ($2); 937 } 938 '{' statement_list_opt '}' 939 { ldlex_popstate (); ldlex_expression (); } 940 phdr_opt fill_opt 941 { 942 ldlex_popstate (); 943 lang_leave_overlay_section ($9, $8); 944 } 945 opt_comma 946 ; 947 948phdrs: 949 PHDRS '{' phdr_list '}' 950 ; 951 952phdr_list: 953 /* empty */ 954 | phdr_list phdr 955 ; 956 957phdr: 958 NAME { ldlex_expression (); } 959 phdr_type phdr_qualifiers { ldlex_popstate (); } 960 ';' 961 { 962 lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at, 963 $4.flags); 964 } 965 ; 966 967phdr_type: 968 exp 969 { 970 $$ = $1; 971 972 if ($1->type.node_class == etree_name 973 && $1->type.node_code == NAME) 974 { 975 const char *s; 976 unsigned int i; 977 static const char * const phdr_types[] = 978 { 979 "PT_NULL", "PT_LOAD", "PT_DYNAMIC", 980 "PT_INTERP", "PT_NOTE", "PT_SHLIB", 981 "PT_PHDR" 982 }; 983 984 s = $1->name.name; 985 for (i = 0; 986 i < sizeof phdr_types / sizeof phdr_types[0]; 987 i++) 988 if (strcmp (s, phdr_types[i]) == 0) 989 { 990 $$ = exp_intop (i); 991 break; 992 } 993 } 994 } 995 ; 996 997phdr_qualifiers: 998 /* empty */ 999 { 1000 memset (&$$, 0, sizeof (struct phdr_info)); 1001 } 1002 | NAME phdr_val phdr_qualifiers 1003 { 1004 $$ = $3; 1005 if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL) 1006 $$.filehdr = true; 1007 else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL) 1008 $$.phdrs = true; 1009 else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL) 1010 $$.flags = $2; 1011 else 1012 einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"), $1); 1013 } 1014 | AT '(' exp ')' phdr_qualifiers 1015 { 1016 $$ = $5; 1017 $$.at = $3; 1018 } 1019 ; 1020 1021phdr_val: 1022 /* empty */ 1023 { 1024 $$ = NULL; 1025 } 1026 | '(' exp ')' 1027 { 1028 $$ = $2; 1029 } 1030 ; 1031 1032/* This syntax is used within an external version script file. */ 1033 1034version_script_file: 1035 { 1036 ldlex_version_file (); 1037 PUSH_ERROR (_("VERSION script")); 1038 } 1039 vers_nodes 1040 { 1041 ldlex_popstate (); 1042 POP_ERROR (); 1043 } 1044 ; 1045 1046/* This is used within a normal linker script file. */ 1047 1048version: 1049 { 1050 ldlex_version_script (); 1051 } 1052 VERSIONK '{' vers_nodes '}' 1053 { 1054 ldlex_popstate (); 1055 } 1056 ; 1057 1058vers_nodes: 1059 vers_node 1060 | vers_nodes vers_node 1061 ; 1062 1063vers_node: 1064 '{' vers_tag '}' ';' 1065 { 1066 lang_register_vers_node (NULL, $2, NULL); 1067 } 1068 | VERS_TAG '{' vers_tag '}' ';' 1069 { 1070 lang_register_vers_node ($1, $3, NULL); 1071 } 1072 | VERS_TAG '{' vers_tag '}' verdep ';' 1073 { 1074 lang_register_vers_node ($1, $3, $5); 1075 } 1076 ; 1077 1078verdep: 1079 VERS_TAG 1080 { 1081 $$ = lang_add_vers_depend (NULL, $1); 1082 } 1083 | verdep VERS_TAG 1084 { 1085 $$ = lang_add_vers_depend ($1, $2); 1086 } 1087 ; 1088 1089vers_tag: 1090 /* empty */ 1091 { 1092 $$ = lang_new_vers_node (NULL, NULL); 1093 } 1094 | vers_defns ';' 1095 { 1096 $$ = lang_new_vers_node ($1, NULL); 1097 } 1098 | GLOBAL ':' vers_defns ';' 1099 { 1100 $$ = lang_new_vers_node ($3, NULL); 1101 } 1102 | LOCAL ':' vers_defns ';' 1103 { 1104 $$ = lang_new_vers_node (NULL, $3); 1105 } 1106 | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';' 1107 { 1108 $$ = lang_new_vers_node ($3, $7); 1109 } 1110 ; 1111 1112vers_defns: 1113 VERS_IDENTIFIER 1114 { 1115 $$ = lang_new_vers_regex (NULL, $1, ldgram_vers_current_lang); 1116 } 1117 | vers_defns ';' VERS_IDENTIFIER 1118 { 1119 $$ = lang_new_vers_regex ($1, $3, ldgram_vers_current_lang); 1120 } 1121 | EXTERN NAME '{' 1122 { 1123 $<name>$ = ldgram_vers_current_lang; 1124 ldgram_vers_current_lang = $2; 1125 } 1126 vers_defns '}' 1127 { 1128 $$ = $5; 1129 ldgram_vers_current_lang = $<name>4; 1130 } 1131 ; 1132 1133%% 1134void 1135yyerror(arg) 1136 const char *arg; 1137{ 1138 if (ldfile_assumed_script) 1139 einfo (_("%P:%s: file format not recognized; treating as linker script\n"), 1140 ldfile_input_filename); 1141 if (error_index > 0 && error_index < ERROR_NAME_MAX) 1142 einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]); 1143 else 1144 einfo ("%P%F:%S: %s\n", arg); 1145} 1146