1 %{ /* deffilep.y - parser for .def files */ 2 3 /* Copyright (C) 1995-2014 Free Software Foundation, Inc. 4 5 This file is part of GNU Binutils. 6 7 This program 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 This program is distributed in the hope that it will be useful, 13 but 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, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "libiberty.h" 24 #include "safe-ctype.h" 25 #include "bfd.h" 26 #include "ld.h" 27 #include "ldmisc.h" 28 #include "deffile.h" 29 30 #define TRACE 0 31 32 #define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1)) 33 34 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), 35 as well as gratuitiously global symbol names, so we can have multiple 36 yacc generated parsers in ld. Note that these are only the variables 37 produced by yacc. If other parser generators (bison, byacc, etc) produce 38 additional global names that conflict at link time, then those parser 39 generators need to be fixed instead of adding those names to this list. */ 40 41 #define yymaxdepth def_maxdepth 42 #define yyparse def_parse 43 #define yylex def_lex 44 #define yyerror def_error 45 #define yylval def_lval 46 #define yychar def_char 47 #define yydebug def_debug 48 #define yypact def_pact 49 #define yyr1 def_r1 50 #define yyr2 def_r2 51 #define yydef def_def 52 #define yychk def_chk 53 #define yypgo def_pgo 54 #define yyact def_act 55 #define yyexca def_exca 56 #define yyerrflag def_errflag 57 #define yynerrs def_nerrs 58 #define yyps def_ps 59 #define yypv def_pv 60 #define yys def_s 61 #define yy_yys def_yys 62 #define yystate def_state 63 #define yytmp def_tmp 64 #define yyv def_v 65 #define yy_yyv def_yyv 66 #define yyval def_val 67 #define yylloc def_lloc 68 #define yyreds def_reds /* With YYDEBUG defined. */ 69 #define yytoks def_toks /* With YYDEBUG defined. */ 70 #define yylhs def_yylhs 71 #define yylen def_yylen 72 #define yydefred def_yydefred 73 #define yydgoto def_yydgoto 74 #define yysindex def_yysindex 75 #define yyrindex def_yyrindex 76 #define yygindex def_yygindex 77 #define yytable def_yytable 78 #define yycheck def_yycheck 79 80 typedef struct def_pool_str { 81 struct def_pool_str *next; 82 char data[1]; 83 } def_pool_str; 84 85 static def_pool_str *pool_strs = NULL; 86 87 static char *def_pool_alloc (size_t sz); 88 static char *def_pool_strdup (const char *str); 89 static void def_pool_free (void); 90 91 static void def_description (const char *); 92 static void def_exports (const char *, const char *, int, int, const char *); 93 static void def_heapsize (int, int); 94 static void def_import (const char *, const char *, const char *, const char *, 95 int, const char *); 96 static void def_image_name (const char *, bfd_vma, int); 97 static void def_section (const char *, int); 98 static void def_section_alt (const char *, const char *); 99 static void def_stacksize (int, int); 100 static void def_version (int, int); 101 static void def_directive (char *); 102 static void def_aligncomm (char *str, int align); 103 static int def_parse (void); 104 static int def_error (const char *); 105 static int def_lex (void); 106 107 static int lex_forced_token = 0; 108 static const char *lex_parse_string = 0; 109 static const char *lex_parse_string_end = 0; 110 111 %} 112 113 %union { 114 char *id; 115 const char *id_const; 116 int number; 117 bfd_vma vma; 118 char *digits; 119 }; 120 121 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL 122 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL 123 %token PRIVATEU PRIVATEL ALIGNCOMM 124 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL 125 %token <id> ID 126 %token <digits> DIGITS 127 %type <number> NUMBER 128 %type <vma> VMA opt_base 129 %type <digits> opt_digits 130 %type <number> opt_ordinal 131 %type <number> attr attr_list opt_number exp_opt_list exp_opt 132 %type <id> opt_name opt_name2 opt_equal_name anylang_id opt_id 133 %type <id> opt_equalequal_name 134 %type <id_const> keyword_as_name 135 136 %% 137 138 start: start command 139 | command 140 ; 141 142 command: 143 NAME opt_name opt_base { def_image_name ($2, $3, 0); } 144 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); } 145 | DESCRIPTION ID { def_description ($2);} 146 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);} 147 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} 148 | CODE attr_list { def_section ("CODE", $2);} 149 | DATAU attr_list { def_section ("DATA", $2);} 150 | SECTIONS seclist 151 | EXPORTS explist 152 | IMPORTS implist 153 | VERSIONK NUMBER { def_version ($2, 0);} 154 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);} 155 | DIRECTIVE ID { def_directive ($2);} 156 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);} 157 ; 158 159 160 explist: 161 /* EMPTY */ 162 | expline 163 | explist expline 164 ; 165 166 expline: 167 /* The opt_comma is necessary to support both the usual 168 DEF file syntax as well as .drectve syntax which 169 mandates <expsym>,<expoptlist>. */ 170 opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name 171 { def_exports ($1, $2, $3, $5, $7); } 172 ; 173 exp_opt_list: 174 /* The opt_comma is necessary to support both the usual 175 DEF file syntax as well as .drectve syntax which 176 allows for comma separated opt list. */ 177 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; } 178 | { $$ = 0; } 179 ; 180 exp_opt: 181 NONAMEU { $$ = 1; } 182 | NONAMEL { $$ = 1; } 183 | CONSTANTU { $$ = 2; } 184 | CONSTANTL { $$ = 2; } 185 | DATAU { $$ = 4; } 186 | DATAL { $$ = 4; } 187 | PRIVATEU { $$ = 8; } 188 | PRIVATEL { $$ = 8; } 189 ; 190 implist: 191 implist impline 192 | impline 193 ; 194 195 impline: 196 ID '=' ID '.' ID '.' ID opt_equalequal_name 197 { def_import ($1, $3, $5, $7, -1, $8); } 198 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name 199 { def_import ($1, $3, $5, 0, $7, $8); } 200 | ID '=' ID '.' ID opt_equalequal_name 201 { def_import ($1, $3, 0, $5, -1, $6); } 202 | ID '=' ID '.' NUMBER opt_equalequal_name 203 { def_import ($1, $3, 0, 0, $5, $6); } 204 | ID '.' ID '.' ID opt_equalequal_name 205 { def_import( 0, $1, $3, $5, -1, $6); } 206 | ID '.' ID opt_equalequal_name 207 { def_import ( 0, $1, 0, $3, -1, $4); } 208 ; 209 210 seclist: 211 seclist secline 212 | secline 213 ; 214 215 secline: 216 ID attr_list { def_section ($1, $2);} 217 | ID ID { def_section_alt ($1, $2);} 218 ; 219 220 attr_list: 221 attr_list opt_comma attr { $$ = $1 | $3; } 222 | attr { $$ = $1; } 223 ; 224 225 opt_comma: 226 ',' 227 | 228 ; 229 opt_number: ',' NUMBER { $$=$2;} 230 | { $$=-1;} 231 ; 232 233 attr: 234 READ { $$ = 1;} 235 | WRITE { $$ = 2;} 236 | EXECUTE { $$=4;} 237 | SHARED { $$=8;} 238 ; 239 240 241 keyword_as_name: BASE { $$ = "BASE"; } 242 | CODE { $$ = "CODE"; } 243 | CONSTANTU { $$ = "CONSTANT"; } 244 | CONSTANTL { $$ = "constant"; } 245 | DATAU { $$ = "DATA"; } 246 | DATAL { $$ = "data"; } 247 | DESCRIPTION { $$ = "DESCRIPTION"; } 248 | DIRECTIVE { $$ = "DIRECTIVE"; } 249 | EXECUTE { $$ = "EXECUTE"; } 250 | EXPORTS { $$ = "EXPORTS"; } 251 | HEAPSIZE { $$ = "HEAPSIZE"; } 252 | IMPORTS { $$ = "IMPORTS"; } 253 /* Disable LIBRARY keyword as valid symbol-name. This is necessary 254 for libtool, which places this command after EXPORTS command. 255 This behavior is illegal by specification, but sadly required by 256 by compatibility reasons. 257 See PR binutils/13710 258 | LIBRARY { $$ = "LIBRARY"; } */ 259 | NAME { $$ = "NAME"; } 260 | NONAMEU { $$ = "NONAME"; } 261 | NONAMEL { $$ = "noname"; } 262 | PRIVATEU { $$ = "PRIVATE"; } 263 | PRIVATEL { $$ = "private"; } 264 | READ { $$ = "READ"; } 265 | SHARED { $$ = "SHARED"; } 266 | STACKSIZE_K { $$ = "STACKSIZE"; } 267 | VERSIONK { $$ = "VERSION"; } 268 | WRITE { $$ = "WRITE"; } 269 ; 270 271 opt_name2: ID { $$ = $1; } 272 | '.' keyword_as_name 273 { 274 char *name = xmalloc (strlen ($2) + 2); 275 sprintf (name, ".%s", $2); 276 $$ = name; 277 } 278 | '.' opt_name2 279 { 280 char *name = def_pool_alloc (strlen ($2) + 2); 281 sprintf (name, ".%s", $2); 282 $$ = name; 283 } 284 | keyword_as_name '.' opt_name2 285 { 286 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1); 287 sprintf (name, "%s.%s", $1, $3); 288 $$ = name; 289 } 290 | ID '.' opt_name2 291 { 292 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1); 293 sprintf (name, "%s.%s", $1, $3); 294 $$ = name; 295 } 296 ; 297 298 opt_name: opt_name2 { $$ = $1; } 299 | { $$ = ""; } 300 ; 301 302 opt_equalequal_name: EQUAL ID { $$ = $2; } 303 | { $$ = 0; } 304 ; 305 306 opt_ordinal: 307 '@' NUMBER { $$ = $2;} 308 | { $$ = -1;} 309 ; 310 311 opt_equal_name: 312 '=' opt_name2 { $$ = $2; } 313 | { $$ = 0; } 314 ; 315 316 opt_base: BASE '=' VMA { $$ = $3;} 317 | { $$ = (bfd_vma) -1;} 318 ; 319 320 anylang_id: ID { $$ = $1; } 321 | '.' ID 322 { 323 char *id = def_pool_alloc (strlen ($2) + 2); 324 sprintf (id, ".%s", $2); 325 $$ = id; 326 } 327 | anylang_id '.' opt_digits opt_id 328 { 329 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1); 330 sprintf (id, "%s.%s%s", $1, $3, $4); 331 $$ = id; 332 } 333 ; 334 335 opt_digits: DIGITS { $$ = $1; } 336 | { $$ = ""; } 337 ; 338 339 opt_id: ID { $$ = $1; } 340 | { $$ = ""; } 341 ; 342 343 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); } 344 ; 345 VMA: DIGITS { $$ = (bfd_vma) strtoull ($1, 0, 0); } 346 347 %% 348 349 /***************************************************************************** 350 API 351 *****************************************************************************/ 352 353 static FILE *the_file; 354 static const char *def_filename; 355 static int linenumber; 356 static def_file *def; 357 static int saw_newline; 358 359 struct directive 360 { 361 struct directive *next; 362 char *name; 363 int len; 364 }; 365 366 static struct directive *directives = 0; 367 368 def_file * 369 def_file_empty (void) 370 { 371 def_file *rv = xmalloc (sizeof (def_file)); 372 memset (rv, 0, sizeof (def_file)); 373 rv->is_dll = -1; 374 rv->base_address = (bfd_vma) -1; 375 rv->stack_reserve = rv->stack_commit = -1; 376 rv->heap_reserve = rv->heap_commit = -1; 377 rv->version_major = rv->version_minor = -1; 378 return rv; 379 } 380 381 def_file * 382 def_file_parse (const char *filename, def_file *add_to) 383 { 384 struct directive *d; 385 386 the_file = fopen (filename, "r"); 387 def_filename = filename; 388 linenumber = 1; 389 if (!the_file) 390 { 391 perror (filename); 392 return 0; 393 } 394 if (add_to) 395 { 396 def = add_to; 397 } 398 else 399 { 400 def = def_file_empty (); 401 } 402 403 saw_newline = 1; 404 if (def_parse ()) 405 { 406 def_file_free (def); 407 fclose (the_file); 408 def_pool_free (); 409 return 0; 410 } 411 412 fclose (the_file); 413 414 while ((d = directives) != NULL) 415 { 416 #if TRACE 417 printf ("Adding directive %08x `%s'\n", d->name, d->name); 418 #endif 419 def_file_add_directive (def, d->name, d->len); 420 directives = d->next; 421 free (d->name); 422 free (d); 423 } 424 def_pool_free (); 425 426 return def; 427 } 428 429 void 430 def_file_free (def_file *fdef) 431 { 432 int i; 433 434 if (!fdef) 435 return; 436 if (fdef->name) 437 free (fdef->name); 438 if (fdef->description) 439 free (fdef->description); 440 441 if (fdef->section_defs) 442 { 443 for (i = 0; i < fdef->num_section_defs; i++) 444 { 445 if (fdef->section_defs[i].name) 446 free (fdef->section_defs[i].name); 447 if (fdef->section_defs[i].class) 448 free (fdef->section_defs[i].class); 449 } 450 free (fdef->section_defs); 451 } 452 453 if (fdef->exports) 454 { 455 for (i = 0; i < fdef->num_exports; i++) 456 { 457 if (fdef->exports[i].internal_name 458 && fdef->exports[i].internal_name != fdef->exports[i].name) 459 free (fdef->exports[i].internal_name); 460 if (fdef->exports[i].name) 461 free (fdef->exports[i].name); 462 if (fdef->exports[i].its_name) 463 free (fdef->exports[i].its_name); 464 } 465 free (fdef->exports); 466 } 467 468 if (fdef->imports) 469 { 470 for (i = 0; i < fdef->num_imports; i++) 471 { 472 if (fdef->imports[i].internal_name 473 && fdef->imports[i].internal_name != fdef->imports[i].name) 474 free (fdef->imports[i].internal_name); 475 if (fdef->imports[i].name) 476 free (fdef->imports[i].name); 477 if (fdef->imports[i].its_name) 478 free (fdef->imports[i].its_name); 479 } 480 free (fdef->imports); 481 } 482 483 while (fdef->modules) 484 { 485 def_file_module *m = fdef->modules; 486 487 fdef->modules = fdef->modules->next; 488 free (m); 489 } 490 491 while (fdef->aligncomms) 492 { 493 def_file_aligncomm *c = fdef->aligncomms; 494 495 fdef->aligncomms = fdef->aligncomms->next; 496 free (c->symbol_name); 497 free (c); 498 } 499 500 free (fdef); 501 } 502 503 #ifdef DEF_FILE_PRINT 504 void 505 def_file_print (FILE *file, def_file *fdef) 506 { 507 int i; 508 509 fprintf (file, ">>>> def_file at 0x%08x\n", fdef); 510 if (fdef->name) 511 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)"); 512 if (fdef->is_dll != -1) 513 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no"); 514 if (fdef->base_address != (bfd_vma) -1) 515 { 516 fprintf (file, " base address: 0x"); 517 fprintf_vma (file, fdef->base_address); 518 fprintf (file, "\n"); 519 } 520 if (fdef->description) 521 fprintf (file, " description: `%s'\n", fdef->description); 522 if (fdef->stack_reserve != -1) 523 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve); 524 if (fdef->stack_commit != -1) 525 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit); 526 if (fdef->heap_reserve != -1) 527 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve); 528 if (fdef->heap_commit != -1) 529 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit); 530 531 if (fdef->num_section_defs > 0) 532 { 533 fprintf (file, " section defs:\n"); 534 535 for (i = 0; i < fdef->num_section_defs; i++) 536 { 537 fprintf (file, " name: `%s', class: `%s', flags:", 538 fdef->section_defs[i].name, fdef->section_defs[i].class); 539 if (fdef->section_defs[i].flag_read) 540 fprintf (file, " R"); 541 if (fdef->section_defs[i].flag_write) 542 fprintf (file, " W"); 543 if (fdef->section_defs[i].flag_execute) 544 fprintf (file, " X"); 545 if (fdef->section_defs[i].flag_shared) 546 fprintf (file, " S"); 547 fprintf (file, "\n"); 548 } 549 } 550 551 if (fdef->num_exports > 0) 552 { 553 fprintf (file, " exports:\n"); 554 555 for (i = 0; i < fdef->num_exports; i++) 556 { 557 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:", 558 fdef->exports[i].name, fdef->exports[i].internal_name, 559 fdef->exports[i].ordinal); 560 if (fdef->exports[i].flag_private) 561 fprintf (file, " P"); 562 if (fdef->exports[i].flag_constant) 563 fprintf (file, " C"); 564 if (fdef->exports[i].flag_noname) 565 fprintf (file, " N"); 566 if (fdef->exports[i].flag_data) 567 fprintf (file, " D"); 568 fprintf (file, "\n"); 569 } 570 } 571 572 if (fdef->num_imports > 0) 573 { 574 fprintf (file, " imports:\n"); 575 576 for (i = 0; i < fdef->num_imports; i++) 577 { 578 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n", 579 fdef->imports[i].internal_name, 580 fdef->imports[i].module, 581 fdef->imports[i].name, 582 fdef->imports[i].ordinal); 583 } 584 } 585 586 if (fdef->version_major != -1) 587 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor); 588 589 fprintf (file, "<<<< def_file at 0x%08x\n", fdef); 590 } 591 #endif 592 593 /* Helper routine to check for identity of string pointers, 594 which might be NULL. */ 595 596 static int 597 are_names_equal (const char *s1, const char *s2) 598 { 599 if (!s1 && !s2) 600 return 0; 601 if (!s1 || !s2) 602 return (!s1 ? -1 : 1); 603 return strcmp (s1, s2); 604 } 605 606 static int 607 cmp_export_elem (const def_file_export *e, const char *ex_name, 608 const char *in_name, const char *its_name, 609 int ord) 610 { 611 int r; 612 613 if ((r = are_names_equal (ex_name, e->name)) != 0) 614 return r; 615 if ((r = are_names_equal (in_name, e->internal_name)) != 0) 616 return r; 617 if ((r = are_names_equal (its_name, e->its_name)) != 0) 618 return r; 619 return (ord - e->ordinal); 620 } 621 622 /* Search the position of the identical element, or returns the position 623 of the next higher element. If last valid element is smaller, then MAX 624 is returned. */ 625 626 static int 627 find_export_in_list (def_file_export *b, int max, 628 const char *ex_name, const char *in_name, 629 const char *its_name, int ord, int *is_ident) 630 { 631 int e, l, r, p; 632 633 *is_ident = 0; 634 if (!max) 635 return 0; 636 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0) 637 { 638 if (!e) 639 *is_ident = 1; 640 return 0; 641 } 642 if (max == 1) 643 return 1; 644 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0) 645 return max; 646 else if (!e || max == 2) 647 { 648 if (!e) 649 *is_ident = 1; 650 return max - 1; 651 } 652 l = 0; r = max - 1; 653 while (l < r) 654 { 655 p = (l + r) / 2; 656 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord); 657 if (!e) 658 { 659 *is_ident = 1; 660 return p; 661 } 662 else if (e < 0) 663 r = p - 1; 664 else if (e > 0) 665 l = p + 1; 666 } 667 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0) 668 ++l; 669 else if (!e) 670 *is_ident = 1; 671 return l; 672 } 673 674 def_file_export * 675 def_file_add_export (def_file *fdef, 676 const char *external_name, 677 const char *internal_name, 678 int ordinal, 679 const char *its_name, 680 int *is_dup) 681 { 682 def_file_export *e; 683 int pos; 684 int max_exports = ROUND_UP(fdef->num_exports, 32); 685 686 if (internal_name && !external_name) 687 external_name = internal_name; 688 if (external_name && !internal_name) 689 internal_name = external_name; 690 691 /* We need to avoid duplicates. */ 692 *is_dup = 0; 693 pos = find_export_in_list (fdef->exports, fdef->num_exports, 694 external_name, internal_name, 695 its_name, ordinal, is_dup); 696 697 if (*is_dup != 0) 698 return (fdef->exports + pos); 699 700 if (fdef->num_exports >= max_exports) 701 { 702 max_exports = ROUND_UP(fdef->num_exports + 1, 32); 703 if (fdef->exports) 704 fdef->exports = xrealloc (fdef->exports, 705 max_exports * sizeof (def_file_export)); 706 else 707 fdef->exports = xmalloc (max_exports * sizeof (def_file_export)); 708 } 709 710 e = fdef->exports + pos; 711 if (pos != fdef->num_exports) 712 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos))); 713 memset (e, 0, sizeof (def_file_export)); 714 e->name = xstrdup (external_name); 715 e->internal_name = xstrdup (internal_name); 716 e->its_name = (its_name ? xstrdup (its_name) : NULL); 717 e->ordinal = ordinal; 718 fdef->num_exports++; 719 return e; 720 } 721 722 def_file_module * 723 def_get_module (def_file *fdef, const char *name) 724 { 725 def_file_module *s; 726 727 for (s = fdef->modules; s; s = s->next) 728 if (strcmp (s->name, name) == 0) 729 return s; 730 731 return NULL; 732 } 733 734 static def_file_module * 735 def_stash_module (def_file *fdef, const char *name) 736 { 737 def_file_module *s; 738 739 if ((s = def_get_module (fdef, name)) != NULL) 740 return s; 741 s = xmalloc (sizeof (def_file_module) + strlen (name)); 742 s->next = fdef->modules; 743 fdef->modules = s; 744 s->user_data = 0; 745 strcpy (s->name, name); 746 return s; 747 } 748 749 static int 750 cmp_import_elem (const def_file_import *e, const char *ex_name, 751 const char *in_name, const char *module, 752 int ord) 753 { 754 int r; 755 756 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL)))) 757 return r; 758 if ((r = are_names_equal (ex_name, e->name)) != 0) 759 return r; 760 if ((r = are_names_equal (in_name, e->internal_name)) != 0) 761 return r; 762 if (ord != e->ordinal) 763 return (ord < e->ordinal ? -1 : 1); 764 return 0; 765 } 766 767 /* Search the position of the identical element, or returns the position 768 of the next higher element. If last valid element is smaller, then MAX 769 is returned. */ 770 771 static int 772 find_import_in_list (def_file_import *b, int max, 773 const char *ex_name, const char *in_name, 774 const char *module, int ord, int *is_ident) 775 { 776 int e, l, r, p; 777 778 *is_ident = 0; 779 if (!max) 780 return 0; 781 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0) 782 { 783 if (!e) 784 *is_ident = 1; 785 return 0; 786 } 787 if (max == 1) 788 return 1; 789 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0) 790 return max; 791 else if (!e || max == 2) 792 { 793 if (!e) 794 *is_ident = 1; 795 return max - 1; 796 } 797 l = 0; r = max - 1; 798 while (l < r) 799 { 800 p = (l + r) / 2; 801 e = cmp_import_elem (b + p, ex_name, in_name, module, ord); 802 if (!e) 803 { 804 *is_ident = 1; 805 return p; 806 } 807 else if (e < 0) 808 r = p - 1; 809 else if (e > 0) 810 l = p + 1; 811 } 812 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0) 813 ++l; 814 else if (!e) 815 *is_ident = 1; 816 return l; 817 } 818 819 def_file_import * 820 def_file_add_import (def_file *fdef, 821 const char *name, 822 const char *module, 823 int ordinal, 824 const char *internal_name, 825 const char *its_name, 826 int *is_dup) 827 { 828 def_file_import *i; 829 int pos; 830 int max_imports = ROUND_UP (fdef->num_imports, 16); 831 832 /* We need to avoid here duplicates. */ 833 *is_dup = 0; 834 pos = find_import_in_list (fdef->imports, fdef->num_imports, 835 name, 836 (!internal_name ? name : internal_name), 837 module, ordinal, is_dup); 838 if (*is_dup != 0) 839 return fdef->imports + pos; 840 841 if (fdef->num_imports >= max_imports) 842 { 843 max_imports = ROUND_UP (fdef->num_imports+1, 16); 844 845 if (fdef->imports) 846 fdef->imports = xrealloc (fdef->imports, 847 max_imports * sizeof (def_file_import)); 848 else 849 fdef->imports = xmalloc (max_imports * sizeof (def_file_import)); 850 } 851 i = fdef->imports + pos; 852 if (pos != fdef->num_imports) 853 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos))); 854 memset (i, 0, sizeof (def_file_import)); 855 if (name) 856 i->name = xstrdup (name); 857 if (module) 858 i->module = def_stash_module (fdef, module); 859 i->ordinal = ordinal; 860 if (internal_name) 861 i->internal_name = xstrdup (internal_name); 862 else 863 i->internal_name = i->name; 864 i->its_name = (its_name ? xstrdup (its_name) : NULL); 865 fdef->num_imports++; 866 867 return i; 868 } 869 870 struct 871 { 872 char *param; 873 int token; 874 } 875 diropts[] = 876 { 877 { "-heap", HEAPSIZE }, 878 { "-stack", STACKSIZE_K }, 879 { "-attr", SECTIONS }, 880 { "-export", EXPORTS }, 881 { "-aligncomm", ALIGNCOMM }, 882 { 0, 0 } 883 }; 884 885 void 886 def_file_add_directive (def_file *my_def, const char *param, int len) 887 { 888 def_file *save_def = def; 889 const char *pend = param + len; 890 char * tend = (char *) param; 891 int i; 892 893 def = my_def; 894 895 while (param < pend) 896 { 897 while (param < pend 898 && (ISSPACE (*param) || *param == '\n' || *param == 0)) 899 param++; 900 901 if (param == pend) 902 break; 903 904 /* Scan forward until we encounter any of: 905 - the end of the buffer 906 - the start of a new option 907 - a newline seperating options 908 - a NUL seperating options. */ 909 for (tend = (char *) (param + 1); 910 (tend < pend 911 && !(ISSPACE (tend[-1]) && *tend == '-') 912 && *tend != '\n' && *tend != 0); 913 tend++) 914 ; 915 916 for (i = 0; diropts[i].param; i++) 917 { 918 len = strlen (diropts[i].param); 919 920 if (tend - param >= len 921 && strncmp (param, diropts[i].param, len) == 0 922 && (param[len] == ':' || param[len] == ' ')) 923 { 924 lex_parse_string_end = tend; 925 lex_parse_string = param + len + 1; 926 lex_forced_token = diropts[i].token; 927 saw_newline = 0; 928 if (def_parse ()) 929 continue; 930 break; 931 } 932 } 933 934 if (!diropts[i].param) 935 { 936 if (tend < pend) 937 { 938 char saved; 939 940 saved = * tend; 941 * tend = 0; 942 /* xgettext:c-format */ 943 einfo (_("Warning: .drectve `%s' unrecognized\n"), param); 944 * tend = saved; 945 } 946 else 947 { 948 einfo (_("Warning: corrupt .drectve at end of def file\n")); 949 } 950 } 951 952 lex_parse_string = 0; 953 param = tend; 954 } 955 956 def = save_def; 957 def_pool_free (); 958 } 959 960 /* Parser Callbacks. */ 961 962 static void 963 def_image_name (const char *name, bfd_vma base, int is_dll) 964 { 965 /* If a LIBRARY or NAME statement is specified without a name, there is nothing 966 to do here. We retain the output filename specified on command line. */ 967 if (*name) 968 { 969 const char* image_name = lbasename (name); 970 971 if (image_name != name) 972 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n", 973 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME", 974 name); 975 if (def->name) 976 free (def->name); 977 /* Append the default suffix, if none specified. */ 978 if (strchr (image_name, '.') == 0) 979 { 980 const char * suffix = is_dll ? ".dll" : ".exe"; 981 982 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1); 983 sprintf (def->name, "%s%s", image_name, suffix); 984 } 985 else 986 def->name = xstrdup (image_name); 987 } 988 989 /* Honor a BASE address statement, even if LIBRARY string is empty. */ 990 def->base_address = base; 991 def->is_dll = is_dll; 992 } 993 994 static void 995 def_description (const char *text) 996 { 997 int len = def->description ? strlen (def->description) : 0; 998 999 len += strlen (text) + 1; 1000 if (def->description) 1001 { 1002 def->description = xrealloc (def->description, len); 1003 strcat (def->description, text); 1004 } 1005 else 1006 { 1007 def->description = xmalloc (len); 1008 strcpy (def->description, text); 1009 } 1010 } 1011 1012 static void 1013 def_stacksize (int reserve, int commit) 1014 { 1015 def->stack_reserve = reserve; 1016 def->stack_commit = commit; 1017 } 1018 1019 static void 1020 def_heapsize (int reserve, int commit) 1021 { 1022 def->heap_reserve = reserve; 1023 def->heap_commit = commit; 1024 } 1025 1026 static void 1027 def_section (const char *name, int attr) 1028 { 1029 def_file_section *s; 1030 int max_sections = ROUND_UP (def->num_section_defs, 4); 1031 1032 if (def->num_section_defs >= max_sections) 1033 { 1034 max_sections = ROUND_UP (def->num_section_defs+1, 4); 1035 1036 if (def->section_defs) 1037 def->section_defs = xrealloc (def->section_defs, 1038 max_sections * sizeof (def_file_import)); 1039 else 1040 def->section_defs = xmalloc (max_sections * sizeof (def_file_import)); 1041 } 1042 s = def->section_defs + def->num_section_defs; 1043 memset (s, 0, sizeof (def_file_section)); 1044 s->name = xstrdup (name); 1045 if (attr & 1) 1046 s->flag_read = 1; 1047 if (attr & 2) 1048 s->flag_write = 1; 1049 if (attr & 4) 1050 s->flag_execute = 1; 1051 if (attr & 8) 1052 s->flag_shared = 1; 1053 1054 def->num_section_defs++; 1055 } 1056 1057 static void 1058 def_section_alt (const char *name, const char *attr) 1059 { 1060 int aval = 0; 1061 1062 for (; *attr; attr++) 1063 { 1064 switch (*attr) 1065 { 1066 case 'R': 1067 case 'r': 1068 aval |= 1; 1069 break; 1070 case 'W': 1071 case 'w': 1072 aval |= 2; 1073 break; 1074 case 'X': 1075 case 'x': 1076 aval |= 4; 1077 break; 1078 case 'S': 1079 case 's': 1080 aval |= 8; 1081 break; 1082 } 1083 } 1084 def_section (name, aval); 1085 } 1086 1087 static void 1088 def_exports (const char *external_name, 1089 const char *internal_name, 1090 int ordinal, 1091 int flags, 1092 const char *its_name) 1093 { 1094 def_file_export *dfe; 1095 int is_dup = 0; 1096 1097 if (!internal_name && external_name) 1098 internal_name = external_name; 1099 #if TRACE 1100 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name); 1101 #endif 1102 1103 dfe = def_file_add_export (def, external_name, internal_name, ordinal, 1104 its_name, &is_dup); 1105 1106 /* We might check here for flag redefinition and warn. For now we 1107 ignore duplicates silently. */ 1108 if (is_dup) 1109 return; 1110 1111 if (flags & 1) 1112 dfe->flag_noname = 1; 1113 if (flags & 2) 1114 dfe->flag_constant = 1; 1115 if (flags & 4) 1116 dfe->flag_data = 1; 1117 if (flags & 8) 1118 dfe->flag_private = 1; 1119 } 1120 1121 static void 1122 def_import (const char *internal_name, 1123 const char *module, 1124 const char *dllext, 1125 const char *name, 1126 int ordinal, 1127 const char *its_name) 1128 { 1129 char *buf = 0; 1130 const char *ext = dllext ? dllext : "dll"; 1131 int is_dup = 0; 1132 1133 buf = xmalloc (strlen (module) + strlen (ext) + 2); 1134 sprintf (buf, "%s.%s", module, ext); 1135 module = buf; 1136 1137 def_file_add_import (def, name, module, ordinal, internal_name, its_name, 1138 &is_dup); 1139 free (buf); 1140 } 1141 1142 static void 1143 def_version (int major, int minor) 1144 { 1145 def->version_major = major; 1146 def->version_minor = minor; 1147 } 1148 1149 static void 1150 def_directive (char *str) 1151 { 1152 struct directive *d = xmalloc (sizeof (struct directive)); 1153 1154 d->next = directives; 1155 directives = d; 1156 d->name = xstrdup (str); 1157 d->len = strlen (str); 1158 } 1159 1160 static void 1161 def_aligncomm (char *str, int align) 1162 { 1163 def_file_aligncomm *c, *p; 1164 1165 p = NULL; 1166 c = def->aligncomms; 1167 while (c != NULL) 1168 { 1169 int e = strcmp (c->symbol_name, str); 1170 if (!e) 1171 { 1172 /* Not sure if we want to allow here duplicates with 1173 different alignments, but for now we keep them. */ 1174 e = (int) c->alignment - align; 1175 if (!e) 1176 return; 1177 } 1178 if (e > 0) 1179 break; 1180 c = (p = c)->next; 1181 } 1182 1183 c = xmalloc (sizeof (def_file_aligncomm)); 1184 c->symbol_name = xstrdup (str); 1185 c->alignment = (unsigned int) align; 1186 if (!p) 1187 { 1188 c->next = def->aligncomms; 1189 def->aligncomms = c; 1190 } 1191 else 1192 { 1193 c->next = p->next; 1194 p->next = c; 1195 } 1196 } 1197 1198 static int 1199 def_error (const char *err) 1200 { 1201 einfo ("%P: %s:%d: %s\n", 1202 def_filename ? def_filename : "<unknown-file>", linenumber, err); 1203 return 0; 1204 } 1205 1206 1207 /* Lexical Scanner. */ 1208 1209 #undef TRACE 1210 #define TRACE 0 1211 1212 /* Never freed, but always reused as needed, so no real leak. */ 1213 static char *buffer = 0; 1214 static int buflen = 0; 1215 static int bufptr = 0; 1216 1217 static void 1218 put_buf (char c) 1219 { 1220 if (bufptr == buflen) 1221 { 1222 buflen += 50; /* overly reasonable, eh? */ 1223 if (buffer) 1224 buffer = xrealloc (buffer, buflen + 1); 1225 else 1226 buffer = xmalloc (buflen + 1); 1227 } 1228 buffer[bufptr++] = c; 1229 buffer[bufptr] = 0; /* not optimal, but very convenient. */ 1230 } 1231 1232 static struct 1233 { 1234 char *name; 1235 int token; 1236 } 1237 tokens[] = 1238 { 1239 { "BASE", BASE }, 1240 { "CODE", CODE }, 1241 { "CONSTANT", CONSTANTU }, 1242 { "constant", CONSTANTL }, 1243 { "DATA", DATAU }, 1244 { "data", DATAL }, 1245 { "DESCRIPTION", DESCRIPTION }, 1246 { "DIRECTIVE", DIRECTIVE }, 1247 { "EXECUTE", EXECUTE }, 1248 { "EXPORTS", EXPORTS }, 1249 { "HEAPSIZE", HEAPSIZE }, 1250 { "IMPORTS", IMPORTS }, 1251 { "LIBRARY", LIBRARY }, 1252 { "NAME", NAME }, 1253 { "NONAME", NONAMEU }, 1254 { "noname", NONAMEL }, 1255 { "PRIVATE", PRIVATEU }, 1256 { "private", PRIVATEL }, 1257 { "READ", READ }, 1258 { "SECTIONS", SECTIONS }, 1259 { "SEGMENTS", SECTIONS }, 1260 { "SHARED", SHARED }, 1261 { "STACKSIZE", STACKSIZE_K }, 1262 { "VERSION", VERSIONK }, 1263 { "WRITE", WRITE }, 1264 { 0, 0 } 1265 }; 1266 1267 static int 1268 def_getc (void) 1269 { 1270 int rv; 1271 1272 if (lex_parse_string) 1273 { 1274 if (lex_parse_string >= lex_parse_string_end) 1275 rv = EOF; 1276 else 1277 rv = *lex_parse_string++; 1278 } 1279 else 1280 { 1281 rv = fgetc (the_file); 1282 } 1283 if (rv == '\n') 1284 saw_newline = 1; 1285 return rv; 1286 } 1287 1288 static int 1289 def_ungetc (int c) 1290 { 1291 if (lex_parse_string) 1292 { 1293 lex_parse_string--; 1294 return c; 1295 } 1296 else 1297 return ungetc (c, the_file); 1298 } 1299 1300 static int 1301 def_lex (void) 1302 { 1303 int c, i, q; 1304 1305 if (lex_forced_token) 1306 { 1307 i = lex_forced_token; 1308 lex_forced_token = 0; 1309 #if TRACE 1310 printf ("lex: forcing token %d\n", i); 1311 #endif 1312 return i; 1313 } 1314 1315 c = def_getc (); 1316 1317 /* Trim leading whitespace. */ 1318 while (c != EOF && (c == ' ' || c == '\t') && saw_newline) 1319 c = def_getc (); 1320 1321 if (c == EOF) 1322 { 1323 #if TRACE 1324 printf ("lex: EOF\n"); 1325 #endif 1326 return 0; 1327 } 1328 1329 if (saw_newline && c == ';') 1330 { 1331 do 1332 { 1333 c = def_getc (); 1334 } 1335 while (c != EOF && c != '\n'); 1336 if (c == '\n') 1337 return def_lex (); 1338 return 0; 1339 } 1340 1341 /* Must be something else. */ 1342 saw_newline = 0; 1343 1344 if (ISDIGIT (c)) 1345 { 1346 bufptr = 0; 1347 while (c != EOF && (ISXDIGIT (c) || (c == 'x'))) 1348 { 1349 put_buf (c); 1350 c = def_getc (); 1351 } 1352 if (c != EOF) 1353 def_ungetc (c); 1354 yylval.digits = def_pool_strdup (buffer); 1355 #if TRACE 1356 printf ("lex: `%s' returns DIGITS\n", buffer); 1357 #endif 1358 return DIGITS; 1359 } 1360 1361 if (ISALPHA (c) || strchr ("$:-_?@", c)) 1362 { 1363 bufptr = 0; 1364 q = c; 1365 put_buf (c); 1366 c = def_getc (); 1367 1368 if (q == '@') 1369 { 1370 if (ISBLANK (c) ) /* '@' followed by whitespace. */ 1371 return (q); 1372 else if (ISDIGIT (c)) /* '@' followed by digit. */ 1373 { 1374 def_ungetc (c); 1375 return (q); 1376 } 1377 #if TRACE 1378 printf ("lex: @ returns itself\n"); 1379 #endif 1380 } 1381 1382 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c))) 1383 { 1384 put_buf (c); 1385 c = def_getc (); 1386 } 1387 if (c != EOF) 1388 def_ungetc (c); 1389 if (ISALPHA (q)) /* Check for tokens. */ 1390 { 1391 for (i = 0; tokens[i].name; i++) 1392 if (strcmp (tokens[i].name, buffer) == 0) 1393 { 1394 #if TRACE 1395 printf ("lex: `%s' is a string token\n", buffer); 1396 #endif 1397 return tokens[i].token; 1398 } 1399 } 1400 #if TRACE 1401 printf ("lex: `%s' returns ID\n", buffer); 1402 #endif 1403 yylval.id = def_pool_strdup (buffer); 1404 return ID; 1405 } 1406 1407 if (c == '\'' || c == '"') 1408 { 1409 q = c; 1410 c = def_getc (); 1411 bufptr = 0; 1412 1413 while (c != EOF && c != q) 1414 { 1415 put_buf (c); 1416 c = def_getc (); 1417 } 1418 yylval.id = def_pool_strdup (buffer); 1419 #if TRACE 1420 printf ("lex: `%s' returns ID\n", buffer); 1421 #endif 1422 return ID; 1423 } 1424 1425 if ( c == '=') 1426 { 1427 c = def_getc (); 1428 if (c == '=') 1429 { 1430 #if TRACE 1431 printf ("lex: `==' returns EQUAL\n"); 1432 #endif 1433 return EQUAL; 1434 } 1435 def_ungetc (c); 1436 #if TRACE 1437 printf ("lex: `=' returns itself\n"); 1438 #endif 1439 return '='; 1440 } 1441 if (c == '.' || c == ',') 1442 { 1443 #if TRACE 1444 printf ("lex: `%c' returns itself\n", c); 1445 #endif 1446 return c; 1447 } 1448 1449 if (c == '\n') 1450 { 1451 linenumber++; 1452 saw_newline = 1; 1453 } 1454 1455 /*printf ("lex: 0x%02x ignored\n", c); */ 1456 return def_lex (); 1457 } 1458 1459 static char * 1460 def_pool_alloc (size_t sz) 1461 { 1462 def_pool_str *e; 1463 1464 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz); 1465 e->next = pool_strs; 1466 pool_strs = e; 1467 return e->data; 1468 } 1469 1470 static char * 1471 def_pool_strdup (const char *str) 1472 { 1473 char *s; 1474 size_t len; 1475 if (!str) 1476 return NULL; 1477 len = strlen (str) + 1; 1478 s = def_pool_alloc (len); 1479 memcpy (s, str, len); 1480 return s; 1481 } 1482 1483 static void 1484 def_pool_free (void) 1485 { 1486 def_pool_str *p; 1487 while ((p = pool_strs) != NULL) 1488 { 1489 pool_strs = p->next; 1490 free (p); 1491 } 1492 } 1493