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(®ion->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