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