1 %{ 2 /* Parser for linker scripts. 3 Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 2001. 5 6 This program is Open Source software; you can redistribute it and/or 7 modify it under the terms of the Open Software License version 1.0 as 8 published by the Open Source Initiative. 9 10 You should have received a copy of the Open Software License along 11 with this program; if not, you may obtain a copy of the Open Software 12 License version 1.0 from http://www.opensource.org/licenses/osl.php or 13 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 14 3001 King Ranch Road, Ukiah, CA 95482. */ 15 16 #ifdef HAVE_CONFIG_H 17 # include <config.h> 18 #endif 19 20 #include <assert.h> 21 #include <error.h> 22 #include <libintl.h> 23 #include <stdbool.h> 24 #include <stdint.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include <system.h> 30 #include <ld.h> 31 32 /* The error handler. */ 33 static void yyerror (const char *s); 34 35 /* Some helper functions we need to construct the data structures 36 describing information from the file. */ 37 static struct expression *new_expr (int tag); 38 static struct input_section_name *new_input_section_name (const char *name, 39 bool sort_flag); 40 static struct input_rule *new_input_rule (int tag); 41 static struct output_rule *new_output_rule (int tag); 42 static struct assignment *new_assignment (const char *variable, 43 struct expression *expression, 44 bool provide_flag); 45 static void new_segment (int mode, struct output_rule *output_rule); 46 static struct filename_list *new_filename_listelem (const char *string); 47 static void add_inputfiles (struct filename_list *fnames); 48 static struct id_list *new_id_listelem (const char *str); 49 static struct version *new_version (struct id_list *local, 50 struct id_list *global); 51 static struct version *merge_versions (struct version *one, 52 struct version *two); 53 static void add_versions (struct version *versions); 54 55 extern int yylex (void); 56 %} 57 58 %union { 59 uintmax_t num; 60 enum expression_tag op; 61 char *str; 62 struct expression *expr; 63 struct input_section_name *sectionname; 64 struct filemask_section_name *filemask_section_name; 65 struct input_rule *input_rule; 66 struct output_rule *output_rule; 67 struct assignment *assignment; 68 struct filename_list *filename_list; 69 struct version *version; 70 struct id_list *id_list; 71 } 72 73 %token kADD_OP 74 %token kALIGN 75 %token kENTRY 76 %token kEXCLUDE_FILE 77 %token <str> kFILENAME 78 %token kGLOBAL 79 %token kGROUP 80 %token <str> kID 81 %token kINPUT 82 %token kINTERP 83 %token kKEEP 84 %token kLOCAL 85 %token <num> kMODE 86 %token kMUL_OP 87 %token <num> kNUM 88 %token kOUTPUT_FORMAT 89 %token kPAGESIZE 90 %token kPROVIDE 91 %token kSEARCH_DIR 92 %token kSEGMENT 93 %token kSIZEOF_HEADERS 94 %token kSORT 95 %token kVERSION 96 %token kVERSION_SCRIPT 97 98 %left '|' 99 %left '&' 100 %left ADD_OP 101 %left MUL_OP '*' 102 103 %type <op> kADD_OP 104 %type <op> kMUL_OP 105 %type <str> filename_id 106 %type <str> filename_id_star 107 %type <str> exclude_opt 108 %type <expr> expr 109 %type <sectionname> sort_opt_name 110 %type <filemask_section_name> sectionname 111 %type <input_rule> inputsection 112 %type <input_rule> inputsections 113 %type <output_rule> outputsection 114 %type <output_rule> outputsections 115 %type <assignment> assignment 116 %type <filename_list> filename_id_list 117 %type <version> versionlist 118 %type <version> version 119 %type <version> version_stmt_list 120 %type <version> version_stmt 121 %type <id_list> filename_id_star_list 122 123 %expect 16 124 125 %% 126 127 script_or_version: 128 file 129 | kVERSION_SCRIPT versionlist 130 { add_versions ($2); } 131 ; 132 133 file: file content 134 | content 135 ; 136 137 content: kENTRY '(' kID ')' ';' 138 { 139 if (likely (ld_state.entry == NULL)) 140 ld_state.entry = $3; 141 } 142 | kSEARCH_DIR '(' filename_id ')' ';' 143 { 144 ld_new_searchdir ($3); 145 } 146 | kPAGESIZE '(' kNUM ')' ';' 147 { 148 if (likely (ld_state.pagesize == 0)) 149 ld_state.pagesize = $3; 150 } 151 | kINTERP '(' filename_id ')' ';' 152 { 153 if (likely (ld_state.interp == NULL)) 154 ld_state.interp = $3; 155 } 156 | kSEGMENT kMODE '{' outputsections '}' 157 { 158 new_segment ($2, $4); 159 } 160 | kSEGMENT error '{' outputsections '}' 161 { 162 fputs_unlocked (gettext ("mode for segment invalid\n"), 163 stderr); 164 new_segment (0, $4); 165 } 166 | kGROUP '(' filename_id_list ')' 167 { 168 /* First little optimization. If there is only one 169 file in the group don't do anything. */ 170 if ($3 != $3->next) 171 { 172 $3->next->group_start = 1; 173 $3->group_end = 1; 174 } 175 add_inputfiles ($3); 176 } 177 | kINPUT '(' filename_id_list ')' 178 { add_inputfiles ($3); } 179 | kVERSION '{' versionlist '}' 180 { add_versions ($3); } 181 | kOUTPUT_FORMAT '(' filename_id ')' 182 { /* XXX TODO */ } 183 ; 184 185 outputsections: outputsections outputsection 186 { 187 $2->next = $1->next; 188 $$ = $1->next = $2; 189 } 190 | outputsection 191 { $$ = $1; } 192 ; 193 194 outputsection: assignment ';' 195 { 196 $$ = new_output_rule (output_assignment); 197 $$->val.assignment = $1; 198 } 199 | kID '{' inputsections '}' 200 { 201 $$ = new_output_rule (output_section); 202 $$->val.section.name = $1; 203 $$->val.section.input = $3->next; 204 if (ld_state.strip == strip_debug 205 && ebl_debugscn_p (ld_state.ebl, $1)) 206 $$->val.section.ignored = true; 207 else 208 $$->val.section.ignored = false; 209 $3->next = NULL; 210 } 211 | kID ';' 212 { 213 /* This is a short cut for "ID { *(ID) }". */ 214 $$ = new_output_rule (output_section); 215 $$->val.section.name = $1; 216 $$->val.section.input = new_input_rule (input_section); 217 $$->val.section.input->next = NULL; 218 $$->val.section.input->val.section = 219 (struct filemask_section_name *) 220 obstack_alloc (&ld_state.smem, 221 sizeof (struct filemask_section_name)); 222 $$->val.section.input->val.section->filemask = NULL; 223 $$->val.section.input->val.section->excludemask = NULL; 224 $$->val.section.input->val.section->section_name = 225 new_input_section_name ($1, false); 226 $$->val.section.input->val.section->keep_flag = false; 227 if (ld_state.strip == strip_debug 228 && ebl_debugscn_p (ld_state.ebl, $1)) 229 $$->val.section.ignored = true; 230 else 231 $$->val.section.ignored = false; 232 } 233 ; 234 235 assignment: kID '=' expr 236 { $$ = new_assignment ($1, $3, false); } 237 | kPROVIDE '(' kID '=' expr ')' 238 { $$ = new_assignment ($3, $5, true); } 239 ; 240 241 inputsections: inputsections inputsection 242 { 243 $2->next = $1->next; 244 $$ = $1->next = $2; 245 } 246 | inputsection 247 { $$ = $1; } 248 ; 249 250 inputsection: sectionname 251 { 252 $$ = new_input_rule (input_section); 253 $$->val.section = $1; 254 } 255 | kKEEP '(' sectionname ')' 256 { 257 $3->keep_flag = true; 258 259 $$ = new_input_rule (input_section); 260 $$->val.section = $3; 261 } 262 | assignment ';' 263 { 264 $$ = new_input_rule (input_assignment); 265 $$->val.assignment = $1; 266 } 267 ; 268 269 sectionname: filename_id_star '(' exclude_opt sort_opt_name ')' 270 { 271 $$ = (struct filemask_section_name *) 272 obstack_alloc (&ld_state.smem, sizeof (*$$)); 273 $$->filemask = $1; 274 $$->excludemask = $3; 275 $$->section_name = $4; 276 $$->keep_flag = false; 277 } 278 ; 279 280 sort_opt_name: kID 281 { $$ = new_input_section_name ($1, false); } 282 | kSORT '(' kID ')' 283 { $$ = new_input_section_name ($3, true); } 284 ; 285 286 exclude_opt: kEXCLUDE_FILE '(' filename_id ')' 287 { $$ = $3; } 288 | 289 { $$ = NULL; } 290 ; 291 292 expr: kALIGN '(' expr ')' 293 { 294 $$ = new_expr (exp_align); 295 $$->val.child = $3; 296 } 297 | '(' expr ')' 298 { $$ = $2; } 299 | expr '*' expr 300 { 301 $$ = new_expr (exp_mult); 302 $$->val.binary.left = $1; 303 $$->val.binary.right = $3; 304 } 305 | expr kMUL_OP expr 306 { 307 $$ = new_expr ($2); 308 $$->val.binary.left = $1; 309 $$->val.binary.right = $3; 310 } 311 | expr kADD_OP expr 312 { 313 $$ = new_expr ($2); 314 $$->val.binary.left = $1; 315 $$->val.binary.right = $3; 316 } 317 | expr '&' expr 318 { 319 $$ = new_expr (exp_and); 320 $$->val.binary.left = $1; 321 $$->val.binary.right = $3; 322 } 323 | expr '|' expr 324 { 325 $$ = new_expr (exp_or); 326 $$->val.binary.left = $1; 327 $$->val.binary.right = $3; 328 } 329 | kNUM 330 { 331 $$ = new_expr (exp_num); 332 $$->val.num = $1; 333 } 334 | kID 335 { 336 $$ = new_expr (exp_id); 337 $$->val.str = $1; 338 } 339 | kSIZEOF_HEADERS 340 { $$ = new_expr (exp_sizeof_headers); } 341 | kPAGESIZE 342 { $$ = new_expr (exp_pagesize); } 343 ; 344 345 filename_id_list: filename_id_list comma_opt filename_id 346 { 347 struct filename_list *newp = new_filename_listelem ($3); 348 newp->next = $1->next; 349 $$ = $1->next = newp; 350 } 351 | filename_id 352 { $$ = new_filename_listelem ($1); } 353 ; 354 355 comma_opt: ',' 356 | 357 ; 358 359 versionlist: versionlist version 360 { 361 $2->next = $1->next; 362 $$ = $1->next = $2; 363 } 364 | version 365 { $$ = $1; } 366 ; 367 368 version: '{' version_stmt_list '}' ';' 369 { 370 $2->versionname = ""; 371 $2->parentname = NULL; 372 $$ = $2; 373 } 374 | filename_id '{' version_stmt_list '}' ';' 375 { 376 $3->versionname = $1; 377 $3->parentname = NULL; 378 $$ = $3; 379 } 380 | filename_id '{' version_stmt_list '}' filename_id ';' 381 { 382 $3->versionname = $1; 383 $3->parentname = $5; 384 $$ = $3; 385 } 386 ; 387 388 version_stmt_list: 389 version_stmt_list version_stmt 390 { $$ = merge_versions ($1, $2); } 391 | version_stmt 392 { $$ = $1; } 393 ; 394 395 version_stmt: kGLOBAL filename_id_star_list 396 { $$ = new_version (NULL, $2); } 397 | kLOCAL filename_id_star_list 398 { $$ = new_version ($2, NULL); } 399 ; 400 401 filename_id_star_list: 402 filename_id_star_list filename_id_star ';' 403 { 404 struct id_list *newp = new_id_listelem ($2); 405 newp->next = $1->next; 406 $$ = $1->next = newp; 407 } 408 | filename_id_star ';' 409 { $$ = new_id_listelem ($1); } 410 ; 411 412 filename_id: kFILENAME 413 { $$ = $1; } 414 | kID 415 { $$ = $1; } 416 ; 417 418 filename_id_star: filename_id 419 { $$ = $1; } 420 | '*' 421 { $$ = NULL; } 422 ; 423 424 %% 425 426 static void 427 yyerror (const char *s) 428 { 429 error (0, 0, (ld_scan_version_script 430 ? gettext ("while reading version script '%s': %s at line %d") 431 : gettext ("while reading linker script '%s': %s at line %d")), 432 ldin_fname, gettext (s), ldlineno); 433 } 434 435 436 static struct expression * 437 new_expr (int tag) 438 { 439 struct expression *newp = (struct expression *) 440 obstack_alloc (&ld_state.smem, sizeof (*newp)); 441 442 newp->tag = tag; 443 return newp; 444 } 445 446 447 static struct input_section_name * 448 new_input_section_name (const char *name, bool sort_flag) 449 { 450 struct input_section_name *newp = (struct input_section_name *) 451 obstack_alloc (&ld_state.smem, sizeof (*newp)); 452 453 newp->name = name; 454 newp->sort_flag = sort_flag; 455 return newp; 456 } 457 458 459 static struct input_rule * 460 new_input_rule (int tag) 461 { 462 struct input_rule *newp = (struct input_rule *) 463 obstack_alloc (&ld_state.smem, sizeof (*newp)); 464 465 newp->tag = tag; 466 newp->next = newp; 467 return newp; 468 } 469 470 471 static struct output_rule * 472 new_output_rule (int tag) 473 { 474 struct output_rule *newp = (struct output_rule *) 475 memset (obstack_alloc (&ld_state.smem, sizeof (*newp)), 476 '\0', sizeof (*newp)); 477 478 newp->tag = tag; 479 newp->next = newp; 480 return newp; 481 } 482 483 484 static struct assignment * 485 new_assignment (const char *variable, struct expression *expression, 486 bool provide_flag) 487 { 488 struct assignment *newp = (struct assignment *) 489 obstack_alloc (&ld_state.smem, sizeof (*newp)); 490 491 newp->variable = variable; 492 newp->expression = expression; 493 newp->sym = NULL; 494 newp->provide_flag = provide_flag; 495 496 /* Insert the symbol into a hash table. We will later have to matc*/ 497 return newp; 498 } 499 500 501 static void 502 new_segment (int mode, struct output_rule *output_rule) 503 { 504 struct output_segment *newp; 505 506 newp 507 = (struct output_segment *) obstack_alloc (&ld_state.smem, sizeof (*newp)); 508 newp->mode = mode; 509 newp->next = newp; 510 511 newp->output_rules = output_rule->next; 512 output_rule->next = NULL; 513 514 /* Enqueue the output segment description. */ 515 if (ld_state.output_segments == NULL) 516 ld_state.output_segments = newp; 517 else 518 { 519 newp->next = ld_state.output_segments->next; 520 ld_state.output_segments = ld_state.output_segments->next = newp; 521 } 522 523 /* If the output file should be stripped of all symbol set the flag 524 in the structures of all output sections. */ 525 if (mode == 0 && ld_state.strip == strip_all) 526 { 527 struct output_rule *runp; 528 529 for (runp = newp->output_rules; runp != NULL; runp = runp->next) 530 if (runp->tag == output_section) 531 runp->val.section.ignored = true; 532 } 533 } 534 535 536 static struct filename_list * 537 new_filename_listelem (const char *string) 538 { 539 struct filename_list *newp; 540 541 /* We use calloc and not the obstack since this object can be freed soon. */ 542 newp = (struct filename_list *) xcalloc (1, sizeof (*newp)); 543 newp->name = string; 544 newp->next = newp; 545 return newp; 546 } 547 548 549 static void 550 add_inputfiles (struct filename_list *fnames) 551 { 552 assert (fnames != NULL); 553 554 if (ld_state.srcfiles == NULL) 555 ld_state.srcfiles = fnames; 556 else 557 { 558 struct filename_list *first = ld_state.srcfiles->next; 559 560 ld_state.srcfiles->next = fnames->next; 561 fnames->next = first; 562 ld_state.srcfiles->next = fnames; 563 } 564 } 565 566 567 static _Bool 568 special_char_p (const char *str) 569 { 570 while (*str != '\0') 571 { 572 if (__builtin_expect (*str == '*', 0) 573 || __builtin_expect (*str == '?', 0) 574 || __builtin_expect (*str == '[', 0)) 575 return true; 576 577 ++str; 578 } 579 580 return false; 581 } 582 583 584 static struct id_list * 585 new_id_listelem (const char *str) 586 { 587 struct id_list *newp; 588 589 newp = (struct id_list *) obstack_alloc (&ld_state.smem, sizeof (*newp)); 590 if (str == NULL) 591 newp->u.id_type = id_all; 592 else if (__builtin_expect (special_char_p (str), false)) 593 newp->u.id_type = id_wild; 594 else 595 newp->u.id_type = id_str; 596 newp->id = str; 597 newp->next = newp; 598 599 return newp; 600 } 601 602 603 static struct version * 604 new_version (struct id_list *local, struct id_list *global) 605 { 606 struct version *newp; 607 608 newp = (struct version *) obstack_alloc (&ld_state.smem, sizeof (*newp)); 609 newp->next = newp; 610 newp->local_names = local; 611 newp->global_names = global; 612 newp->versionname = NULL; 613 newp->parentname = NULL; 614 615 return newp; 616 } 617 618 619 static struct version * 620 merge_versions (struct version *one, struct version *two) 621 { 622 assert (two->local_names == NULL || two->global_names == NULL); 623 624 if (two->local_names != NULL) 625 { 626 if (one->local_names == NULL) 627 one->local_names = two->local_names; 628 else 629 { 630 two->local_names->next = one->local_names->next; 631 one->local_names = one->local_names->next = two->local_names; 632 } 633 } 634 else 635 { 636 if (one->global_names == NULL) 637 one->global_names = two->global_names; 638 else 639 { 640 two->global_names->next = one->global_names->next; 641 one->global_names = one->global_names->next = two->global_names; 642 } 643 } 644 645 return one; 646 } 647 648 649 static void 650 add_id_list (const char *versionname, struct id_list *runp, _Bool local) 651 { 652 struct id_list *lastp = runp; 653 654 if (runp == NULL) 655 /* Nothing to do. */ 656 return; 657 658 /* Convert into a simple single-linked list. */ 659 runp = runp->next; 660 assert (runp != NULL); 661 lastp->next = NULL; 662 663 do 664 if (runp->u.id_type == id_str) 665 { 666 struct id_list *curp; 667 struct id_list *defp; 668 unsigned long int hval = elf_hash (runp->id); 669 670 curp = runp; 671 runp = runp->next; 672 673 defp = ld_version_str_tab_find (&ld_state.version_str_tab, hval, curp); 674 if (defp != NULL) 675 { 676 /* There is already a version definition for this symbol. */ 677 while (strcmp (defp->u.s.versionname, versionname) != 0) 678 { 679 if (defp->next == NULL) 680 { 681 /* No version like this so far. */ 682 defp->next = curp; 683 curp->u.s.local = local; 684 curp->u.s.versionname = versionname; 685 curp->next = NULL; 686 defp = NULL; 687 break; 688 } 689 690 defp = defp->next; 691 } 692 693 if (defp != NULL && defp->u.s.local != local) 694 error (EXIT_FAILURE, 0, versionname[0] == '\0' 695 ? gettext ("\ 696 symbol '%s' in declared both local and global for unnamed version") 697 : gettext ("\ 698 symbol '%s' in declared both local and global for version '%s'"), 699 runp->id, versionname); 700 } 701 else 702 { 703 /* This is the first version definition for this symbol. */ 704 ld_version_str_tab_insert (&ld_state.version_str_tab, hval, curp); 705 706 curp->u.s.local = local; 707 curp->u.s.versionname = versionname; 708 curp->next = NULL; 709 } 710 } 711 else if (runp->u.id_type == id_all) 712 { 713 if (local) 714 { 715 if (ld_state.default_bind_global) 716 error (EXIT_FAILURE, 0, 717 gettext ("default visibility set as local and global")); 718 ld_state.default_bind_local = true; 719 } 720 else 721 { 722 if (ld_state.default_bind_local) 723 error (EXIT_FAILURE, 0, 724 gettext ("default visibility set as local and global")); 725 ld_state.default_bind_global = true; 726 } 727 728 runp = runp->next; 729 } 730 else 731 { 732 assert (runp->u.id_type == id_wild); 733 /* XXX TBI */ 734 abort (); 735 } 736 while (runp != NULL); 737 } 738 739 740 static void 741 add_versions (struct version *versions) 742 { 743 struct version *lastp = versions; 744 745 if (versions == NULL) 746 return; 747 748 /* Convert into a simple single-linked list. */ 749 versions = versions->next; 750 assert (versions != NULL); 751 lastp->next = NULL; 752 753 do 754 { 755 struct version *oldp; 756 757 add_id_list (versions->versionname, versions->local_names, true); 758 add_id_list (versions->versionname, versions->global_names, false); 759 760 oldp = versions; 761 versions = versions->next; 762 } 763 while (versions != NULL); 764 } 765