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