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