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