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