ldgram.y revision 33965
1/* A YACC grammer to parse a superset of the AT&T linker scripting languaue. 2 Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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 enum section_type sectype; 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 struct lang_nocrossref *nocrossref; 79 struct lang_output_section_phdr_list *section_phdr; 80 struct bfd_elf_version_deps *deflist; 81 struct bfd_elf_version_expr *versyms; 82 struct bfd_elf_version_tree *versnode; 83} 84 85%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val 86%type <etree> opt_exp_without_type 87%type <integer> fill_opt 88%type <name> memspec_opt casesymlist 89%token <integer> INT 90%token <name> NAME LNAME 91%type <integer> length 92%type <phdr> phdr_qualifiers 93%type <nocrossref> nocrossref_list 94%type <section_phdr> phdr_opt 95%type <integer> opt_nocrossrefs 96 97%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ 98%right <token> '?' ':' 99%left <token> OROR 100%left <token> ANDAND 101%left <token> '|' 102%left <token> '^' 103%left <token> '&' 104%left <token> EQ NE 105%left <token> '<' '>' LE GE 106%left <token> LSHIFT RSHIFT 107 108%left <token> '+' '-' 109%left <token> '*' '/' '%' 110 111%right UNARY 112%token END 113%left <token> '(' 114%token <token> ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE 115%token SECTIONS PHDRS 116%token '{' '}' 117%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH 118%token SIZEOF_HEADERS 119%token INCLUDE 120%token MEMORY DEFSYMEND 121%token NOLOAD DSECT COPY INFO OVERLAY 122%token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY 123%token <integer> NEXT 124%token SIZEOF ADDR LOADADDR MAX MIN 125%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS 126%token ORIGIN FILL 127%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS 128%token ALIGNMOD AT PROVIDE 129%type <token> assign_op atype 130%type <name> filename 131%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD 132%token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL 133%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START 134%token <name> VERS_TAG VERS_IDENTIFIER 135%token GLOBAL LOCAL VERSION INPUT_VERSION_SCRIPT 136%type <versyms> vers_defns 137%type <versnode> vers_tag 138%type <deflist> verdep 139 140%% 141 142file: 143 INPUT_SCRIPT script_file 144 | INPUT_MRI_SCRIPT mri_script_file 145 | INPUT_VERSION_SCRIPT version_script_file 146 | INPUT_DEFSYM defsym_expr 147 ; 148 149 150filename: NAME; 151 152 153defsym_expr: 154 { ldlex_defsym(); } 155 NAME '=' exp 156 { 157 ldlex_popstate(); 158 lang_add_assignment(exp_assop($3,$2,$4)); 159 } 160 161/* SYNTAX WITHIN AN MRI SCRIPT FILE */ 162mri_script_file: 163 { 164 ldlex_mri_script (); 165 PUSH_ERROR ("MRI style script"); 166 } 167 mri_script_lines 168 { 169 ldlex_popstate (); 170 mri_draw_tree (); 171 POP_ERROR (); 172 } 173 ; 174 175mri_script_lines: 176 mri_script_lines mri_script_command NEWLINE 177 | 178 ; 179 180mri_script_command: 181 CHIP exp 182 | CHIP exp ',' exp 183 | NAME { 184 einfo("%P%F: unrecognised keyword in MRI style script '%s'\n",$1); 185 } 186 | LIST { 187 config.map_filename = "-"; 188 } 189 | ORDER ordernamelist 190 | ENDWORD 191 | PUBLIC NAME '=' exp 192 { mri_public($2, $4); } 193 | PUBLIC NAME ',' exp 194 { mri_public($2, $4); } 195 | PUBLIC NAME exp 196 { mri_public($2, $3); } 197 | FORMAT NAME 198 { mri_format($2); } 199 | SECT NAME ',' exp 200 { mri_output_section($2, $4);} 201 | SECT NAME exp 202 { mri_output_section($2, $3);} 203 | SECT NAME '=' exp 204 { mri_output_section($2, $4);} 205 | ALIGN_K NAME '=' exp 206 { mri_align($2,$4); } 207 | ALIGN_K NAME ',' exp 208 { mri_align($2,$4); } 209 | ALIGNMOD NAME '=' exp 210 { mri_alignmod($2,$4); } 211 | ALIGNMOD NAME ',' exp 212 { mri_alignmod($2,$4); } 213 | ABSOLUTE mri_abs_name_list 214 | LOAD mri_load_name_list 215 | NAMEWORD NAME 216 { mri_name($2); } 217 | ALIAS NAME ',' NAME 218 { mri_alias($2,$4,0);} 219 | ALIAS NAME ',' INT 220 { mri_alias($2,0,(int) $4);} 221 | BASE exp 222 { mri_base($2); } 223 | TRUNCATE INT 224 { mri_truncate((unsigned int) $2); } 225 | CASE casesymlist 226 | EXTERN extern_name_list 227 | INCLUDE filename 228 { ldfile_open_command_file ($2); } mri_script_lines END 229 | START NAME 230 { lang_add_entry ($2, false); } 231 | 232 ; 233 234ordernamelist: 235 ordernamelist ',' NAME { mri_order($3); } 236 | ordernamelist NAME { mri_order($2); } 237 | 238 ; 239 240mri_load_name_list: 241 NAME 242 { mri_load($1); } 243 | mri_load_name_list ',' NAME { mri_load($3); } 244 ; 245 246mri_abs_name_list: 247 NAME 248 { mri_only_load($1); } 249 | mri_abs_name_list ',' NAME 250 { mri_only_load($3); } 251 ; 252 253casesymlist: 254 /* empty */ { $$ = NULL; } 255 | NAME 256 | casesymlist ',' NAME 257 ; 258 259extern_name_list: 260 NAME 261 { ldlang_add_undef ($1); } 262 | extern_name_list ',' NAME 263 { ldlang_add_undef ($3); } 264 ; 265 266script_file: 267 { 268 ldlex_both(); 269 } 270 ifile_list 271 { 272 ldlex_popstate(); 273 } 274 ; 275 276 277ifile_list: 278 ifile_list ifile_p1 279 | 280 ; 281 282 283 284ifile_p1: 285 memory 286 | sections 287 | phdrs 288 | startup 289 | high_level_library 290 | low_level_library 291 | floating_point_support 292 | statement_anywhere 293 | version 294 | ';' 295 | TARGET_K '(' NAME ')' 296 { lang_add_target($3); } 297 | SEARCH_DIR '(' filename ')' 298 { ldfile_add_library_path ($3, false); } 299 | OUTPUT '(' filename ')' 300 { lang_add_output($3, 1); } 301 | OUTPUT_FORMAT '(' NAME ')' 302 { lang_add_output_format ($3, (char *) NULL, 303 (char *) NULL, 1); } 304 | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')' 305 { lang_add_output_format ($3, $5, $7, 1); } 306 | OUTPUT_ARCH '(' NAME ')' 307 { ldfile_set_output_arch($3); } 308 | FORCE_COMMON_ALLOCATION 309 { command_line.force_common_definition = true ; } 310 | INPUT '(' input_list ')' 311 | GROUP 312 { lang_enter_group (); } 313 '(' input_list ')' 314 { lang_leave_group (); } 315 | MAP '(' filename ')' 316 { lang_add_map($3); } 317 | INCLUDE filename 318 { ldfile_open_command_file($2); } ifile_list END 319 | NOCROSSREFS '(' nocrossref_list ')' 320 { 321 lang_add_nocrossref ($3); 322 } 323 ; 324 325input_list: 326 NAME 327 { lang_add_input_file($1,lang_input_file_is_search_file_enum, 328 (char *)NULL); } 329 | input_list ',' NAME 330 { lang_add_input_file($3,lang_input_file_is_search_file_enum, 331 (char *)NULL); } 332 | input_list NAME 333 { lang_add_input_file($2,lang_input_file_is_search_file_enum, 334 (char *)NULL); } 335 | LNAME 336 { lang_add_input_file($1,lang_input_file_is_l_enum, 337 (char *)NULL); } 338 | input_list ',' LNAME 339 { lang_add_input_file($3,lang_input_file_is_l_enum, 340 (char *)NULL); } 341 | input_list LNAME 342 { lang_add_input_file($2,lang_input_file_is_l_enum, 343 (char *)NULL); } 344 ; 345 346sections: 347 SECTIONS '{' sec_or_group_p1 '}' 348 ; 349 350sec_or_group_p1: 351 sec_or_group_p1 section 352 | sec_or_group_p1 statement_anywhere 353 | 354 ; 355 356statement_anywhere: 357 ENTRY '(' NAME ')' 358 { lang_add_entry ($3, false); } 359 | assignment end 360 ; 361 362/* The '*' and '?' cases are there because the lexer returns them as 363 separate tokens rather than as NAME. */ 364file_NAME_list: 365 NAME 366 { lang_add_wild ($1, current_file); } 367 | '*' 368 { lang_add_wild ("*", current_file); } 369 | '?' 370 { lang_add_wild ("?", current_file); } 371 | file_NAME_list opt_comma NAME 372 { lang_add_wild ($3, current_file); } 373 | file_NAME_list opt_comma '*' 374 { lang_add_wild ("*", current_file); } 375 | file_NAME_list opt_comma '?' 376 { lang_add_wild ("?", current_file); } 377 ; 378 379input_section_spec: 380 NAME 381 { 382 lang_add_wild((char *)NULL, $1); 383 } 384 | '[' 385 { 386 current_file = (char *)NULL; 387 } 388 file_NAME_list 389 ']' 390 | NAME 391 { 392 current_file = $1; 393 } 394 '(' file_NAME_list ')' 395 | '?' 396 /* This case is needed because the lexer returns a 397 single question mark as '?' rather than NAME. */ 398 { 399 current_file = "?"; 400 } 401 '(' file_NAME_list ')' 402 | '*' 403 { 404 current_file = (char *)NULL; 405 } 406 '(' file_NAME_list ')' 407 ; 408 409statement: 410 assignment end 411 | CREATE_OBJECT_SYMBOLS 412 { 413 lang_add_attribute(lang_object_symbols_statement_enum); 414 } 415 | ';' 416 | CONSTRUCTORS 417 { 418 419 lang_add_attribute(lang_constructors_statement_enum); 420 } 421 | input_section_spec 422 | length '(' mustbe_exp ')' 423 { 424 lang_add_data((int) $1,$3); 425 } 426 427 | FILL '(' mustbe_exp ')' 428 { 429 lang_add_fill 430 (exp_get_value_int($3, 431 0, 432 "fill value", 433 lang_first_phase_enum)); 434 } 435 ; 436 437statement_list: 438 statement_list statement 439 | statement 440 ; 441 442statement_list_opt: 443 /* empty */ 444 | statement_list 445 ; 446 447length: 448 QUAD 449 { $$ = $1; } 450 | LONG 451 { $$ = $1; } 452 | SHORT 453 { $$ = $1; } 454 | BYTE 455 { $$ = $1; } 456 ; 457 458fill_opt: 459 '=' mustbe_exp 460 { 461 $$ = exp_get_value_int($2, 462 0, 463 "fill value", 464 lang_first_phase_enum); 465 } 466 | { $$ = 0; } 467 ; 468 469 470 471assign_op: 472 PLUSEQ 473 { $$ = '+'; } 474 | MINUSEQ 475 { $$ = '-'; } 476 | MULTEQ 477 { $$ = '*'; } 478 | DIVEQ 479 { $$ = '/'; } 480 | LSHIFTEQ 481 { $$ = LSHIFT; } 482 | RSHIFTEQ 483 { $$ = RSHIFT; } 484 | ANDEQ 485 { $$ = '&'; } 486 | OREQ 487 { $$ = '|'; } 488 489 ; 490 491end: ';' | ',' 492 ; 493 494 495assignment: 496 NAME '=' mustbe_exp 497 { 498 lang_add_assignment (exp_assop ($2, $1, $3)); 499 } 500 | NAME assign_op mustbe_exp 501 { 502 lang_add_assignment (exp_assop ('=', $1, 503 exp_binop ($2, 504 exp_nameop (NAME, 505 $1), 506 $3))); 507 } 508 | PROVIDE '(' NAME '=' mustbe_exp ')' 509 { 510 lang_add_assignment (exp_provide ($3, $5)); 511 } 512 ; 513 514 515opt_comma: 516 ',' | ; 517 518 519memory: 520 MEMORY '{' memory_spec memory_spec_list '}' 521 ; 522 523memory_spec_list: 524 memory_spec_list memory_spec 525 | memory_spec_list ',' memory_spec 526 | 527 ; 528 529 530memory_spec: NAME 531 { region = lang_memory_region_lookup($1); } 532 attributes_opt ':' 533 origin_spec opt_comma length_spec 534 535 ; origin_spec: 536 ORIGIN '=' mustbe_exp 537 { region->current = 538 region->origin = 539 exp_get_vma($3, 0L,"origin", lang_first_phase_enum); 540} 541 ; length_spec: 542 LENGTH '=' mustbe_exp 543 { region->length = exp_get_vma($3, 544 ~((bfd_vma)0), 545 "length", 546 lang_first_phase_enum); 547 } 548 549 550attributes_opt: 551 '(' NAME ')' 552 { 553 lang_set_flags(®ion->flags, $2); 554 } 555 | 556 557 ; 558 559startup: 560 STARTUP '(' filename ')' 561 { lang_startup($3); } 562 ; 563 564high_level_library: 565 HLL '(' high_level_library_NAME_list ')' 566 | HLL '(' ')' 567 { ldemul_hll((char *)NULL); } 568 ; 569 570high_level_library_NAME_list: 571 high_level_library_NAME_list opt_comma filename 572 { ldemul_hll($3); } 573 | filename 574 { ldemul_hll($1); } 575 576 ; 577 578low_level_library: 579 SYSLIB '(' low_level_library_NAME_list ')' 580 ; low_level_library_NAME_list: 581 low_level_library_NAME_list opt_comma filename 582 { ldemul_syslib($3); } 583 | 584 ; 585 586floating_point_support: 587 FLOAT 588 { lang_float(true); } 589 | NOFLOAT 590 { lang_float(false); } 591 ; 592 593nocrossref_list: 594 /* empty */ 595 { 596 $$ = NULL; 597 } 598 | NAME nocrossref_list 599 { 600 struct lang_nocrossref *n; 601 602 n = (struct lang_nocrossref *) xmalloc (sizeof *n); 603 n->name = $1; 604 n->next = $2; 605 $$ = n; 606 } 607 | NAME ',' nocrossref_list 608 { 609 struct lang_nocrossref *n; 610 611 n = (struct lang_nocrossref *) xmalloc (sizeof *n); 612 n->name = $1; 613 n->next = $3; 614 $$ = n; 615 } 616 ; 617 618mustbe_exp: { ldlex_expression(); } 619 exp 620 { ldlex_popstate(); $$=$2;} 621 ; 622 623exp : 624 '-' exp %prec UNARY 625 { $$ = exp_unop('-', $2); } 626 | '(' exp ')' 627 { $$ = $2; } 628 | NEXT '(' exp ')' %prec UNARY 629 { $$ = exp_unop((int) $1,$3); } 630 | '!' exp %prec UNARY 631 { $$ = exp_unop('!', $2); } 632 | '+' exp %prec UNARY 633 { $$ = $2; } 634 | '~' exp %prec UNARY 635 { $$ = exp_unop('~', $2);} 636 637 | exp '*' exp 638 { $$ = exp_binop('*', $1, $3); } 639 | exp '/' exp 640 { $$ = exp_binop('/', $1, $3); } 641 | exp '%' exp 642 { $$ = exp_binop('%', $1, $3); } 643 | exp '+' exp 644 { $$ = exp_binop('+', $1, $3); } 645 | exp '-' exp 646 { $$ = exp_binop('-' , $1, $3); } 647 | exp LSHIFT exp 648 { $$ = exp_binop(LSHIFT , $1, $3); } 649 | exp RSHIFT exp 650 { $$ = exp_binop(RSHIFT , $1, $3); } 651 | exp EQ exp 652 { $$ = exp_binop(EQ , $1, $3); } 653 | exp NE exp 654 { $$ = exp_binop(NE , $1, $3); } 655 | exp LE exp 656 { $$ = exp_binop(LE , $1, $3); } 657 | exp GE exp 658 { $$ = exp_binop(GE , $1, $3); } 659 | exp '<' exp 660 { $$ = exp_binop('<' , $1, $3); } 661 | exp '>' exp 662 { $$ = exp_binop('>' , $1, $3); } 663 | exp '&' exp 664 { $$ = exp_binop('&' , $1, $3); } 665 | exp '^' exp 666 { $$ = exp_binop('^' , $1, $3); } 667 | exp '|' exp 668 { $$ = exp_binop('|' , $1, $3); } 669 | exp '?' exp ':' exp 670 { $$ = exp_trinop('?' , $1, $3, $5); } 671 | exp ANDAND exp 672 { $$ = exp_binop(ANDAND , $1, $3); } 673 | exp OROR exp 674 { $$ = exp_binop(OROR , $1, $3); } 675 | DEFINED '(' NAME ')' 676 { $$ = exp_nameop(DEFINED, $3); } 677 | INT 678 { $$ = exp_intop($1); } 679 | SIZEOF_HEADERS 680 { $$ = exp_nameop(SIZEOF_HEADERS,0); } 681 682 | SIZEOF '(' NAME ')' 683 { $$ = exp_nameop(SIZEOF,$3); } 684 | ADDR '(' NAME ')' 685 { $$ = exp_nameop(ADDR,$3); } 686 | LOADADDR '(' NAME ')' 687 { $$ = exp_nameop(LOADADDR,$3); } 688 | ABSOLUTE '(' exp ')' 689 { $$ = exp_unop(ABSOLUTE, $3); } 690 | ALIGN_K '(' exp ')' 691 { $$ = exp_unop(ALIGN_K,$3); } 692 | BLOCK '(' exp ')' 693 { $$ = exp_unop(ALIGN_K,$3); } 694 | NAME 695 { $$ = exp_nameop(NAME,$1); } 696 | MAX '(' exp ',' exp ')' 697 { $$ = exp_binop (MAX, $3, $5 ); } 698 | MIN '(' exp ',' exp ')' 699 { $$ = exp_binop (MIN, $3, $5 ); } 700 ; 701 702 703opt_at: 704 AT '(' exp ')' { $$ = $3; } 705 | { $$ = 0; } 706 ; 707 708section: NAME { ldlex_expression(); } 709 opt_exp_with_type 710 opt_at { ldlex_popstate (); ldlex_script (); } 711 '{' 712 { 713 lang_enter_output_section_statement($1, $3, 714 sectype, 715 0, 0, 0, $4); 716 } 717 statement_list_opt 718 '}' { ldlex_popstate (); ldlex_expression (); } 719 memspec_opt phdr_opt fill_opt 720 { 721 ldlex_popstate (); 722 lang_leave_output_section_statement ($13, $11, $12); 723 } 724 opt_comma 725 | OVERLAY 726 { ldlex_expression (); } 727 opt_exp_without_type opt_nocrossrefs opt_at 728 { ldlex_popstate (); ldlex_script (); } 729 '{' 730 { 731 lang_enter_overlay ($3, $5, (int) $4); 732 } 733 overlay_section 734 '}' 735 { ldlex_popstate (); ldlex_expression (); } 736 memspec_opt phdr_opt fill_opt 737 { 738 ldlex_popstate (); 739 lang_leave_overlay ($14, $12, $13); 740 } 741 opt_comma 742 | /* The GROUP case is just enough to support the gcc 743 svr3.ifile script. It is not intended to be full 744 support. I'm not even sure what GROUP is supposed 745 to mean. */ 746 GROUP { ldlex_expression (); } 747 opt_exp_with_type 748 { 749 ldlex_popstate (); 750 lang_add_assignment (exp_assop ('=', ".", $3)); 751 } 752 '{' sec_or_group_p1 '}' 753 ; 754 755type: 756 NOLOAD { sectype = noload_section; } 757 | DSECT { sectype = dsect_section; } 758 | COPY { sectype = copy_section; } 759 | INFO { sectype = info_section; } 760 | OVERLAY { sectype = overlay_section; } 761 ; 762 763atype: 764 '(' type ')' 765 | /* EMPTY */ { sectype = normal_section; } 766 ; 767 768opt_exp_with_type: 769 exp atype ':' { $$ = $1; } 770 | atype ':' { $$ = (etree_type *)NULL; } 771 | /* The BIND cases are to support the gcc svr3.ifile 772 script. They aren't intended to implement full 773 support for the BIND keyword. I'm not even sure 774 what BIND is supposed to mean. */ 775 BIND '(' exp ')' atype ':' { $$ = $3; } 776 | BIND '(' exp ')' BLOCK '(' exp ')' atype ':' 777 { $$ = $3; } 778 ; 779 780opt_exp_without_type: 781 exp ':' { $$ = $1; } 782 | ':' { $$ = (etree_type *) NULL; } 783 ; 784 785opt_nocrossrefs: 786 /* empty */ 787 { $$ = 0; } 788 | NOCROSSREFS 789 { $$ = 1; } 790 ; 791 792memspec_opt: 793 '>' NAME 794 { $$ = $2; } 795 | { $$ = "*default*"; } 796 ; 797 798phdr_opt: 799 /* empty */ 800 { 801 $$ = NULL; 802 } 803 | phdr_opt ':' NAME 804 { 805 struct lang_output_section_phdr_list *n; 806 807 n = ((struct lang_output_section_phdr_list *) 808 xmalloc (sizeof *n)); 809 n->name = $3; 810 n->used = false; 811 n->next = $1; 812 $$ = n; 813 } 814 ; 815 816overlay_section: 817 /* empty */ 818 | overlay_section 819 NAME 820 { 821 ldlex_script (); 822 lang_enter_overlay_section ($2); 823 } 824 '{' statement_list_opt '}' 825 { ldlex_popstate (); ldlex_expression (); } 826 phdr_opt fill_opt 827 { 828 ldlex_popstate (); 829 lang_leave_overlay_section ($9, $8); 830 } 831 opt_comma 832 ; 833 834phdrs: 835 PHDRS '{' phdr_list '}' 836 ; 837 838phdr_list: 839 /* empty */ 840 | phdr_list phdr 841 ; 842 843phdr: 844 NAME { ldlex_expression (); } 845 phdr_type phdr_qualifiers { ldlex_popstate (); } 846 ';' 847 { 848 lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at, 849 $4.flags); 850 } 851 ; 852 853phdr_type: 854 exp 855 { 856 $$ = $1; 857 858 if ($1->type.node_class == etree_name 859 && $1->type.node_code == NAME) 860 { 861 const char *s; 862 unsigned int i; 863 static const char * const phdr_types[] = 864 { 865 "PT_NULL", "PT_LOAD", "PT_DYNAMIC", 866 "PT_INTERP", "PT_NOTE", "PT_SHLIB", 867 "PT_PHDR" 868 }; 869 870 s = $1->name.name; 871 for (i = 0; 872 i < sizeof phdr_types / sizeof phdr_types[0]; 873 i++) 874 if (strcmp (s, phdr_types[i]) == 0) 875 { 876 $$ = exp_intop (i); 877 break; 878 } 879 } 880 } 881 ; 882 883phdr_qualifiers: 884 /* empty */ 885 { 886 memset (&$$, 0, sizeof (struct phdr_info)); 887 } 888 | NAME phdr_val phdr_qualifiers 889 { 890 $$ = $3; 891 if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL) 892 $$.filehdr = true; 893 else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL) 894 $$.phdrs = true; 895 else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL) 896 $$.flags = $2; 897 else 898 einfo ("%X%P:%S: PHDRS syntax error at `%s'\n", $1); 899 } 900 | AT '(' exp ')' phdr_qualifiers 901 { 902 $$ = $5; 903 $$.at = $3; 904 } 905 ; 906 907phdr_val: 908 /* empty */ 909 { 910 $$ = NULL; 911 } 912 | '(' exp ')' 913 { 914 $$ = $2; 915 } 916 ; 917 918/* This syntax is used within an external version script file. */ 919 920version_script_file: 921 { 922 ldlex_version_file (); 923 PUSH_ERROR ("VERSION script"); 924 } 925 vers_nodes 926 { 927 ldlex_popstate (); 928 POP_ERROR (); 929 } 930 ; 931 932/* This is used within a normal linker script file. */ 933 934version: 935 { 936 ldlex_version_script (); 937 } 938 VERSION '{' vers_nodes '}' 939 { 940 ldlex_popstate (); 941 } 942 ; 943 944vers_nodes: 945 vers_node 946 | vers_nodes vers_node 947 ; 948 949vers_node: 950 VERS_TAG '{' vers_tag '}' ';' 951 { 952 lang_register_vers_node ($1, $3, NULL); 953 } 954 | VERS_TAG '{' vers_tag '}' verdep ';' 955 { 956 lang_register_vers_node ($1, $3, $5); 957 } 958 ; 959 960verdep: 961 VERS_TAG 962 { 963 $$ = lang_add_vers_depend (NULL, $1); 964 } 965 | verdep VERS_TAG 966 { 967 $$ = lang_add_vers_depend ($1, $2); 968 } 969 ; 970 971vers_tag: 972 /* empty */ 973 { 974 $$ = lang_new_vers_node (NULL, NULL); 975 } 976 | vers_defns ';' 977 { 978 $$ = lang_new_vers_node ($1, NULL); 979 } 980 | GLOBAL ':' vers_defns ';' 981 { 982 $$ = lang_new_vers_node ($3, NULL); 983 } 984 | LOCAL ':' vers_defns ';' 985 { 986 $$ = lang_new_vers_node (NULL, $3); 987 } 988 | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';' 989 { 990 $$ = lang_new_vers_node ($3, $7); 991 } 992 ; 993 994vers_defns: 995 VERS_IDENTIFIER 996 { 997 $$ = lang_new_vers_regex (NULL, $1); 998 } 999 | vers_defns ';' VERS_IDENTIFIER 1000 { 1001 $$ = lang_new_vers_regex ($1, $3); 1002 } 1003 ; 1004 1005%% 1006void 1007yyerror(arg) 1008 const char *arg; 1009{ 1010 if (ldfile_assumed_script) 1011 einfo ("%P:%s: file format not recognized; treating as linker script\n", 1012 ldfile_input_filename); 1013 if (error_index > 0 && error_index < ERROR_NAME_MAX) 1014 einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]); 1015 else 1016 einfo ("%P%F:%S: %s\n", arg); 1017} 1018