dlltool.c revision 38889
1/* dlltool.c -- tool to generate stuff for PE style DLLs 2 Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. */ 20 21 22/* 23 This program allows you to build the files necessary to create 24 DLLs to run on a system which understands PE format image files. 25 (eg, Windows NT) 26 27 See "Peering Inside the PE: A Tour of the Win32 Portable Executable 28 File Format", MSJ 1994, Volume 9 for more information. 29 Also see "Microsoft Portable Executable and Common Object File Format, 30 Specification 4.1" for more information. 31 32 A DLL contains an export table which contains the information 33 which the runtime loader needs to tie up references from a 34 referencing program. 35 36 The export table is generated by this program by reading 37 in a .DEF file or scanning the .a and .o files which will be in the 38 DLL. A .o file can contain information in special ".drectve" sections 39 with export information. 40 41 A DEF file contains any number of the following commands: 42 43 44 NAME <name> [ , <base> ] 45 The result is going to be <name>.EXE 46 47 LIBRARY <name> [ , <base> ] 48 The result is going to be <name>.DLL 49 50 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) * 51 Declares name1 as an exported symbol from the 52 DLL, with optional ordinal number <integer> 53 54 IMPORTS ( [ <name> = ] <name> . <name> ) * 55 Ignored for compatibility 56 57 DESCRIPTION <string> 58 Puts <string> into output .exp file in the .rdata section 59 60 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ] 61 Generates --stack|--heap <number-reserve>,<number-commit> 62 in the output .drectve section. The linker will 63 see this and act upon it. 64 65 [CODE|DATA] <attr>+ 66 SECTIONS ( <sectionname> <attr>+ )* 67 <attr> = READ | WRITE | EXECUTE | SHARED 68 Generates --attr <sectionname> <attr> in the output 69 .drectve section. The linker will see this and act 70 upon it. 71 72 73 A -export:<name> in a .drectve section in an input .o or .a 74 file to this program is equivalent to a EXPORTS <name> 75 in a .DEF file. 76 77 78 79 The program generates output files with the prefix supplied 80 on the command line, or in the def file, or taken from the first 81 supplied argument. 82 83 The .exp.s file contains the information necessary to export 84 the routines in the DLL. The .lib.s file contains the information 85 necessary to use the DLL's routines from a referencing program. 86 87 88 89 Example: 90 91 file1.c: 92 asm (".section .drectve"); 93 asm (".ascii \"-export:adef\""); 94 95 adef(char *s) 96 { 97 printf("hello from the dll %s\n",s); 98 } 99 100 bdef(char *s) 101 { 102 printf("hello from the dll and the other entry point %s\n",s); 103 } 104 105 file2.c: 106 asm (".section .drectve"); 107 asm (".ascii \"-export:cdef\""); 108 asm (".ascii \"-export:ddef\""); 109 cdef(char *s) 110 { 111 printf("hello from the dll %s\n",s); 112 } 113 114 ddef(char *s) 115 { 116 printf("hello from the dll and the other entry point %s\n",s); 117 } 118 119 printf() 120 { 121 return 9; 122 } 123 124 main.c 125 126 main() 127 { 128 cdef(); 129 } 130 131 thedll.def 132 133 LIBRARY thedll 134 HEAPSIZE 0x40000, 0x2000 135 EXPORTS bdef @ 20 136 cdef @ 30 NONAME 137 138 SECTIONS donkey READ WRITE 139 aardvark EXECUTE 140 141 142 # compile up the parts of the dll 143 144 gcc -c file1.c 145 gcc -c file2.c 146 147 # put them in a library (you don't have to, you 148 # could name all the .os on the dlltool line) 149 150 ar qcv thedll.in file1.o file2.o 151 ranlib thedll.in 152 153 # run this tool over the library and the def file 154 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a 155 156 # build the dll with the library with file1.o, file2.o and the export table 157 ld -o thedll.dll thedll.o thedll.in 158 159 # build the mainline 160 gcc -c themain.c 161 162 # link the executable with the import library 163 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a 164 165 */ 166 167/* .idata section description 168 169 The .idata section is the import table. It is a collection of several 170 subsections used to keep the pieces for each dll together: .idata$[234567]. 171 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc. 172 173 .idata$2 = Import Directory Table 174 = array of IMAGE_IMPORT_DESCRIPTOR's. 175 176 DWORD Characteristics; - pointer to .idata$4 177 DWORD TimeDateStamp; - currently always 0 178 DWORD ForwarderChain; - currently always 0 179 DWORD Name; - pointer to dll's name 180 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5 181 182 .idata$3 = null terminating entry for .idata$2. 183 184 .idata$4 = Import Lookup Table 185 = array of array of pointers to hint name table. 186 There is one for each dll being imported from, and each dll's set is 187 terminated by a trailing NULL. 188 189 .idata$5 = Import Address Table 190 = array of array of pointers to hint name table. 191 There is one for each dll being imported from, and each dll's set is 192 terminated by a trailing NULL. 193 Initially, this table is identical to the Import Lookup Table. However, 194 at load time, the loader overwrites the entries with the address of the 195 function. 196 197 .idata$6 = Hint Name Table 198 = Array of { short, asciz } entries, one for each imported function. 199 The `short' is the function's ordinal number. 200 201 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc) 202*/ 203 204/* AIX requires this to be the first thing in the file. */ 205#ifndef __GNUC__ 206# ifdef _AIX 207 #pragma alloca 208#endif 209#endif 210 211#define show_allnames 0 212 213#define PAGE_SIZE 4096 214#define PAGE_MASK (-PAGE_SIZE) 215#include "bfd.h" 216#include "libiberty.h" 217#include "bucomm.h" 218#include "getopt.h" 219#include "demangle.h" 220#include "dlltool.h" 221 222#include <ctype.h> 223#include <time.h> 224 225#ifdef HAVE_SYS_WAIT_H 226#include <sys/wait.h> 227#else /* ! HAVE_SYS_WAIT_H */ 228#if ! defined (_WIN32) || defined (__CYGWIN32__) 229#ifndef WIFEXITED 230#define WIFEXITED(w) (((w)&0377) == 0) 231#endif 232#ifndef WIFSIGNALED 233#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) 234#endif 235#ifndef WTERMSIG 236#define WTERMSIG(w) ((w) & 0177) 237#endif 238#ifndef WEXITSTATUS 239#define WEXITSTATUS(w) (((w) >> 8) & 0377) 240#endif 241#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 242#ifndef WIFEXITED 243#define WIFEXITED(w) (((w) & 0xff) == 0) 244#endif 245#ifndef WIFSIGNALED 246#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 247#endif 248#ifndef WTERMSIG 249#define WTERMSIG(w) ((w) & 0x7f) 250#endif 251#ifndef WEXITSTATUS 252#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 253#endif 254#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 255#endif /* ! HAVE_SYS_WAIT_H */ 256 257static char *as_name = "as"; 258 259static int no_idata4; 260static int no_idata5; 261static char *exp_name; 262static char *imp_name; 263static char *head_label; 264static char *imp_name_lab; 265static char *dll_name; 266 267static int add_indirect = 0; 268static int add_underscore = 0; 269static int dontdeltemps = 0; 270 271static char *def_file; 272 273static char *program_name; 274 275static int machine; 276static int killat; 277static int verbose; 278static FILE *output_def; 279static FILE *base_file; 280 281#ifdef DLLTOOL_ARM 282static const char *mname = "arm"; 283#endif 284 285#ifdef DLLTOOL_I386 286static const char *mname = "i386"; 287#endif 288 289#ifdef DLLTOOL_PPC 290static const char *mname = "ppc"; 291#endif 292 293#define PATHMAX 250 /* What's the right name for this ? */ 294 295/* This bit of assemly does jmp * .... 296s set how_jtab_roff to mark where the 32bit abs branch should go */ 297static const unsigned char i386_jtab[] = 298{ 299 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 300}; 301 302static const unsigned char arm_jtab[] = 303{ 304 0x00, 0xc0, 0x9f, 0xe5, 305 0x00, 0xf0, 0x9c, 0xe5, 306 0, 0, 0, 0 307}; 308 309/* This is the glue sequence for PowerPC PE. There is a */ 310/* tocrel16-tocdefn reloc against the first instruction. */ 311/* We also need a IMGLUE reloc against the glue function */ 312/* to restore the toc saved by the third instruction in */ 313/* the glue. */ 314static const unsigned char ppc_jtab[] = 315{ 316 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */ 317 /* Reloc TOCREL16 __imp_xxx */ 318 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */ 319 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */ 320 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */ 321 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */ 322 0x20, 0x04, 0x80, 0x4E /* bctr */ 323}; 324 325#ifdef DLLTOOL_PPC 326/* the glue instruction, picks up the toc from the stw in */ 327/* the above code: "lwz r2,4(r1)" */ 328static bfd_vma ppc_glue_insn = 0x80410004; 329#endif 330 331static char outfile[PATHMAX]; 332 333struct mac 334 { 335 const char *type; 336 const char *how_byte; 337 const char *how_short; 338 const char *how_long; 339 const char *how_asciz; 340 const char *how_comment; 341 const char *how_jump; 342 const char *how_global; 343 const char *how_space; 344 const char *how_align_short; 345 const char *how_align_long; 346 const char *how_bfd_target; 347 enum bfd_architecture how_bfd_arch; 348 const unsigned char *how_jtab; 349 int how_jtab_size; /* size of the jtab entry */ 350 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */ 351 }; 352 353static const struct mac mtable[] = 354{ 355 { 356#define MARM 0 357 "arm", ".byte", ".short", ".long", ".asciz", "@", 358 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 359 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm, 360 arm_jtab, sizeof(arm_jtab),8 361 } 362 , 363 { 364#define M386 1 365 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386, 366 i386_jtab,sizeof(i386_jtab),2, 367 } 368 , 369 { 370#define MPPC 2 371 "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc, 372 ppc_jtab,sizeof(ppc_jtab),0, 373 } 374 , 375{ 0} 376}; 377 378typedef struct dlist 379{ 380 char *text; 381 struct dlist *next; 382} 383dlist_type; 384 385typedef struct export 386 { 387 const char *name; 388 const char *internal_name; 389 int ordinal; 390 int constant; 391 int noname; 392 int data; 393 int hint; 394 struct export *next; 395 } 396export_type; 397 398static const char *rvaafter PARAMS ((int)); 399static const char *rvabefore PARAMS ((int)); 400static const char *asm_prefix PARAMS ((int)); 401static void run PARAMS ((const char *, char *)); 402static void basenames PARAMS ((bfd *)); 403static void scan_open_obj_file PARAMS ((bfd *)); 404static void scan_obj_file PARAMS ((const char *)); 405static void dump_def_info PARAMS ((FILE *)); 406static int sfunc PARAMS ((const void *, const void *)); 407static void flush_page PARAMS ((FILE *, long *, int, int)); 408static void gen_def_file PARAMS ((void)); 409static void gen_exp_file PARAMS ((void)); 410static const char *xlate PARAMS ((const char *)); 411static void dump_iat PARAMS ((FILE *, export_type *)); 412static char *make_label PARAMS ((const char *, const char *)); 413static bfd *make_one_lib_file PARAMS ((export_type *, int)); 414static bfd *make_head PARAMS ((void)); 415static bfd *make_tail PARAMS ((void)); 416static void gen_lib_file PARAMS ((void)); 417static int pfunc PARAMS ((const void *, const void *)); 418static int nfunc PARAMS ((const void *, const void *)); 419static void remove_null_names PARAMS ((export_type **)); 420static void dtab PARAMS ((export_type **)); 421static void process_duplicates PARAMS ((export_type **)); 422static void fill_ordinals PARAMS ((export_type **)); 423static int alphafunc PARAMS ((const void *, const void *)); 424static void mangle_defs PARAMS ((void)); 425static void usage PARAMS ((FILE *, int)); 426 427static const char * 428rvaafter (machine) 429 int machine; 430{ 431 switch (machine) 432 { 433 case MARM: 434 return ""; 435 case M386: 436 return ""; 437 case MPPC: 438 return ""; 439 } 440 return ""; 441} 442 443static const char * 444rvabefore (machine) 445 int machine; 446{ 447 switch (machine) 448 { 449 case MARM: 450 return ".rva\t"; 451 case M386: 452 return ".rva\t"; 453 case MPPC: 454 return ".rva\t"; 455 } 456 return ""; 457} 458 459static const char * 460asm_prefix (machine) 461 int machine; 462{ 463 switch (machine) 464 { 465 case MARM: 466 return ""; 467 case M386: 468 return "_"; 469 case MPPC: 470 return ""; 471 } 472 return ""; 473} 474 475#define ASM_BYTE mtable[machine].how_byte 476#define ASM_SHORT mtable[machine].how_short 477#define ASM_LONG mtable[machine].how_long 478#define ASM_TEXT mtable[machine].how_asciz 479#define ASM_C mtable[machine].how_comment 480#define ASM_JUMP mtable[machine].how_jump 481#define ASM_GLOBAL mtable[machine].how_global 482#define ASM_SPACE mtable[machine].how_space 483#define ASM_ALIGN_SHORT mtable[machine].how_align_short 484#define ASM_RVA_BEFORE rvabefore(machine) 485#define ASM_RVA_AFTER rvaafter(machine) 486#define ASM_PREFIX asm_prefix(machine) 487#define ASM_ALIGN_LONG mtable[machine].how_align_long 488#define HOW_BFD_TARGET 0 /* always default*/ 489#define HOW_BFD_ARCH mtable[machine].how_bfd_arch 490#define HOW_JTAB mtable[machine].how_jtab 491#define HOW_JTAB_SIZE mtable[machine].how_jtab_size 492#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff 493static char **oav; 494 495void 496process_def_file (name) 497 const char *name; 498{ 499 FILE *f = fopen (name, FOPEN_RT); 500 if (!f) 501 { 502 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name); 503 exit (1); 504 } 505 506 yyin = f; 507 508 yyparse (); 509} 510 511/**********************************************************************/ 512 513/* Communications with the parser */ 514 515static const char *d_name; /* Arg to NAME or LIBRARY */ 516static int d_nfuncs; /* Number of functions exported */ 517static int d_named_nfuncs; /* Number of named functions exported */ 518static int d_low_ord; /* Lowest ordinal index */ 519static int d_high_ord; /* Highest ordinal index */ 520static export_type *d_exports; /*list of exported functions */ 521static export_type **d_exports_lexically; /* vector of exported functions in alpha order */ 522static dlist_type *d_list; /* Descriptions */ 523static dlist_type *a_list; /* Stuff to go in directives */ 524 525static int d_is_dll; 526static int d_is_exe; 527 528int 529yyerror (err) 530 const char *err; 531{ 532 fprintf (stderr, "%s: Syntax error in def file %s:%d\n", 533 program_name, def_file, linenumber); 534 return 0; 535} 536 537void 538def_exports (name, internal_name, ordinal, noname, constant, data) 539 const char *name; 540 const char *internal_name; 541 int ordinal; 542 int noname; 543 int constant; 544 int data; 545{ 546 struct export *p = (struct export *) xmalloc (sizeof (*p)); 547 548 p->name = name; 549 p->internal_name = internal_name ? internal_name : name; 550 p->ordinal = ordinal; 551 p->constant = constant; 552 p->noname = noname; 553 p->data = data; 554 p->next = d_exports; 555 d_exports = p; 556 d_nfuncs++; 557} 558 559void 560def_name (name, base) 561 const char *name; 562 int base; 563{ 564 if (verbose) 565 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base); 566 if (d_is_dll) 567 { 568 fprintf (stderr, "Can't have LIBRARY and NAME\n"); 569 } 570 d_name = name; 571 d_is_exe = 1; 572} 573 574void 575def_library (name, base) 576 const char *name; 577 int base; 578{ 579 if (verbose) 580 printf ("%s: LIBRARY %s base %x\n", program_name, name, base); 581 if (d_is_exe) 582 { 583 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name); 584 } 585 d_name = name; 586 d_is_dll = 1; 587} 588 589void 590def_description (desc) 591 const char *desc; 592{ 593 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 594 d->text = xstrdup (desc); 595 d->next = d_list; 596 d_list = d; 597} 598 599void 600new_directive (dir) 601 char *dir; 602{ 603 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 604 d->text = xstrdup (dir); 605 d->next = a_list; 606 a_list = d; 607} 608 609void 610def_stacksize (reserve, commit) 611 int reserve; 612 int commit; 613{ 614 char b[200]; 615 if (commit > 0) 616 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); 617 else 618 sprintf (b, "-stack 0x%x ", reserve); 619 new_directive (xstrdup (b)); 620} 621 622void 623def_heapsize (reserve, commit) 624 int reserve; 625 int commit; 626{ 627 char b[200]; 628 if (commit > 0) 629 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); 630 else 631 sprintf (b, "-heap 0x%x ", reserve); 632 new_directive (xstrdup (b)); 633} 634 635void 636def_import (internal, module, entry) 637 const char *internal; 638 const char *module; 639 const char *entry; 640{ 641 if (verbose) 642 fprintf (stderr, "%s: IMPORTS are ignored", program_name); 643} 644 645void 646def_version (major, minor) 647 int major; 648 int minor; 649{ 650 printf ("VERSION %d.%d\n", major, minor); 651} 652 653void 654def_section (name, attr) 655 const char *name; 656 int attr; 657{ 658 char buf[200]; 659 char atts[5]; 660 char *d = atts; 661 if (attr & 1) 662 *d++ = 'R'; 663 664 if (attr & 2) 665 *d++ = 'W'; 666 if (attr & 4) 667 *d++ = 'X'; 668 if (attr & 8) 669 *d++ = 'S'; 670 *d++ = 0; 671 sprintf (buf, "-attr %s %s", name, atts); 672 new_directive (xstrdup (buf)); 673} 674 675void 676def_code (attr) 677 int attr; 678{ 679 680 def_section ("CODE", attr); 681} 682 683void 684def_data (attr) 685 int attr; 686{ 687 def_section ("DATA", attr); 688} 689 690/**********************************************************************/ 691 692static void 693run (what, args) 694 const char *what; 695 char *args; 696{ 697 char *s; 698 int pid, wait_status; 699 int i; 700 const char **argv; 701 char *errmsg_fmt, *errmsg_arg; 702 char *temp_base = choose_temp_base (); 703 704 if (verbose) 705 fprintf (stderr, "%s %s\n", what, args); 706 707 /* Count the args */ 708 i = 0; 709 for (s = args; *s; s++) 710 if (*s == ' ') 711 i++; 712 i++; 713 argv = alloca (sizeof (char *) * (i + 3)); 714 i = 0; 715 argv[i++] = what; 716 s = args; 717 while (1) 718 { 719 argv[i++] = s; 720 while (*s != ' ' && *s != 0) 721 s++; 722 if (*s == 0) 723 break; 724 *s++ = 0; 725 } 726 argv[i++] = NULL; 727 728 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 729 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 730 731 if (pid == -1) 732 { 733 int errno_val = errno; 734 735 fprintf (stderr, "%s: ", program_name); 736 fprintf (stderr, errmsg_fmt, errmsg_arg); 737 fprintf (stderr, ": %s\n", strerror (errno_val)); 738 exit (1); 739 } 740 741 pid = pwait (pid, &wait_status, 0); 742 if (pid == -1) 743 { 744 fprintf (stderr, "%s: wait: %s\n", program_name, strerror (errno)); 745 exit (1); 746 } 747 else if (WIFSIGNALED (wait_status)) 748 { 749 fprintf (stderr, "%s: subprocess got fatal signal %d\n", 750 program_name, WTERMSIG (wait_status)); 751 exit (1); 752 } 753 else if (WIFEXITED (wait_status)) 754 { 755 if (WEXITSTATUS (wait_status) != 0) 756 fprintf (stderr, "%s: %s exited with status %d\n", 757 program_name, what, WEXITSTATUS (wait_status)); 758 } 759 else 760 abort (); 761} 762 763/* read in and block out the base relocations */ 764static void 765basenames (abfd) 766 bfd *abfd; 767{ 768} 769 770static void 771scan_open_obj_file (abfd) 772 bfd *abfd; 773{ 774 /* Look for .drectve's */ 775 asection *s = bfd_get_section_by_name (abfd, ".drectve"); 776 if (s) 777 { 778 int size = bfd_get_section_size_before_reloc (s); 779 char *buf = xmalloc (size); 780 char *p; 781 char *e; 782 bfd_get_section_contents (abfd, s, buf, 0, size); 783 if (verbose) 784 fprintf (stderr, "%s: Sucking in info from %s\n", 785 program_name, 786 bfd_get_filename (abfd)); 787 788 /* Search for -export: strings */ 789 p = buf; 790 e = buf + size; 791 while (p < e) 792 { 793 if (p[0] == '-' 794 && strncmp (p, "-export:", 8) == 0) 795 { 796 char *name; 797 char *c; 798 p += 8; 799 name = p; 800 while (p < e && *p != ' ' && *p != '-') 801 p++; 802 c = xmalloc (p - name + 1); 803 memcpy (c, name, p - name); 804 c[p - name] = 0; 805 /* FIXME: The 5th arg is for the `constant' field. 806 What should it be? Not that it matters since it's not 807 currently useful. */ 808 def_exports (c, 0, -1, 0, 0, 0); 809 } 810 else 811 p++; 812 } 813 free (buf); 814 } 815 816 basenames (abfd); 817 818 if (verbose) 819 fprintf (stderr, "%s: Done readin\n", 820 program_name); 821} 822 823static void 824scan_obj_file (filename) 825 const char *filename; 826{ 827 bfd *f = bfd_openr (filename, 0); 828 829 if (!f) 830 { 831 fprintf (stderr, "%s: Unable to open object file %s\n", 832 program_name, 833 filename); 834 exit (1); 835 } 836 if (bfd_check_format (f, bfd_archive)) 837 { 838 bfd *arfile = bfd_openr_next_archived_file (f, 0); 839 while (arfile) 840 { 841 if (bfd_check_format (arfile, bfd_object)) 842 scan_open_obj_file (arfile); 843 bfd_close (arfile); 844 arfile = bfd_openr_next_archived_file (f, arfile); 845 } 846 } 847 else if (bfd_check_format (f, bfd_object)) 848 { 849 scan_open_obj_file (f); 850 } 851 852 bfd_close (f); 853} 854 855/**********************************************************************/ 856 857static void 858dump_def_info (f) 859 FILE *f; 860{ 861 int i; 862 export_type *exp; 863 fprintf (f, "%s ", ASM_C); 864 for (i = 0; oav[i]; i++) 865 fprintf (f, "%s ", oav[i]); 866 fprintf (f, "\n"); 867 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 868 { 869 fprintf (f, "%s %d = %s %s @ %d %s%s%s\n", 870 ASM_C, 871 i, 872 exp->name, 873 exp->internal_name, 874 exp->ordinal, 875 exp->noname ? "NONAME " : "", 876 exp->constant ? "CONSTANT" : "", 877 exp->data ? "DATA" : ""); 878 } 879} 880 881/* Generate the .exp file */ 882 883static int 884sfunc (a, b) 885 const void *a; 886 const void *b; 887{ 888 return *(const long *) a - *(const long *) b; 889} 890 891static void 892flush_page (f, need, page_addr, on_page) 893 FILE *f; 894 long *need; 895 int page_addr; 896 int on_page; 897{ 898 int i; 899 900 /* Flush this page */ 901 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", 902 ASM_LONG, 903 page_addr, 904 ASM_C); 905 fprintf (f, "\t%s\t0x%x\t%s Size of block\n", 906 ASM_LONG, 907 (on_page * 2) + (on_page & 1) * 2 + 8, 908 ASM_C); 909 for (i = 0; i < on_page; i++) 910 { 911 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000); 912 } 913 /* And padding */ 914 if (on_page & 1) 915 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000); 916} 917 918static void 919gen_def_file () 920{ 921 int i; 922 export_type *exp; 923 924 fprintf (output_def, ";"); 925 for (i = 0; oav[i]; i++) 926 fprintf (output_def, " %s", oav[i]); 927 928 fprintf (output_def, "\nEXPORTS\n"); 929 930 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 931 { 932 char *quote = strchr (exp->name, '.') ? "\"" : ""; 933 fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n", 934 quote, 935 exp->name, 936 quote, 937 exp->ordinal, 938 exp->noname ? " NONAME" : "", 939 exp->data ? " DATA" : "", 940 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS)); 941 } 942} 943 944static void 945gen_exp_file () 946{ 947 FILE *f; 948 int i; 949 export_type *exp; 950 dlist_type *dl; 951 952 953 sprintf (outfile, "t%s", exp_name); 954 955 if (verbose) 956 fprintf (stderr, "%s: Generate exp file %s\n", 957 program_name, exp_name); 958 959 f = fopen (outfile, FOPEN_WT); 960 if (!f) 961 { 962 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile); 963 exit (1); 964 } 965 if (verbose) 966 { 967 fprintf (stderr, "%s: Opened file %s\n", 968 program_name, outfile); 969 } 970 971 dump_def_info (f); 972 if (d_exports) 973 { 974 fprintf (f, "\t.section .edata\n\n"); 975 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); 976 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0), 977 ASM_C); 978 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); 979 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 980 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C); 981 982 983 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C); 984 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n", 985 ASM_C, 986 d_named_nfuncs, d_low_ord, d_high_ord); 987 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, 988 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C); 989 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 990 991 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", 992 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 993 994 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 995 996 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name); 997 998 999 fprintf(f,"%s Export address Table\n", ASM_C); 1000 fprintf(f,"\t%s\n", ASM_ALIGN_LONG); 1001 fprintf (f, "afuncs:\n"); 1002 i = d_low_ord; 1003 1004 for (exp = d_exports; exp; exp = exp->next) 1005 { 1006 if (exp->ordinal != i) 1007 { 1008#if 0 1009 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n", 1010 ASM_SPACE, 1011 (exp->ordinal - i) * 4, 1012 ASM_C, 1013 i, exp->ordinal - 1); 1014 i = exp->ordinal; 1015#endif 1016 while (i < exp->ordinal) 1017 { 1018 fprintf(f,"\t%s\t0\n", ASM_LONG); 1019 i++; 1020 } 1021 } 1022 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, 1023 ASM_PREFIX, 1024 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1025 i++; 1026 } 1027 1028 fprintf (f,"%s Export Name Pointer Table\n", ASM_C); 1029 fprintf (f, "anames:\n"); 1030 1031 for (i = 0; (exp = d_exports_lexically[i]); i++) 1032 { 1033 if (!exp->noname || show_allnames) 1034 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER); 1035 } 1036 1037 fprintf (f,"%s Export Oridinal Table\n", ASM_C); 1038 fprintf (f, "anords:\n"); 1039 for (i = 0; (exp = d_exports_lexically[i]); i++) 1040 { 1041 if (!exp->noname || show_allnames) 1042 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord); 1043 } 1044 1045 fprintf(f,"%s Export Name Table\n", ASM_C); 1046 for (i = 0; (exp = d_exports_lexically[i]); i++) 1047 if (!exp->noname || show_allnames) 1048 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name); 1049 1050 if (a_list) 1051 { 1052 fprintf (f, "\t.section .drectve\n"); 1053 for (dl = a_list; dl; dl = dl->next) 1054 { 1055 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text); 1056 } 1057 } 1058 if (d_list) 1059 { 1060 fprintf (f, "\t.section .rdata\n"); 1061 for (dl = d_list; dl; dl = dl->next) 1062 { 1063 char *p; 1064 int l; 1065 /* We dont output as ascii 'cause there can 1066 be quote characters in the string */ 1067 1068 l = 0; 1069 for (p = dl->text; *p; p++) 1070 { 1071 if (l == 0) 1072 fprintf (f, "\t%s\t", ASM_BYTE); 1073 else 1074 fprintf (f, ","); 1075 fprintf (f, "%d", *p); 1076 if (p[1] == 0) 1077 { 1078 fprintf (f, ",0\n"); 1079 break; 1080 } 1081 if (++l == 10) 1082 { 1083 fprintf (f, "\n"); 1084 l = 0; 1085 } 1086 } 1087 } 1088 } 1089 } 1090 1091 1092 /* Add to the output file a way of getting to the exported names 1093 without using the import library. */ 1094 if (add_indirect) 1095 { 1096 fprintf (f, "\t.section\t.rdata\n"); 1097 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 1098 if (!exp->noname || show_allnames) 1099 { 1100 /* We use a single underscore for MS compatibility, and a 1101 double underscore for backward compatibility with old 1102 cygwin releases. */ 1103 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); 1104 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); 1105 fprintf (f, "__imp_%s:\n", exp->name); 1106 fprintf (f, "_imp__%s:\n", exp->name); 1107 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name); 1108 } 1109 } 1110 1111 /* Dump the reloc section if a base file is provided */ 1112 if (base_file) 1113 { 1114 int addr; 1115 long need[PAGE_SIZE]; 1116 long page_addr; 1117 int numbytes; 1118 int num_entries; 1119 long *copy; 1120 int j; 1121 int on_page; 1122 fprintf (f, "\t.section\t.init\n"); 1123 fprintf (f, "lab:\n"); 1124 1125 fseek (base_file, 0, SEEK_END); 1126 numbytes = ftell (base_file); 1127 fseek (base_file, 0, SEEK_SET); 1128 copy = xmalloc (numbytes); 1129 fread (copy, 1, numbytes, base_file); 1130 num_entries = numbytes / sizeof (long); 1131 1132 1133 fprintf (f, "\t.section\t.reloc\n"); 1134 if (num_entries) 1135 { 1136 int src; 1137 int dst = 0; 1138 int last = -1; 1139 qsort (copy, num_entries, sizeof (long), sfunc); 1140 /* Delete duplcates */ 1141 for (src = 0; src < num_entries; src++) 1142 { 1143 if (last != copy[src]) 1144 last = copy[dst++] = copy[src]; 1145 } 1146 num_entries = dst; 1147 addr = copy[0]; 1148 page_addr = addr & PAGE_MASK; /* work out the page addr */ 1149 on_page = 0; 1150 for (j = 0; j < num_entries; j++) 1151 { 1152 addr = copy[j]; 1153 if ((addr & PAGE_MASK) != page_addr) 1154 { 1155 flush_page (f, need, page_addr, on_page); 1156 on_page = 0; 1157 page_addr = addr & PAGE_MASK; 1158 } 1159 need[on_page++] = addr; 1160 } 1161 flush_page (f, need, page_addr, on_page); 1162 1163/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ 1164 } 1165 } 1166 1167 fclose (f); 1168 1169 /* assemble the file */ 1170 sprintf (outfile, "-o %s t%s", exp_name, exp_name); 1171 run (as_name, outfile); 1172 if (dontdeltemps == 0) 1173 { 1174 sprintf (outfile, "t%s", exp_name); 1175 unlink (outfile); 1176 } 1177} 1178 1179static const char * 1180xlate (name) 1181 const char *name; 1182{ 1183 if (add_underscore) 1184 { 1185 char *copy = xmalloc (strlen (name) + 2); 1186 copy[0] = '_'; 1187 strcpy (copy + 1, name); 1188 name = copy; 1189 } 1190 1191 if (killat) 1192 { 1193 char *p; 1194 p = strchr (name, '@'); 1195 if (p) 1196 *p = 0; 1197 } 1198 return name; 1199} 1200 1201/**********************************************************************/ 1202 1203static void 1204dump_iat (f, exp) 1205 FILE *f; 1206 export_type *exp; 1207{ 1208 if (exp->noname && !show_allnames ) 1209 { 1210 fprintf (f, "\t%s\t0x%08x\n", 1211 ASM_LONG, 1212 exp->ordinal | 0x80000000); /* hint or orindal ?? */ 1213 } 1214 else 1215 { 1216 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE, 1217 exp->ordinal, 1218 ASM_RVA_AFTER); 1219 } 1220} 1221 1222typedef struct 1223{ 1224 int id; 1225 const char *name; 1226 int flags; 1227 int align; 1228 asection *sec; 1229 asymbol *sym; 1230 asymbol **sympp; 1231 int size; 1232 unsigned char *data; 1233} sinfo; 1234 1235#ifndef DLLTOOL_PPC 1236 1237#define TEXT 0 1238#define DATA 1 1239#define BSS 2 1240#define IDATA7 3 1241#define IDATA5 4 1242#define IDATA4 5 1243#define IDATA6 6 1244 1245#define NSECS 7 1246 1247static sinfo secdata[NSECS] = 1248{ 1249 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2}, 1250 { DATA, ".data", SEC_DATA, 2}, 1251 { BSS, ".bss", 0, 2}, 1252 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, 1253 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, 1254 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, 1255 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1} 1256}; 1257 1258#else 1259 1260/* Sections numbered to make the order the same as other PowerPC NT */ 1261/* compilers. This also keeps funny alignment thingies from happening. */ 1262#define TEXT 0 1263#define PDATA 1 1264#define RDATA 2 1265#define IDATA5 3 1266#define IDATA4 4 1267#define IDATA6 5 1268#define IDATA7 6 1269#define DATA 7 1270#define BSS 8 1271 1272#define NSECS 9 1273 1274static sinfo secdata[NSECS] = 1275{ 1276 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3}, 1277 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2}, 1278 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2}, 1279 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, 1280 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, 1281 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}, 1282 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, 1283 { DATA, ".data", SEC_DATA, 2}, 1284 { BSS, ".bss", 0, 2} 1285}; 1286 1287#endif 1288 1289/* 1290This is what we're trying to make. We generate the imp symbols with 1291both single and double underscores, for compatibility. 1292 1293 .text 1294 .global _GetFileVersionInfoSizeW@8 1295 .global __imp_GetFileVersionInfoSizeW@8 1296_GetFileVersionInfoSizeW@8: 1297 jmp * __imp_GetFileVersionInfoSizeW@8 1298 .section .idata$7 # To force loading of head 1299 .long __version_a_head 1300# Import Address Table 1301 .section .idata$5 1302__imp_GetFileVersionInfoSizeW@8: 1303 .rva ID2 1304 1305# Import Lookup Table 1306 .section .idata$4 1307 .rva ID2 1308# Hint/Name table 1309 .section .idata$6 1310ID2: .short 2 1311 .asciz "GetFileVersionInfoSizeW" 1312 1313 1314For the PowerPC, here's the variation on the above scheme: 1315 1316# Rather than a simple "jmp *", the code to get to the dll function 1317# looks like: 1318 .text 1319 lwz r11,[tocv]__imp_function_name(r2) 1320# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name 1321 lwz r12,0(r11) 1322 stw r2,4(r1) 1323 mtctr r12 1324 lwz r2,4(r11) 1325 bctr 1326*/ 1327 1328static char * 1329make_label (prefix, name) 1330 const char *prefix; 1331 const char *name; 1332{ 1333 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); 1334 char *copy = xmalloc (len +1 ); 1335 strcpy (copy, ASM_PREFIX); 1336 strcat (copy, prefix); 1337 strcat (copy, name); 1338 return copy; 1339} 1340 1341static bfd * 1342make_one_lib_file (exp, i) 1343 export_type *exp; 1344 int i; 1345{ 1346 if (0) 1347 { 1348 FILE *f; 1349 char *prefix="d"; 1350 sprintf (outfile, "%ss%d.s", prefix, i); 1351 f = fopen (outfile, FOPEN_WT); 1352 fprintf (f, "\t.text\n"); 1353 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name); 1354 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); 1355 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); 1356 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX, 1357 exp->name, ASM_JUMP, exp->name); 1358 1359 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C); 1360 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label); 1361 1362 1363 fprintf (f,"%s Import Address Table\n", ASM_C); 1364 1365 fprintf (f, "\t.section .idata$5\n"); 1366 fprintf (f, "__imp_%s:\n", exp->name); 1367 fprintf (f, "_imp__%s:\n", exp->name); 1368 1369 dump_iat (f, exp); 1370 1371 fprintf (f, "\n%s Import Lookup Table\n", ASM_C); 1372 fprintf (f, "\t.section .idata$4\n"); 1373 1374 dump_iat (f, exp); 1375 1376 if(!exp->noname || show_allnames) 1377 { 1378 fprintf (f, "%s Hint/Name table\n", ASM_C); 1379 fprintf (f, "\t.section .idata$6\n"); 1380 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint); 1381 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name)); 1382 } 1383 1384 fclose (f); 1385 1386 1387 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i); 1388 1389 run (as_name, outfile); 1390 1391 } 1392 else 1393 { 1394 1395 bfd *abfd; 1396 1397 asymbol *exp_label; 1398 asymbol *iname, *iname2; 1399 asymbol *iname_lab; 1400 asymbol **iname_lab_pp; 1401 asymbol **iname_pp; 1402 1403 /* Extra Symbols for PPC */ 1404#ifdef DLLTOOL_PPC 1405#define EXTRA 2 1406#else 1407#define EXTRA 0 1408#endif 1409 1410#ifdef DLLTOOL_PPC 1411 asymbol **fn_pp; 1412 asymbol **toc_pp; 1413#endif 1414 1415 asymbol *ptrs[NSECS + 4 + EXTRA + 1]; 1416 1417 char *outname = xmalloc (10); 1418 int oidx = 0; 1419 sprintf (outname, "ds%d.o", i); 1420 abfd = bfd_openw (outname, HOW_BFD_TARGET); 1421 if (!abfd) 1422 { 1423 fprintf (stderr, "%s: bfd_open failed open output file %s\n", 1424 program_name, outname); 1425 exit (1); 1426 } 1427 1428 bfd_set_format (abfd, bfd_object); 1429 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); 1430 1431 1432 /* First make symbols for the sections */ 1433 for (i = 0; i < NSECS; i++) 1434 { 1435 sinfo *si = secdata + i; 1436 if (si->id != i) 1437 abort(); 1438 si->sec = bfd_make_section_old_way (abfd, si->name); 1439 bfd_set_section_flags (abfd, 1440 si->sec, 1441 si->flags); 1442 1443 bfd_set_section_alignment(abfd, si->sec, si->align); 1444 si->sec->output_section = si->sec; 1445 si->sym = bfd_make_empty_symbol(abfd); 1446 si->sym->name = si->sec->name; 1447 si->sym->section = si->sec; 1448 si->sym->flags = BSF_LOCAL; 1449 si->sym->value = 0; 1450 ptrs[oidx] = si->sym; 1451 si->sympp = ptrs + oidx; 1452 si->size = 0; 1453 si->data = NULL; 1454 1455 oidx++; 1456 } 1457 1458 if (! exp->data) 1459 { 1460 exp_label = bfd_make_empty_symbol (abfd); 1461 exp_label->name = make_label ("", exp->name); 1462 1463 /* On PowerPC, the function name points to a descriptor in 1464 the rdata section, the first element of which is a 1465 pointer to the code (..function_name), and the second 1466 points to the .toc */ 1467#ifdef DLLTOOL_PPC 1468 if (machine == MPPC) 1469 exp_label->section = secdata[RDATA].sec; 1470 else 1471#endif 1472 exp_label->section = secdata[TEXT].sec; 1473 1474 exp_label->flags = BSF_GLOBAL; 1475 exp_label->value = 0; 1476 1477 ptrs[oidx++] = exp_label; 1478 } 1479 1480 /* Generate imp symbols with one underscore for Microsoft 1481 compatibility, and with two underscores for backward 1482 compatibility with old versions of cygwin. */ 1483 iname = bfd_make_empty_symbol(abfd); 1484 iname->name = make_label ("__imp_", exp->name); 1485 iname->section = secdata[IDATA5].sec; 1486 iname->flags = BSF_GLOBAL; 1487 iname->value = 0; 1488 1489 iname2 = bfd_make_empty_symbol(abfd); 1490 iname2->name = make_label ("_imp__", exp->name); 1491 iname2->section = secdata[IDATA5].sec; 1492 iname2->flags = BSF_GLOBAL; 1493 iname2->value = 0; 1494 1495 iname_lab = bfd_make_empty_symbol(abfd); 1496 1497 iname_lab->name = head_label; 1498 iname_lab->section = (asection *)&bfd_und_section; 1499 iname_lab->flags = 0; 1500 iname_lab->value = 0; 1501 1502 1503 iname_pp = ptrs + oidx; 1504 ptrs[oidx++] = iname; 1505 ptrs[oidx++] = iname2; 1506 1507 iname_lab_pp = ptrs + oidx; 1508 ptrs[oidx++] = iname_lab; 1509 1510#ifdef DLLTOOL_PPC 1511 /* The symbol refering to the code (.text) */ 1512 { 1513 asymbol *function_name; 1514 1515 function_name = bfd_make_empty_symbol(abfd); 1516 function_name->name = make_label ("..", exp->name); 1517 function_name->section = secdata[TEXT].sec; 1518 function_name->flags = BSF_GLOBAL; 1519 function_name->value = 0; 1520 1521 fn_pp = ptrs + oidx; 1522 ptrs[oidx++] = function_name; 1523 } 1524 1525 /* The .toc symbol */ 1526 { 1527 asymbol *toc_symbol; /* The .toc symbol */ 1528 1529 toc_symbol = bfd_make_empty_symbol(abfd); 1530 toc_symbol->name = make_label (".", "toc"); 1531 toc_symbol->section = (asection *)&bfd_und_section; 1532 toc_symbol->flags = BSF_GLOBAL; 1533 toc_symbol->value = 0; 1534 1535 toc_pp = ptrs + oidx; 1536 ptrs[oidx++] = toc_symbol; 1537 } 1538#endif 1539 1540 ptrs[oidx] = 0; 1541 1542 for (i = 0; i < NSECS; i++) 1543 { 1544 sinfo *si = secdata + i; 1545 asection *sec = si->sec; 1546 arelent *rel; 1547 arelent **rpp; 1548 1549 switch (i) 1550 { 1551 case TEXT: 1552 if (! exp->data) 1553 { 1554 si->size = HOW_JTAB_SIZE; 1555 si->data = xmalloc (HOW_JTAB_SIZE); 1556 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); 1557 1558 /* add the reloqc into idata$5 */ 1559 rel = xmalloc (sizeof (arelent)); 1560 rpp = xmalloc (sizeof (arelent *) * 2); 1561 rpp[0] = rel; 1562 rpp[1] = 0; 1563 rel->address = HOW_JTAB_ROFF; 1564 rel->addend = 0; 1565 1566 if (machine == MPPC) 1567 { 1568 rel->howto = bfd_reloc_type_lookup (abfd, 1569 BFD_RELOC_16_GOTOFF); 1570 rel->sym_ptr_ptr = iname_pp; 1571 } 1572 else 1573 { 1574 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1575 rel->sym_ptr_ptr = secdata[IDATA5].sympp; 1576 } 1577 sec->orelocation = rpp; 1578 sec->reloc_count = 1; 1579 } 1580 break; 1581 case IDATA4: 1582 case IDATA5: 1583 /* An idata$4 or idata$5 is one word long, and has an 1584 rva to idata$6 */ 1585 1586 si->data = xmalloc (4); 1587 si->size = 4; 1588 1589 if (exp->noname) 1590 { 1591 si->data[0] = exp->ordinal ; 1592 si->data[1] = exp->ordinal >> 8; 1593 si->data[2] = exp->ordinal >> 16; 1594 si->data[3] = 0x80; 1595 } 1596 else 1597 { 1598 sec->reloc_count = 1; 1599 memset (si->data, 0, si->size); 1600 rel = xmalloc (sizeof (arelent)); 1601 rpp = xmalloc (sizeof (arelent *) * 2); 1602 rpp[0] = rel; 1603 rpp[1] = 0; 1604 rel->address = 0; 1605 rel->addend = 0; 1606 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 1607 rel->sym_ptr_ptr = secdata[IDATA6].sympp; 1608 sec->orelocation = rpp; 1609 } 1610 1611 break; 1612 1613 case IDATA6: 1614 if (!exp->noname) 1615 { 1616 /* This used to add 1 to exp->hint. I don't know 1617 why it did that, and it does not match what I see 1618 in programs compiled with the MS tools. */ 1619 int idx = exp->hint; 1620 si->size = strlen (xlate (exp->name)) + 3; 1621 si->data = xmalloc (si->size); 1622 si->data[0] = idx & 0xff; 1623 si->data[1] = idx >> 8; 1624 strcpy (si->data + 2, xlate (exp->name)); 1625 } 1626 break; 1627 case IDATA7: 1628 si->size = 4; 1629 si->data =xmalloc(4); 1630 memset (si->data, 0, si->size); 1631 rel = xmalloc (sizeof (arelent)); 1632 rpp = xmalloc (sizeof (arelent *) * 2); 1633 rpp[0] = rel; 1634 rel->address = 0; 1635 rel->addend = 0; 1636 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 1637 rel->sym_ptr_ptr = iname_lab_pp; 1638 sec->orelocation = rpp; 1639 sec->reloc_count = 1; 1640 break; 1641 1642#ifdef DLLTOOL_PPC 1643 case PDATA: 1644 { 1645 /* The .pdata section is 5 words long. */ 1646 /* Think of it as: */ 1647 /* struct */ 1648 /* { */ 1649 /* bfd_vma BeginAddress, [0x00] */ 1650 /* EndAddress, [0x04] */ 1651 /* ExceptionHandler, [0x08] */ 1652 /* HandlerData, [0x0c] */ 1653 /* PrologEndAddress; [0x10] */ 1654 /* }; */ 1655 1656 /* So this pdata section setups up this as a glue linkage to 1657 a dll routine. There are a number of house keeping things 1658 we need to do: 1659 1660 1. In the name of glue trickery, the ADDR32 relocs for 0, 1661 4, and 0x10 are set to point to the same place: 1662 "..function_name". 1663 2. There is one more reloc needed in the pdata section. 1664 The actual glue instruction to restore the toc on 1665 return is saved as the offset in an IMGLUE reloc. 1666 So we need a total of four relocs for this section. 1667 1668 3. Lastly, the HandlerData field is set to 0x03, to indicate 1669 that this is a glue routine. 1670 */ 1671 arelent *imglue, *ba_rel, *ea_rel, *pea_rel; 1672 1673 /* alignment must be set to 2**2 or you get extra stuff */ 1674 bfd_set_section_alignment(abfd, sec, 2); 1675 1676 si->size = 4 * 5; 1677 si->data =xmalloc(4 * 5); 1678 memset (si->data, 0, si->size); 1679 rpp = xmalloc (sizeof (arelent *) * 5); 1680 rpp[0] = imglue = xmalloc (sizeof (arelent)); 1681 rpp[1] = ba_rel = xmalloc (sizeof (arelent)); 1682 rpp[2] = ea_rel = xmalloc (sizeof (arelent)); 1683 rpp[3] = pea_rel = xmalloc (sizeof (arelent)); 1684 rpp[4] = 0; 1685 1686 /* stick the toc reload instruction in the glue reloc */ 1687 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address); 1688 1689 imglue->addend = 0; 1690 imglue->howto = bfd_reloc_type_lookup (abfd, 1691 BFD_RELOC_32_GOTOFF); 1692 imglue->sym_ptr_ptr = fn_pp; 1693 1694 ba_rel->address = 0; 1695 ba_rel->addend = 0; 1696 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1697 ba_rel->sym_ptr_ptr = fn_pp; 1698 1699 bfd_put_32(abfd, 0x18, si->data + 0x04); 1700 ea_rel->address = 4; 1701 ea_rel->addend = 0; 1702 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1703 ea_rel->sym_ptr_ptr = fn_pp; 1704 1705 /* mark it as glue */ 1706 bfd_put_32(abfd, 0x03, si->data + 0x0c); 1707 1708 /* mark the prolog end address */ 1709 bfd_put_32(abfd, 0x0D, si->data + 0x10); 1710 pea_rel->address = 0x10; 1711 pea_rel->addend = 0; 1712 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1713 pea_rel->sym_ptr_ptr = fn_pp; 1714 1715 sec->orelocation = rpp; 1716 sec->reloc_count = 4; 1717 break; 1718 } 1719 case RDATA: 1720 /* Each external function in a PowerPC PE file has a two word 1721 descriptor consisting of: 1722 1. The address of the code. 1723 2. The address of the appropriate .toc 1724 We use relocs to build this. 1725 */ 1726 1727 si->size = 8; 1728 si->data = xmalloc (8); 1729 memset (si->data, 0, si->size); 1730 1731 rpp = xmalloc (sizeof (arelent *) * 3); 1732 rpp[0] = rel = xmalloc (sizeof (arelent)); 1733 rpp[1] = xmalloc (sizeof (arelent)); 1734 rpp[2] = 0; 1735 1736 rel->address = 0; 1737 rel->addend = 0; 1738 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1739 rel->sym_ptr_ptr = fn_pp; 1740 1741 rel = rpp[1]; 1742 1743 rel->address = 4; 1744 rel->addend = 0; 1745 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 1746 rel->sym_ptr_ptr = toc_pp; 1747 1748 sec->orelocation = rpp; 1749 sec->reloc_count = 2; 1750 break; 1751#endif /* DLLTOOL_PPC */ 1752 } 1753 } 1754 1755 { 1756 bfd_vma vma = 0; 1757 /* Size up all the sections */ 1758 for (i = 0; i < NSECS; i++) 1759 { 1760 sinfo *si = secdata + i; 1761 1762 bfd_set_section_size (abfd, si->sec, si->size); 1763 bfd_set_section_vma (abfd, si->sec, vma); 1764 1765/* vma += si->size;*/ 1766 } 1767 } 1768 /* Write them out */ 1769 for (i = 0; i < NSECS; i++) 1770 { 1771 sinfo *si = secdata + i; 1772 1773 if (i == IDATA5 && no_idata5) 1774 continue; 1775 1776 if (i == IDATA4 && no_idata4) 1777 continue; 1778 1779 bfd_set_section_contents (abfd, si->sec, 1780 si->data, 0, 1781 si->size); 1782 } 1783 1784 bfd_set_symtab (abfd, ptrs, oidx); 1785 bfd_close (abfd); 1786 abfd = bfd_openr (outname, HOW_BFD_TARGET); 1787 return abfd; 1788 } 1789 1790} 1791 1792static bfd * 1793make_head () 1794{ 1795 FILE * f = fopen ("dh.s", FOPEN_WT); 1796 1797 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); 1798 fprintf (f, "\t.section .idata$2\n"); 1799 1800 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); 1801 1802 fprintf (f, "%s:\n", head_label); 1803 1804 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n", 1805 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 1806 1807 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C); 1808 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C); 1809 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C); 1810 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); 1811 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n", 1812 ASM_RVA_BEFORE, 1813 imp_name_lab, 1814 ASM_RVA_AFTER, 1815 ASM_C); 1816 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n", 1817 ASM_RVA_BEFORE, 1818 ASM_RVA_AFTER, ASM_C); 1819 1820 fprintf (f, "%sStuff for compatibility\n", ASM_C); 1821 1822 if (!no_idata5) 1823 { 1824 fprintf (f, "\t.section\t.idata$5\n"); 1825 fprintf (f, "\t%s\t0\n", ASM_LONG); 1826 fprintf (f, "fthunk:\n"); 1827 } 1828 if (!no_idata4) 1829 { 1830 fprintf (f, "\t.section\t.idata$4\n"); 1831 1832 fprintf (f, "\t%s\t0\n", ASM_LONG); 1833 fprintf (f, "\t.section .idata$4\n"); 1834 fprintf (f, "hname:\n"); 1835 } 1836 fclose (f); 1837 1838 sprintf (outfile, "-o dh.o dh.s"); 1839 run (as_name, outfile); 1840 1841 return bfd_openr ("dh.o", HOW_BFD_TARGET); 1842} 1843 1844static bfd * 1845make_tail () 1846{ 1847 FILE * f = fopen ("dt.s", FOPEN_WT); 1848 1849 if (!no_idata4) 1850 { 1851 fprintf (f, "\t.section .idata$4\n"); 1852 fprintf (f, "\t%s\t0\n", ASM_LONG); 1853 } 1854 if (!no_idata5) 1855 { 1856 fprintf (f, "\t.section .idata$5\n"); 1857 fprintf (f, "\t%s\t0\n", ASM_LONG); 1858 } 1859 1860#ifdef DLLTOOL_PPC 1861 /* Normally, we need to see a null descriptor built in idata$3 to 1862 act as the terminator for the list. The ideal way, I suppose, 1863 would be to mark this section as a comdat type 2 section, so 1864 only one would appear in the final .exe (if our linker supported 1865 comdat, that is) or cause it to be inserted by something else (say 1866 crt0) 1867 */ 1868 1869 fprintf (f, "\t.section .idata$3\n"); 1870 fprintf (f, "\t%s\t0\n", ASM_LONG); 1871 fprintf (f, "\t%s\t0\n", ASM_LONG); 1872 fprintf (f, "\t%s\t0\n", ASM_LONG); 1873 fprintf (f, "\t%s\t0\n", ASM_LONG); 1874 fprintf (f, "\t%s\t0\n", ASM_LONG); 1875#endif 1876 1877#ifdef DLLTOOL_PPC 1878 /* Other PowerPC NT compilers use idata$6 for the dllname, so I 1879 do too. Original, huh? */ 1880 fprintf (f, "\t.section .idata$6\n"); 1881#else 1882 fprintf (f, "\t.section .idata$7\n"); 1883#endif 1884 1885 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab); 1886 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n", 1887 imp_name_lab, ASM_TEXT, dll_name); 1888 1889 fclose (f); 1890 1891 sprintf (outfile, "-o dt.o dt.s"); 1892 run (as_name, outfile); 1893 return bfd_openr ("dt.o", HOW_BFD_TARGET); 1894} 1895 1896static void 1897gen_lib_file () 1898{ 1899 int i; 1900 export_type *exp; 1901 bfd *ar_head; 1902 bfd *ar_tail; 1903 bfd *outarch; 1904 bfd * head = 0; 1905 1906 unlink (imp_name); 1907 1908 outarch = bfd_openw (imp_name, HOW_BFD_TARGET); 1909 1910 if (!outarch) 1911 { 1912 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name); 1913 exit (1); 1914 } 1915 bfd_set_format (outarch, bfd_archive); 1916 outarch->has_armap = 1; 1917 1918 /* Work out a reasonable size of things to put onto one line. */ 1919 1920 1921 1922 ar_head = make_head (); 1923 ar_tail = make_tail(); 1924 1925 for (i = 0; (exp = d_exports_lexically[i]); i++) 1926 { 1927 bfd *n = make_one_lib_file (exp, i); 1928 n->next = head; 1929 head = n; 1930 } 1931 1932 1933 /* Now stick them all into the archive */ 1934 1935 ar_head->next = head; 1936 ar_tail->next = ar_head; 1937 head = ar_tail; 1938 1939 if (! bfd_set_archive_head (outarch, head)) 1940 bfd_fatal ("bfd_set_archive_head"); 1941 if (! bfd_close (outarch)) 1942 bfd_fatal (imp_name); 1943 1944 while (head != NULL) 1945 { 1946 bfd *n = head->next; 1947 bfd_close (head); 1948 head = n; 1949 } 1950 1951 /* Delete all the temp files */ 1952 1953 if (dontdeltemps == 0) 1954 { 1955 sprintf (outfile, "dh.o"); 1956 unlink (outfile); 1957 sprintf (outfile, "dh.s"); 1958 unlink (outfile); 1959 sprintf (outfile, "dt.o"); 1960 unlink (outfile); 1961 sprintf (outfile, "dt.s"); 1962 unlink (outfile); 1963 } 1964 1965 if (dontdeltemps < 2) 1966 { 1967 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 1968 { 1969 sprintf (outfile, "ds%d.o",i); 1970 if (unlink (outfile) < 0) 1971 fprintf (stderr, "%s: cannot delete %s: %s\n", program_name, 1972 outfile, strerror (errno)); 1973 } 1974 } 1975} 1976 1977/**********************************************************************/ 1978 1979/* Run through the information gathered from the .o files and the 1980 .def file and work out the best stuff */ 1981static int 1982pfunc (a, b) 1983 const void *a; 1984 const void *b; 1985{ 1986 export_type *ap = *(export_type **) a; 1987 export_type *bp = *(export_type **) b; 1988 if (ap->ordinal == bp->ordinal) 1989 return 0; 1990 1991 /* unset ordinals go to the bottom */ 1992 if (ap->ordinal == -1) 1993 return 1; 1994 if (bp->ordinal == -1) 1995 return -1; 1996 return (ap->ordinal - bp->ordinal); 1997} 1998 1999static int 2000nfunc (a, b) 2001 const void *a; 2002 const void *b; 2003{ 2004 export_type *ap = *(export_type **) a; 2005 export_type *bp = *(export_type **) b; 2006 2007 return (strcmp (ap->name, bp->name)); 2008} 2009 2010static void 2011remove_null_names (ptr) 2012 export_type **ptr; 2013{ 2014 int src; 2015 int dst; 2016 for (dst = src = 0; src < d_nfuncs; src++) 2017 { 2018 if (ptr[src]) 2019 { 2020 ptr[dst] = ptr[src]; 2021 dst++; 2022 } 2023 } 2024 d_nfuncs = dst; 2025} 2026 2027static void 2028dtab (ptr) 2029 export_type **ptr; 2030{ 2031#ifdef SACDEBUG 2032 int i; 2033 for (i = 0; i < d_nfuncs; i++) 2034 { 2035 if (ptr[i]) 2036 { 2037 printf ("%d %s @ %d %s%s%s\n", 2038 i, ptr[i]->name, ptr[i]->ordinal, 2039 ptr[i]->noname ? "NONAME " : "", 2040 ptr[i]->constant ? "CONSTANT" : "", 2041 ptr[i]->data ? "DATA" : ""); 2042 } 2043 else 2044 printf ("empty\n"); 2045 } 2046#endif 2047} 2048 2049static void 2050process_duplicates (d_export_vec) 2051 export_type **d_export_vec; 2052{ 2053 int more = 1; 2054 int i; 2055 while (more) 2056 { 2057 2058 more = 0; 2059 /* Remove duplicates */ 2060 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); 2061 2062 dtab (d_export_vec); 2063 for (i = 0; i < d_nfuncs - 1; i++) 2064 { 2065 if (strcmp (d_export_vec[i]->name, 2066 d_export_vec[i + 1]->name) == 0) 2067 { 2068 2069 export_type *a = d_export_vec[i]; 2070 export_type *b = d_export_vec[i + 1]; 2071 2072 more = 1; 2073 if (verbose) 2074 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n", 2075 a->name, 2076 a->ordinal, 2077 b->ordinal); 2078 if (a->ordinal != -1 2079 && b->ordinal != -1) 2080 { 2081 2082 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n", 2083 a->name); 2084 exit (1); 2085 } 2086 /* Merge attributes */ 2087 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; 2088 b->constant |= a->constant; 2089 b->noname |= a->noname; 2090 b->data |= a->data; 2091 d_export_vec[i] = 0; 2092 } 2093 2094 dtab (d_export_vec); 2095 remove_null_names (d_export_vec); 2096 dtab (d_export_vec); 2097 } 2098 } 2099 2100 2101 /* Count the names */ 2102 for (i = 0; i < d_nfuncs; i++) 2103 { 2104 if (!d_export_vec[i]->noname) 2105 d_named_nfuncs++; 2106 } 2107} 2108 2109static void 2110fill_ordinals (d_export_vec) 2111 export_type **d_export_vec; 2112{ 2113 int lowest = -1; 2114 int i; 2115 char *ptr; 2116 int size = 65536; 2117 2118 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 2119 2120 /* fill in the unset ordinals with ones from our range */ 2121 2122 ptr = (char *) xmalloc (size); 2123 2124 memset (ptr, 0, size); 2125 2126 /* Mark in our large vector all the numbers that are taken */ 2127 for (i = 0; i < d_nfuncs; i++) 2128 { 2129 if (d_export_vec[i]->ordinal != -1) 2130 { 2131 ptr[d_export_vec[i]->ordinal] = 1; 2132 if (lowest == -1 || d_export_vec[i]->ordinal < lowest) 2133 { 2134 lowest = d_export_vec[i]->ordinal; 2135 } 2136 } 2137 } 2138 2139 /* Start at 1 for compatibility with MS toolchain. */ 2140 if (lowest == -1) 2141 lowest = 1; 2142 2143 /* Now fill in ordinals where the user wants us to choose. */ 2144 for (i = 0; i < d_nfuncs; i++) 2145 { 2146 if (d_export_vec[i]->ordinal == -1) 2147 { 2148 register int j; 2149 2150 /* First try within or after any user supplied range. */ 2151 for (j = lowest; j < size; j++) 2152 if (ptr[j] == 0) 2153 { 2154 ptr[j] = 1; 2155 d_export_vec[i]->ordinal = j; 2156 goto done; 2157 } 2158 2159 /* Then try before the range. */ 2160 for (j = lowest; j >0; j--) 2161 if (ptr[j] == 0) 2162 { 2163 ptr[j] = 1; 2164 d_export_vec[i]->ordinal = j; 2165 goto done; 2166 } 2167 done:; 2168 } 2169 } 2170 2171 free (ptr); 2172 2173 /* And resort */ 2174 2175 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 2176 2177 /* Work out the lowest and highest ordinal numbers. */ 2178 if (d_nfuncs) 2179 { 2180 if (d_export_vec[0]) 2181 d_low_ord = d_export_vec[0]->ordinal; 2182 if (d_export_vec[d_nfuncs-1]) 2183 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal; 2184 } 2185} 2186 2187static int 2188alphafunc (av,bv) 2189 const void *av; 2190 const void *bv; 2191{ 2192 const export_type **a = (const export_type **) av; 2193 const export_type **b = (const export_type **) bv; 2194 2195 return strcmp ((*a)->name, (*b)->name); 2196} 2197 2198static void 2199mangle_defs () 2200{ 2201 /* First work out the minimum ordinal chosen */ 2202 2203 export_type *exp; 2204 2205 int i; 2206 int hint = 0; 2207 export_type **d_export_vec 2208 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs); 2209 2210 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 2211 { 2212 d_export_vec[i] = exp; 2213 } 2214 2215 process_duplicates (d_export_vec); 2216 fill_ordinals (d_export_vec); 2217 2218 /* Put back the list in the new order */ 2219 d_exports = 0; 2220 for (i = d_nfuncs - 1; i >= 0; i--) 2221 { 2222 d_export_vec[i]->next = d_exports; 2223 d_exports = d_export_vec[i]; 2224 } 2225 2226 /* Build list in alpha order */ 2227 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1)); 2228 2229 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 2230 { 2231 d_exports_lexically[i] = exp; 2232 } 2233 d_exports_lexically[i] = 0; 2234 2235 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc); 2236 2237 /* Fill exp entries with their hint values */ 2238 2239 for (i = 0; i < d_nfuncs; i++) 2240 { 2241 if (!d_exports_lexically[i]->noname || show_allnames) 2242 d_exports_lexically[i]->hint = hint++; 2243 } 2244 2245} 2246 2247/**********************************************************************/ 2248 2249static void 2250usage (file, status) 2251 FILE *file; 2252 int status; 2253{ 2254 fprintf (file, "Usage %s <options> <object-files>\n", program_name); 2255 fprintf (file, " --machine <machine>\n"); 2256 fprintf (file, " --output-exp <outname> Generate export file.\n"); 2257 fprintf (file, " --output-lib <outname> Generate input library.\n"); 2258 fprintf (file, " --add-indirect Add dll indirects to export file.\n"); 2259 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n"); 2260 fprintf (file, " --def <deffile> Name input .def file\n"); 2261 fprintf (file, " --output-def <deffile> Name output .def file\n"); 2262 fprintf (file, " --base-file <basefile> Read linker generated base file\n"); 2263 fprintf (file, " --no-idata4 Don't generate idata$4 section\n"); 2264 fprintf (file, " --no-idata5 Don't generate idata$5 section\n"); 2265 fprintf (file, " -v Verbose\n"); 2266 fprintf (file, " -U Add underscores to .lib\n"); 2267 fprintf (file, " -k Kill @<n> from exported names\n"); 2268 fprintf (file, " --as <name> Use <name> for assembler\n"); 2269 fprintf (file, " --nodelete Keep temp files.\n"); 2270 exit (status); 2271} 2272 2273#define OPTION_NO_IDATA4 'x' 2274#define OPTION_NO_IDATA5 'c' 2275static const struct option long_options[] = 2276{ 2277 {"nodelete", no_argument, NULL, 'n'}, 2278 {"dllname", required_argument, NULL, 'D'}, 2279 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4}, 2280 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5}, 2281 {"output-exp", required_argument, NULL, 'e'}, 2282 {"output-def", required_argument, NULL, 'z'}, 2283 {"output-lib", required_argument, NULL, 'l'}, 2284 {"def", required_argument, NULL, 'd'}, 2285 {"add-underscore", no_argument, NULL, 'U'}, 2286 {"killat", no_argument, NULL, 'k'}, 2287 {"help", no_argument, NULL, 'h'}, 2288 {"machine", required_argument, NULL, 'm'}, 2289 {"add-indirect", no_argument, NULL, 'a'}, 2290 {"base-file", required_argument, NULL, 'b'}, 2291 {"as", required_argument, NULL, 'S'}, 2292 {0} 2293}; 2294 2295int 2296main (ac, av) 2297 int ac; 2298 char **av; 2299{ 2300 int c; 2301 int i; 2302 char *firstarg = 0; 2303 program_name = av[0]; 2304 oav = av; 2305 2306 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0)) 2307 != EOF) 2308 { 2309 switch (c) 2310 { 2311 case OPTION_NO_IDATA4: 2312 no_idata4 = 1; 2313 break; 2314 case OPTION_NO_IDATA5: 2315 no_idata5 = 1; 2316 break; 2317 case 'S': 2318 as_name = optarg; 2319 break; 2320 2321 /* ignored for compatibility */ 2322 case 'u': 2323 break; 2324 case 'a': 2325 add_indirect = 1; 2326 break; 2327 case 'z': 2328 output_def = fopen (optarg, FOPEN_WT); 2329 break; 2330 case 'D': 2331 dll_name = optarg; 2332 break; 2333 case 'l': 2334 imp_name = optarg; 2335 break; 2336 case 'e': 2337 exp_name = optarg; 2338 break; 2339 case 'h': 2340 case '?': 2341 usage (stderr, 0); 2342 break; 2343 case 'm': 2344 mname = optarg; 2345 break; 2346 case 'v': 2347 verbose = 1; 2348 break; 2349 case 'y': 2350#if 0 2351 /* We don't currently define YYDEBUG when building 2352 defparse.y. */ 2353 yydebug = 1; 2354#endif 2355 break; 2356 case 'U': 2357 add_underscore = 1; 2358 break; 2359 case 'k': 2360 killat = 1; 2361 break; 2362 case 'd': 2363 def_file = optarg; 2364 break; 2365 case 'n': 2366 dontdeltemps++; 2367 break; 2368 case 'b': 2369 base_file = fopen (optarg, FOPEN_RB); 2370 if (!base_file) 2371 { 2372 fprintf (stderr, "%s: Unable to open base-file %s\n", 2373 av[0], 2374 optarg); 2375 exit (1); 2376 } 2377 break; 2378 default: 2379 usage (stderr, 1); 2380 } 2381 } 2382 2383 2384 for (i = 0; mtable[i].type; i++) 2385 { 2386 if (strcmp (mtable[i].type, mname) == 0) 2387 break; 2388 } 2389 2390 if (!mtable[i].type) 2391 { 2392 fprintf (stderr, "Machine not supported\n"); 2393 exit (1); 2394 } 2395 machine = i; 2396 2397 2398 if (!dll_name && exp_name) 2399 { 2400 char len = strlen (exp_name) + 5; 2401 dll_name = xmalloc (len); 2402 strcpy (dll_name, exp_name); 2403 strcat (dll_name, ".dll"); 2404 } 2405 2406 if (def_file) 2407 { 2408 process_def_file (def_file); 2409 } 2410 while (optind < ac) 2411 { 2412 if (!firstarg) 2413 firstarg = av[optind]; 2414 scan_obj_file (av[optind]); 2415 optind++; 2416 } 2417 2418 mangle_defs (); 2419 2420 if (exp_name) 2421 gen_exp_file (); 2422 if (imp_name) 2423 { 2424 /* Make imp_name safe for use as a label. */ 2425 char *p; 2426 2427 imp_name_lab = xstrdup (imp_name); 2428 for (p = imp_name_lab; *p; p++) 2429 { 2430 if (!isalpha (*p) && !isdigit (*p)) 2431 *p = '_'; 2432 } 2433 head_label = make_label("_head_", imp_name_lab); 2434 gen_lib_file (); 2435 } 2436 if (output_def) 2437 gen_def_file (); 2438 2439 return 0; 2440} 2441