1 /* dlltool.c -- tool to generate stuff for PE style DLLs 2 Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 3 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 2 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., 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. */ 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> ] ) 51 | ( <name1> = <module-name> . <external-name>)) 52 [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) * 53 Declares name1 as an exported symbol from the 54 DLL, with optional ordinal number <integer>. 55 Or declares name1 as an alias (forward) of the function <external-name> 56 in the DLL <module-name>. 57 58 IMPORTS ( ( <internal-name> = <module-name> . <integer> ) 59 | ( [ <internal-name> = ] <module-name> . <external-name> )) * 60 Declares that <external-name> or the exported function whoes ordinal number 61 is <integer> is to be imported from the file <module-name>. If 62 <internal-name> is specified then this is the name that the imported 63 function will be refereed to in the body of the DLL. 64 65 DESCRIPTION <string> 66 Puts <string> into output .exp file in the .rdata section 67 68 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ] 69 Generates --stack|--heap <number-reserve>,<number-commit> 70 in the output .drectve section. The linker will 71 see this and act upon it. 72 73 [CODE|DATA] <attr>+ 74 SECTIONS ( <sectionname> <attr>+ )* 75 <attr> = READ | WRITE | EXECUTE | SHARED 76 Generates --attr <sectionname> <attr> in the output 77 .drectve section. The linker will see this and act 78 upon it. 79 80 81 A -export:<name> in a .drectve section in an input .o or .a 82 file to this program is equivalent to a EXPORTS <name> 83 in a .DEF file. 84 85 86 87 The program generates output files with the prefix supplied 88 on the command line, or in the def file, or taken from the first 89 supplied argument. 90 91 The .exp.s file contains the information necessary to export 92 the routines in the DLL. The .lib.s file contains the information 93 necessary to use the DLL's routines from a referencing program. 94 95 96 97 Example: 98 99 file1.c: 100 asm (".section .drectve"); 101 asm (".ascii \"-export:adef\""); 102 103 void adef (char * s) 104 { 105 printf ("hello from the dll %s\n", s); 106 } 107 108 void bdef (char * s) 109 { 110 printf ("hello from the dll and the other entry point %s\n", s); 111 } 112 113 file2.c: 114 asm (".section .drectve"); 115 asm (".ascii \"-export:cdef\""); 116 asm (".ascii \"-export:ddef\""); 117 118 void cdef (char * s) 119 { 120 printf ("hello from the dll %s\n", s); 121 } 122 123 void ddef (char * s) 124 { 125 printf ("hello from the dll and the other entry point %s\n", s); 126 } 127 128 int printf (void) 129 { 130 return 9; 131 } 132 133 themain.c: 134 int main (void) 135 { 136 cdef (); 137 return 0; 138 } 139 140 thedll.def 141 142 LIBRARY thedll 143 HEAPSIZE 0x40000, 0x2000 144 EXPORTS bdef @ 20 145 cdef @ 30 NONAME 146 147 SECTIONS donkey READ WRITE 148 aardvark EXECUTE 149 150 # Compile up the parts of the dll and the program 151 152 gcc -c file1.c file2.c themain.c 153 154 # Optional: put the dll objects into a library 155 # (you don't have to, you could name all the object 156 # files on the dlltool line) 157 158 ar qcv thedll.in file1.o file2.o 159 ranlib thedll.in 160 161 # Run this tool over the DLL's .def file and generate an exports 162 # file (thedll.o) and an imports file (thedll.a). 163 # (You may have to use -S to tell dlltool where to find the assembler). 164 165 dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a 166 167 # Build the dll with the library and the export table 168 169 ld -o thedll.dll thedll.o thedll.in 170 171 # Link the executable with the import library 172 173 gcc -o themain.exe themain.o thedll.a 174 175 This example can be extended if relocations are needed in the DLL: 176 177 # Compile up the parts of the dll and the program 178 179 gcc -c file1.c file2.c themain.c 180 181 # Run this tool over the DLL's .def file and generate an imports file. 182 183 dlltool --def thedll.def --output-lib thedll.lib 184 185 # Link the executable with the import library and generate a base file 186 # at the same time 187 188 gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base 189 190 # Run this tool over the DLL's .def file and generate an exports file 191 # which includes the relocations from the base file. 192 193 dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp 194 195 # Build the dll with file1.o, file2.o and the export table 196 197 ld -o thedll.dll thedll.exp file1.o file2.o */ 198 199 /* .idata section description 200 201 The .idata section is the import table. It is a collection of several 202 subsections used to keep the pieces for each dll together: .idata$[234567]. 203 IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc. 204 205 .idata$2 = Import Directory Table 206 = array of IMAGE_IMPORT_DESCRIPTOR's. 207 208 DWORD Import Lookup Table; - pointer to .idata$4 209 DWORD TimeDateStamp; - currently always 0 210 DWORD ForwarderChain; - currently always 0 211 DWORD Name; - pointer to dll's name 212 PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5 213 214 .idata$3 = null terminating entry for .idata$2. 215 216 .idata$4 = Import Lookup Table 217 = array of array of pointers to hint name table. 218 There is one for each dll being imported from, and each dll's set is 219 terminated by a trailing NULL. 220 221 .idata$5 = Import Address Table 222 = array of array of pointers to hint name table. 223 There is one for each dll being imported from, and each dll's set is 224 terminated by a trailing NULL. 225 Initially, this table is identical to the Import Lookup Table. However, 226 at load time, the loader overwrites the entries with the address of the 227 function. 228 229 .idata$6 = Hint Name Table 230 = Array of { short, asciz } entries, one for each imported function. 231 The `short' is the function's ordinal number. 232 233 .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */ 234 235 /* AIX requires this to be the first thing in the file. */ 236 #ifndef __GNUC__ 237 # ifdef _AIX 238 #pragma alloca 239 #endif 240 #endif 241 242 #define show_allnames 0 243 244 #define PAGE_SIZE 4096 245 #define PAGE_MASK (-PAGE_SIZE) 246 #include "bfd.h" 247 #include "libiberty.h" 248 #include "bucomm.h" 249 #include "getopt.h" 250 #include "demangle.h" 251 #include "dyn-string.h" 252 #include "dlltool.h" 253 #include "safe-ctype.h" 254 255 #include <time.h> 256 #include <sys/stat.h> 257 258 #ifdef ANSI_PROTOTYPES 259 #include <stdarg.h> 260 #else 261 #include <varargs.h> 262 #endif 263 264 #ifdef DLLTOOL_ARM 265 #include "coff/arm.h" 266 #include "coff/internal.h" 267 #endif 268 269 /* Forward references. */ 270 static char *look_for_prog (const char *, const char *, int); 271 static char *deduce_name (const char *); 272 273 #ifdef DLLTOOL_MCORE_ELF 274 static void mcore_elf_cache_filename (char *); 275 static void mcore_elf_gen_out_file (void); 276 #endif 277 278 #ifdef HAVE_SYS_WAIT_H 279 #include <sys/wait.h> 280 #else /* ! HAVE_SYS_WAIT_H */ 281 #if ! defined (_WIN32) || defined (__CYGWIN32__) 282 #ifndef WIFEXITED 283 #define WIFEXITED(w) (((w) & 0377) == 0) 284 #endif 285 #ifndef WIFSIGNALED 286 #define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0) 287 #endif 288 #ifndef WTERMSIG 289 #define WTERMSIG(w) ((w) & 0177) 290 #endif 291 #ifndef WEXITSTATUS 292 #define WEXITSTATUS(w) (((w) >> 8) & 0377) 293 #endif 294 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 295 #ifndef WIFEXITED 296 #define WIFEXITED(w) (((w) & 0xff) == 0) 297 #endif 298 #ifndef WIFSIGNALED 299 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 300 #endif 301 #ifndef WTERMSIG 302 #define WTERMSIG(w) ((w) & 0x7f) 303 #endif 304 #ifndef WEXITSTATUS 305 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 306 #endif 307 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 308 #endif /* ! HAVE_SYS_WAIT_H */ 309 310 /* ifunc and ihead data structures: ttk@cygnus.com 1997 311 312 When IMPORT declarations are encountered in a .def file the 313 function import information is stored in a structure referenced by 314 the global variable IMPORT_LIST. The structure is a linked list 315 containing the names of the dll files each function is imported 316 from and a linked list of functions being imported from that dll 317 file. This roughly parallels the structure of the .idata section 318 in the PE object file. 319 320 The contents of .def file are interpreted from within the 321 process_def_file function. Every time an IMPORT declaration is 322 encountered, it is broken up into its component parts and passed to 323 def_import. IMPORT_LIST is initialized to NULL in function main. */ 324 325 typedef struct ifunct 326 { 327 char * name; /* Name of function being imported. */ 328 int ord; /* Two-byte ordinal value associated with function. */ 329 struct ifunct *next; 330 } ifunctype; 331 332 typedef struct iheadt 333 { 334 char *dllname; /* Name of dll file imported from. */ 335 long nfuncs; /* Number of functions in list. */ 336 struct ifunct *funchead; /* First function in list. */ 337 struct ifunct *functail; /* Last function in list. */ 338 struct iheadt *next; /* Next dll file in list. */ 339 } iheadtype; 340 341 /* Structure containing all import information as defined in .def file 342 (qv "ihead structure"). */ 343 344 static iheadtype *import_list = NULL; 345 346 static char *as_name = NULL; 347 static char * as_flags = ""; 348 349 static char *tmp_prefix; 350 351 static int no_idata4; 352 static int no_idata5; 353 static char *exp_name; 354 static char *imp_name; 355 static char *head_label; 356 static char *imp_name_lab; 357 static char *dll_name; 358 359 static int add_indirect = 0; 360 static int add_underscore = 0; 361 static int dontdeltemps = 0; 362 363 /* TRUE if we should export all symbols. Otherwise, we only export 364 symbols listed in .drectve sections or in the def file. */ 365 static bfd_boolean export_all_symbols; 366 367 /* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when 368 exporting all symbols. */ 369 static bfd_boolean do_default_excludes = TRUE; 370 371 /* Default symbols to exclude when exporting all the symbols. */ 372 static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr"; 373 374 /* TRUE if we should add __imp_<SYMBOL> to import libraries for backward 375 compatibility to old Cygwin releases. */ 376 static bfd_boolean create_compat_implib; 377 378 static char *def_file; 379 380 extern char * program_name; 381 382 static int machine; 383 static int killat; 384 static int add_stdcall_alias; 385 static int verbose; 386 static FILE *output_def; 387 static FILE *base_file; 388 389 #ifdef DLLTOOL_ARM 390 #ifdef DLLTOOL_ARM_EPOC 391 static const char *mname = "arm-epoc"; 392 #else 393 static const char *mname = "arm"; 394 #endif 395 #endif 396 397 #ifdef DLLTOOL_I386 398 static const char *mname = "i386"; 399 #endif 400 401 #ifdef DLLTOOL_PPC 402 static const char *mname = "ppc"; 403 #endif 404 405 #ifdef DLLTOOL_SH 406 static const char *mname = "sh"; 407 #endif 408 409 #ifdef DLLTOOL_MIPS 410 static const char *mname = "mips"; 411 #endif 412 413 #ifdef DLLTOOL_MCORE 414 static const char * mname = "mcore-le"; 415 #endif 416 417 #ifdef DLLTOOL_MCORE_ELF 418 static const char * mname = "mcore-elf"; 419 static char * mcore_elf_out_file = NULL; 420 static char * mcore_elf_linker = NULL; 421 static char * mcore_elf_linker_flags = NULL; 422 423 #define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve") 424 #endif 425 426 #ifndef DRECTVE_SECTION_NAME 427 #define DRECTVE_SECTION_NAME ".drectve" 428 #endif 429 430 #define PATHMAX 250 /* What's the right name for this ? */ 431 432 char *tmp_asm_buf; 433 char *tmp_head_s_buf; 434 char *tmp_head_o_buf; 435 char *tmp_tail_s_buf; 436 char *tmp_tail_o_buf; 437 char *tmp_stub_buf; 438 439 #define TMP_ASM dlltmp (&tmp_asm_buf, "%sc.s") 440 #define TMP_HEAD_S dlltmp (&tmp_head_s_buf, "%sh.s") 441 #define TMP_HEAD_O dlltmp (&tmp_head_o_buf, "%sh.o") 442 #define TMP_TAIL_S dlltmp (&tmp_tail_s_buf, "%st.s") 443 #define TMP_TAIL_O dlltmp (&tmp_tail_o_buf, "%st.o") 444 #define TMP_STUB dlltmp (&tmp_stub_buf, "%ss") 445 446 /* This bit of assembly does jmp * .... */ 447 static const unsigned char i386_jtab[] = 448 { 449 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 450 }; 451 452 static const unsigned char arm_jtab[] = 453 { 454 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ 455 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */ 456 0, 0, 0, 0 457 }; 458 459 static const unsigned char arm_interwork_jtab[] = 460 { 461 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */ 462 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */ 463 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */ 464 0, 0, 0, 0 465 }; 466 467 static const unsigned char thumb_jtab[] = 468 { 469 0x40, 0xb4, /* push {r6} */ 470 0x02, 0x4e, /* ldr r6, [pc, #8] */ 471 0x36, 0x68, /* ldr r6, [r6] */ 472 0xb4, 0x46, /* mov ip, r6 */ 473 0x40, 0xbc, /* pop {r6} */ 474 0x60, 0x47, /* bx ip */ 475 0, 0, 0, 0 476 }; 477 478 static const unsigned char mcore_be_jtab[] = 479 { 480 0x71, 0x02, /* lrw r1,2 */ 481 0x81, 0x01, /* ld.w r1,(r1,0) */ 482 0x00, 0xC1, /* jmp r1 */ 483 0x12, 0x00, /* nop */ 484 0x00, 0x00, 0x00, 0x00 /* <address> */ 485 }; 486 487 static const unsigned char mcore_le_jtab[] = 488 { 489 0x02, 0x71, /* lrw r1,2 */ 490 0x01, 0x81, /* ld.w r1,(r1,0) */ 491 0xC1, 0x00, /* jmp r1 */ 492 0x00, 0x12, /* nop */ 493 0x00, 0x00, 0x00, 0x00 /* <address> */ 494 }; 495 496 /* This is the glue sequence for PowerPC PE. There is a 497 tocrel16-tocdefn reloc against the first instruction. 498 We also need a IMGLUE reloc against the glue function 499 to restore the toc saved by the third instruction in 500 the glue. */ 501 static const unsigned char ppc_jtab[] = 502 { 503 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */ 504 /* Reloc TOCREL16 __imp_xxx */ 505 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */ 506 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */ 507 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */ 508 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */ 509 0x20, 0x04, 0x80, 0x4E /* bctr */ 510 }; 511 512 #ifdef DLLTOOL_PPC 513 /* The glue instruction, picks up the toc from the stw in 514 the above code: "lwz r2,4(r1)". */ 515 static bfd_vma ppc_glue_insn = 0x80410004; 516 #endif 517 518 struct mac 519 { 520 const char *type; 521 const char *how_byte; 522 const char *how_short; 523 const char *how_long; 524 const char *how_asciz; 525 const char *how_comment; 526 const char *how_jump; 527 const char *how_global; 528 const char *how_space; 529 const char *how_align_short; 530 const char *how_align_long; 531 const char *how_default_as_switches; 532 const char *how_bfd_target; 533 enum bfd_architecture how_bfd_arch; 534 const unsigned char *how_jtab; 535 int how_jtab_size; /* Size of the jtab entry. */ 536 int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5. */ 537 }; 538 539 static const struct mac 540 mtable[] = 541 { 542 { 543 #define MARM 0 544 "arm", ".byte", ".short", ".long", ".asciz", "@", 545 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 546 ".global", ".space", ".align\t2",".align\t4", "-mapcs-32", 547 "pe-arm-little", bfd_arch_arm, 548 arm_jtab, sizeof (arm_jtab), 8 549 } 550 , 551 { 552 #define M386 1 553 "i386", ".byte", ".short", ".long", ".asciz", "#", 554 "jmp *", ".global", ".space", ".align\t2",".align\t4", "", 555 "pe-i386",bfd_arch_i386, 556 i386_jtab, sizeof (i386_jtab), 2 557 } 558 , 559 { 560 #define MPPC 2 561 "ppc", ".byte", ".short", ".long", ".asciz", "#", 562 "jmp *", ".global", ".space", ".align\t2",".align\t4", "", 563 "pe-powerpcle",bfd_arch_powerpc, 564 ppc_jtab, sizeof (ppc_jtab), 0 565 } 566 , 567 { 568 #define MTHUMB 3 569 "thumb", ".byte", ".short", ".long", ".asciz", "@", 570 "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip", 571 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork", 572 "pe-arm-little", bfd_arch_arm, 573 thumb_jtab, sizeof (thumb_jtab), 12 574 } 575 , 576 #define MARM_INTERWORK 4 577 { 578 "arm_interwork", ".byte", ".short", ".long", ".asciz", "@", 579 "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long", 580 ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork", 581 "pe-arm-little", bfd_arch_arm, 582 arm_interwork_jtab, sizeof (arm_interwork_jtab), 12 583 } 584 , 585 { 586 #define MMCORE_BE 5 587 "mcore-be", ".byte", ".short", ".long", ".asciz", "//", 588 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 589 ".global", ".space", ".align\t2",".align\t4", "", 590 "pe-mcore-big", bfd_arch_mcore, 591 mcore_be_jtab, sizeof (mcore_be_jtab), 8 592 } 593 , 594 { 595 #define MMCORE_LE 6 596 "mcore-le", ".byte", ".short", ".long", ".asciz", "//", 597 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 598 ".global", ".space", ".align\t2",".align\t4", "-EL", 599 "pe-mcore-little", bfd_arch_mcore, 600 mcore_le_jtab, sizeof (mcore_le_jtab), 8 601 } 602 , 603 { 604 #define MMCORE_ELF 7 605 "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//", 606 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 607 ".global", ".space", ".align\t2",".align\t4", "", 608 "elf32-mcore-big", bfd_arch_mcore, 609 mcore_be_jtab, sizeof (mcore_be_jtab), 8 610 } 611 , 612 { 613 #define MMCORE_ELF_LE 8 614 "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//", 615 "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long", 616 ".global", ".space", ".align\t2",".align\t4", "-EL", 617 "elf32-mcore-little", bfd_arch_mcore, 618 mcore_le_jtab, sizeof (mcore_le_jtab), 8 619 } 620 , 621 { 622 #define MARM_EPOC 9 623 "arm-epoc", ".byte", ".short", ".long", ".asciz", "@", 624 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", 625 ".global", ".space", ".align\t2",".align\t4", "", 626 "epoc-pe-arm-little", bfd_arch_arm, 627 arm_jtab, sizeof (arm_jtab), 8 628 } 629 , 630 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 631 }; 632 633 typedef struct dlist 634 { 635 char *text; 636 struct dlist *next; 637 } 638 dlist_type; 639 640 typedef struct export 641 { 642 const char *name; 643 const char *internal_name; 644 int ordinal; 645 int constant; 646 int noname; /* Don't put name in image file. */ 647 int private; /* Don't put reference in import lib. */ 648 int data; 649 int hint; 650 int forward; /* Number of forward label, 0 means no forward. */ 651 struct export *next; 652 } 653 export_type; 654 655 /* A list of symbols which we should not export. */ 656 657 struct string_list 658 { 659 struct string_list *next; 660 char *string; 661 }; 662 663 static struct string_list *excludes; 664 665 static const char *rvaafter (int); 666 static const char *rvabefore (int); 667 static const char *asm_prefix (int); 668 static void process_def_file (const char *); 669 static void new_directive (char *); 670 static void append_import (const char *, const char *, int); 671 static void run (const char *, char *); 672 static void scan_drectve_symbols (bfd *); 673 static void scan_filtered_symbols (bfd *, void *, long, unsigned int); 674 static void add_excludes (const char *); 675 static bfd_boolean match_exclude (const char *); 676 static void set_default_excludes (void); 677 static long filter_symbols (bfd *, void *, long, unsigned int); 678 static void scan_all_symbols (bfd *); 679 static void scan_open_obj_file (bfd *); 680 static void scan_obj_file (const char *); 681 static void dump_def_info (FILE *); 682 static int sfunc (const void *, const void *); 683 static void flush_page (FILE *, long *, int, int); 684 static void gen_def_file (void); 685 static void generate_idata_ofile (FILE *); 686 static void assemble_file (const char *, const char *); 687 static void gen_exp_file (void); 688 static const char *xlate (const char *); 689 #if 0 690 static void dump_iat (FILE *, export_type *); 691 #endif 692 static char *make_label (const char *, const char *); 693 static char *make_imp_label (const char *, const char *); 694 static bfd *make_one_lib_file (export_type *, int); 695 static bfd *make_head (void); 696 static bfd *make_tail (void); 697 static void gen_lib_file (void); 698 static int pfunc (const void *, const void *); 699 static int nfunc (const void *, const void *); 700 static void remove_null_names (export_type **); 701 static void dtab (export_type **); 702 static void process_duplicates (export_type **); 703 static void fill_ordinals (export_type **); 704 static int alphafunc (const void *, const void *); 705 static void mangle_defs (void); 706 static void usage (FILE *, int); 707 static void inform (const char *, ...); 708 709 static char * 710 prefix_encode (char *start, unsigned code) 711 { 712 static char alpha[26] = "abcdefghijklmnopqrstuvwxyz"; 713 static char buf[32]; 714 char *p; 715 strcpy (buf, start); 716 p = strchr (buf, '\0'); 717 do 718 *p++ = alpha[code % sizeof (alpha)]; 719 while ((code /= sizeof (alpha)) != 0); 720 *p = '\0'; 721 return buf; 722 } 723 724 static char * 725 dlltmp (char **buf, const char *fmt) 726 { 727 if (!*buf) 728 { 729 *buf = malloc (strlen (tmp_prefix) + 64); 730 sprintf (*buf, fmt, tmp_prefix); 731 } 732 return *buf; 733 } 734 735 static void 736 inform VPARAMS ((const char * message, ...)) 737 { 738 VA_OPEN (args, message); 739 VA_FIXEDARG (args, const char *, message); 740 741 if (!verbose) 742 return; 743 744 report (message, args); 745 746 VA_CLOSE (args); 747 } 748 749 static const char * 750 rvaafter (int machine) 751 { 752 switch (machine) 753 { 754 case MARM: 755 case M386: 756 case MPPC: 757 case MTHUMB: 758 case MARM_INTERWORK: 759 case MMCORE_BE: 760 case MMCORE_LE: 761 case MMCORE_ELF: 762 case MMCORE_ELF_LE: 763 case MARM_EPOC: 764 break; 765 default: 766 /* xgettext:c-format */ 767 fatal (_("Internal error: Unknown machine type: %d"), machine); 768 break; 769 } 770 return ""; 771 } 772 773 static const char * 774 rvabefore (int machine) 775 { 776 switch (machine) 777 { 778 case MARM: 779 case M386: 780 case MPPC: 781 case MTHUMB: 782 case MARM_INTERWORK: 783 case MMCORE_BE: 784 case MMCORE_LE: 785 case MMCORE_ELF: 786 case MMCORE_ELF_LE: 787 case MARM_EPOC: 788 return ".rva\t"; 789 default: 790 /* xgettext:c-format */ 791 fatal (_("Internal error: Unknown machine type: %d"), machine); 792 break; 793 } 794 return ""; 795 } 796 797 static const char * 798 asm_prefix (int machine) 799 { 800 switch (machine) 801 { 802 case MARM: 803 case MPPC: 804 case MTHUMB: 805 case MARM_INTERWORK: 806 case MMCORE_BE: 807 case MMCORE_LE: 808 case MMCORE_ELF: 809 case MMCORE_ELF_LE: 810 case MARM_EPOC: 811 break; 812 case M386: 813 return "_"; 814 default: 815 /* xgettext:c-format */ 816 fatal (_("Internal error: Unknown machine type: %d"), machine); 817 break; 818 } 819 return ""; 820 } 821 822 #define ASM_BYTE mtable[machine].how_byte 823 #define ASM_SHORT mtable[machine].how_short 824 #define ASM_LONG mtable[machine].how_long 825 #define ASM_TEXT mtable[machine].how_asciz 826 #define ASM_C mtable[machine].how_comment 827 #define ASM_JUMP mtable[machine].how_jump 828 #define ASM_GLOBAL mtable[machine].how_global 829 #define ASM_SPACE mtable[machine].how_space 830 #define ASM_ALIGN_SHORT mtable[machine].how_align_short 831 #define ASM_RVA_BEFORE rvabefore(machine) 832 #define ASM_RVA_AFTER rvaafter(machine) 833 #define ASM_PREFIX asm_prefix(machine) 834 #define ASM_ALIGN_LONG mtable[machine].how_align_long 835 #define HOW_BFD_READ_TARGET 0 /* always default*/ 836 #define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target 837 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch 838 #define HOW_JTAB mtable[machine].how_jtab 839 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size 840 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff 841 #define ASM_SWITCHES mtable[machine].how_default_as_switches 842 843 static char **oav; 844 845 static void 846 process_def_file (const char *name) 847 { 848 FILE *f = fopen (name, FOPEN_RT); 849 850 if (!f) 851 /* xgettext:c-format */ 852 fatal (_("Can't open def file: %s"), name); 853 854 yyin = f; 855 856 /* xgettext:c-format */ 857 inform (_("Processing def file: %s"), name); 858 859 yyparse (); 860 861 inform (_("Processed def file")); 862 } 863 864 /**********************************************************************/ 865 866 /* Communications with the parser. */ 867 868 static const char *d_name; /* Arg to NAME or LIBRARY. */ 869 static int d_nfuncs; /* Number of functions exported. */ 870 static int d_named_nfuncs; /* Number of named functions exported. */ 871 static int d_low_ord; /* Lowest ordinal index. */ 872 static int d_high_ord; /* Highest ordinal index. */ 873 static export_type *d_exports; /* List of exported functions. */ 874 static export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */ 875 static dlist_type *d_list; /* Descriptions. */ 876 static dlist_type *a_list; /* Stuff to go in directives. */ 877 static int d_nforwards = 0; /* Number of forwarded exports. */ 878 879 static int d_is_dll; 880 static int d_is_exe; 881 882 int 883 yyerror (const char * err ATTRIBUTE_UNUSED) 884 { 885 /* xgettext:c-format */ 886 non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber); 887 888 return 0; 889 } 890 891 void 892 def_exports (const char *name, const char *internal_name, int ordinal, 893 int noname, int constant, int data, int private) 894 { 895 struct export *p = (struct export *) xmalloc (sizeof (*p)); 896 897 p->name = name; 898 p->internal_name = internal_name ? internal_name : name; 899 p->ordinal = ordinal; 900 p->constant = constant; 901 p->noname = noname; 902 p->private = private; 903 p->data = data; 904 p->next = d_exports; 905 d_exports = p; 906 d_nfuncs++; 907 908 if ((internal_name != NULL) 909 && (strchr (internal_name, '.') != NULL)) 910 p->forward = ++d_nforwards; 911 else 912 p->forward = 0; /* no forward */ 913 } 914 915 void 916 def_name (const char *name, int base) 917 { 918 /* xgettext:c-format */ 919 inform (_("NAME: %s base: %x"), name, base); 920 921 if (d_is_dll) 922 non_fatal (_("Can't have LIBRARY and NAME")); 923 924 d_name = name; 925 /* If --dllname not provided, use the one in the DEF file. 926 FIXME: Is this appropriate for executables? */ 927 if (! dll_name) 928 dll_name = xstrdup (name); 929 d_is_exe = 1; 930 } 931 932 void 933 def_library (const char *name, int base) 934 { 935 /* xgettext:c-format */ 936 inform (_("LIBRARY: %s base: %x"), name, base); 937 938 if (d_is_exe) 939 non_fatal (_("Can't have LIBRARY and NAME")); 940 941 d_name = name; 942 /* If --dllname not provided, use the one in the DEF file. */ 943 if (! dll_name) 944 dll_name = xstrdup (name); 945 d_is_dll = 1; 946 } 947 948 void 949 def_description (const char *desc) 950 { 951 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 952 d->text = xstrdup (desc); 953 d->next = d_list; 954 d_list = d; 955 } 956 957 static void 958 new_directive (char *dir) 959 { 960 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); 961 d->text = xstrdup (dir); 962 d->next = a_list; 963 a_list = d; 964 } 965 966 void 967 def_heapsize (int reserve, int commit) 968 { 969 char b[200]; 970 if (commit > 0) 971 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); 972 else 973 sprintf (b, "-heap 0x%x ", reserve); 974 new_directive (xstrdup (b)); 975 } 976 977 void 978 def_stacksize (int reserve, int commit) 979 { 980 char b[200]; 981 if (commit > 0) 982 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); 983 else 984 sprintf (b, "-stack 0x%x ", reserve); 985 new_directive (xstrdup (b)); 986 } 987 988 /* append_import simply adds the given import definition to the global 989 import_list. It is used by def_import. */ 990 991 static void 992 append_import (const char *symbol_name, const char *dll_name, int func_ordinal) 993 { 994 iheadtype **pq; 995 iheadtype *q; 996 997 for (pq = &import_list; *pq != NULL; pq = &(*pq)->next) 998 { 999 if (strcmp ((*pq)->dllname, dll_name) == 0) 1000 { 1001 q = *pq; 1002 q->functail->next = xmalloc (sizeof (ifunctype)); 1003 q->functail = q->functail->next; 1004 q->functail->ord = func_ordinal; 1005 q->functail->name = xstrdup (symbol_name); 1006 q->functail->next = NULL; 1007 q->nfuncs++; 1008 return; 1009 } 1010 } 1011 1012 q = xmalloc (sizeof (iheadtype)); 1013 q->dllname = xstrdup (dll_name); 1014 q->nfuncs = 1; 1015 q->funchead = xmalloc (sizeof (ifunctype)); 1016 q->functail = q->funchead; 1017 q->next = NULL; 1018 q->functail->name = xstrdup (symbol_name); 1019 q->functail->ord = func_ordinal; 1020 q->functail->next = NULL; 1021 1022 *pq = q; 1023 } 1024 1025 /* def_import is called from within defparse.y when an IMPORT 1026 declaration is encountered. Depending on the form of the 1027 declaration, the module name may or may not need ".dll" to be 1028 appended to it, the name of the function may be stored in internal 1029 or entry, and there may or may not be an ordinal value associated 1030 with it. */ 1031 1032 /* A note regarding the parse modes: 1033 In defparse.y we have to accept import declarations which follow 1034 any one of the following forms: 1035 <func_name_in_app> = <dll_name>.<func_name_in_dll> 1036 <func_name_in_app> = <dll_name>.<number> 1037 <dll_name>.<func_name_in_dll> 1038 <dll_name>.<number> 1039 Furthermore, the dll's name may or may not end with ".dll", which 1040 complicates the parsing a little. Normally the dll's name is 1041 passed to def_import() in the "module" parameter, but when it ends 1042 with ".dll" it gets passed in "module" sans ".dll" and that needs 1043 to be reappended. 1044 1045 def_import gets five parameters: 1046 APP_NAME - the name of the function in the application, if 1047 present, or NULL if not present. 1048 MODULE - the name of the dll, possibly sans extension (ie, '.dll'). 1049 DLLEXT - the extension of the dll, if present, NULL if not present. 1050 ENTRY - the name of the function in the dll, if present, or NULL. 1051 ORD_VAL - the numerical tag of the function in the dll, if present, 1052 or NULL. Exactly one of <entry> or <ord_val> must be 1053 present (i.e., not NULL). */ 1054 1055 void 1056 def_import (const char *app_name, const char *module, const char *dllext, 1057 const char *entry, int ord_val) 1058 { 1059 const char *application_name; 1060 char *buf; 1061 1062 if (entry != NULL) 1063 application_name = entry; 1064 else 1065 { 1066 if (app_name != NULL) 1067 application_name = app_name; 1068 else 1069 application_name = ""; 1070 } 1071 1072 if (dllext != NULL) 1073 { 1074 buf = (char *) alloca (strlen (module) + strlen (dllext) + 2); 1075 sprintf (buf, "%s.%s", module, dllext); 1076 module = buf; 1077 } 1078 1079 append_import (application_name, module, ord_val); 1080 } 1081 1082 void 1083 def_version (int major, int minor) 1084 { 1085 printf ("VERSION %d.%d\n", major, minor); 1086 } 1087 1088 void 1089 def_section (const char *name, int attr) 1090 { 1091 char buf[200]; 1092 char atts[5]; 1093 char *d = atts; 1094 if (attr & 1) 1095 *d++ = 'R'; 1096 1097 if (attr & 2) 1098 *d++ = 'W'; 1099 if (attr & 4) 1100 *d++ = 'X'; 1101 if (attr & 8) 1102 *d++ = 'S'; 1103 *d++ = 0; 1104 sprintf (buf, "-attr %s %s", name, atts); 1105 new_directive (xstrdup (buf)); 1106 } 1107 1108 void 1109 def_code (int attr) 1110 { 1111 1112 def_section ("CODE", attr); 1113 } 1114 1115 void 1116 def_data (int attr) 1117 { 1118 def_section ("DATA", attr); 1119 } 1120 1121 /**********************************************************************/ 1122 1123 static void 1124 run (const char *what, char *args) 1125 { 1126 char *s; 1127 int pid, wait_status; 1128 int i; 1129 const char **argv; 1130 char *errmsg_fmt, *errmsg_arg; 1131 #if defined(__MSDOS__) && !defined(__GO32__) 1132 char *temp_base = choose_temp_base (); 1133 #else 1134 char *temp_base = NULL; 1135 #endif 1136 1137 inform ("run: %s %s", what, args); 1138 1139 /* Count the args */ 1140 i = 0; 1141 for (s = args; *s; s++) 1142 if (*s == ' ') 1143 i++; 1144 i++; 1145 argv = alloca (sizeof (char *) * (i + 3)); 1146 i = 0; 1147 argv[i++] = what; 1148 s = args; 1149 while (1) 1150 { 1151 while (*s == ' ') 1152 ++s; 1153 argv[i++] = s; 1154 while (*s != ' ' && *s != 0) 1155 s++; 1156 if (*s == 0) 1157 break; 1158 *s++ = 0; 1159 } 1160 argv[i++] = NULL; 1161 1162 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 1163 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 1164 1165 if (pid == -1) 1166 { 1167 inform (strerror (errno)); 1168 1169 fatal (errmsg_fmt, errmsg_arg); 1170 } 1171 1172 pid = pwait (pid, & wait_status, 0); 1173 1174 if (pid == -1) 1175 { 1176 /* xgettext:c-format */ 1177 fatal (_("wait: %s"), strerror (errno)); 1178 } 1179 else if (WIFSIGNALED (wait_status)) 1180 { 1181 /* xgettext:c-format */ 1182 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 1183 } 1184 else if (WIFEXITED (wait_status)) 1185 { 1186 if (WEXITSTATUS (wait_status) != 0) 1187 /* xgettext:c-format */ 1188 non_fatal (_("%s exited with status %d"), 1189 what, WEXITSTATUS (wait_status)); 1190 } 1191 else 1192 abort (); 1193 } 1194 1195 /* Look for a list of symbols to export in the .drectve section of 1196 ABFD. Pass each one to def_exports. */ 1197 1198 static void 1199 scan_drectve_symbols (bfd *abfd) 1200 { 1201 asection * s; 1202 int size; 1203 char * buf; 1204 char * p; 1205 char * e; 1206 1207 /* Look for .drectve's */ 1208 s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME); 1209 1210 if (s == NULL) 1211 return; 1212 1213 size = bfd_get_section_size_before_reloc (s); 1214 buf = xmalloc (size); 1215 1216 bfd_get_section_contents (abfd, s, buf, 0, size); 1217 1218 /* xgettext:c-format */ 1219 inform (_("Sucking in info from %s section in %s"), 1220 DRECTVE_SECTION_NAME, bfd_get_filename (abfd)); 1221 1222 /* Search for -export: strings. The exported symbols can optionally 1223 have type tags (eg., -export:foo,data), so handle those as well. 1224 Currently only data tag is supported. */ 1225 p = buf; 1226 e = buf + size; 1227 while (p < e) 1228 { 1229 if (p[0] == '-' 1230 && strncmp (p, "-export:", 8) == 0) 1231 { 1232 char * name; 1233 char * c; 1234 flagword flags = BSF_FUNCTION; 1235 1236 p += 8; 1237 name = p; 1238 while (p < e && *p != ',' && *p != ' ' && *p != '-') 1239 p++; 1240 c = xmalloc (p - name + 1); 1241 memcpy (c, name, p - name); 1242 c[p - name] = 0; 1243 if (p < e && *p == ',') /* found type tag. */ 1244 { 1245 char *tag_start = ++p; 1246 while (p < e && *p != ' ' && *p != '-') 1247 p++; 1248 if (strncmp (tag_start, "data", 4) == 0) 1249 flags &= ~BSF_FUNCTION; 1250 } 1251 1252 /* FIXME: The 5th arg is for the `constant' field. 1253 What should it be? Not that it matters since it's not 1254 currently useful. */ 1255 def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0); 1256 1257 if (add_stdcall_alias && strchr (c, '@')) 1258 { 1259 int lead_at = (*c == '@') ; 1260 char *exported_name = xstrdup (c + lead_at); 1261 char *atsym = strchr (exported_name, '@'); 1262 *atsym = '\0'; 1263 /* Note: stdcall alias symbols can never be data. */ 1264 def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0); 1265 } 1266 } 1267 else 1268 p++; 1269 } 1270 free (buf); 1271 } 1272 1273 /* Look through the symbols in MINISYMS, and add each one to list of 1274 symbols to export. */ 1275 1276 static void 1277 scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount, 1278 unsigned int size) 1279 { 1280 asymbol *store; 1281 bfd_byte *from, *fromend; 1282 1283 store = bfd_make_empty_symbol (abfd); 1284 if (store == NULL) 1285 bfd_fatal (bfd_get_filename (abfd)); 1286 1287 from = (bfd_byte *) minisyms; 1288 fromend = from + symcount * size; 1289 for (; from < fromend; from += size) 1290 { 1291 asymbol *sym; 1292 const char *symbol_name; 1293 1294 sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store); 1295 if (sym == NULL) 1296 bfd_fatal (bfd_get_filename (abfd)); 1297 1298 symbol_name = bfd_asymbol_name (sym); 1299 if (bfd_get_symbol_leading_char (abfd) == symbol_name[0]) 1300 ++symbol_name; 1301 1302 def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 1303 ! (sym->flags & BSF_FUNCTION), 0); 1304 1305 if (add_stdcall_alias && strchr (symbol_name, '@')) 1306 { 1307 int lead_at = (*symbol_name == '@'); 1308 char *exported_name = xstrdup (symbol_name + lead_at); 1309 char *atsym = strchr (exported_name, '@'); 1310 *atsym = '\0'; 1311 /* Note: stdcall alias symbols can never be data. */ 1312 def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0); 1313 } 1314 } 1315 } 1316 1317 /* Add a list of symbols to exclude. */ 1318 1319 static void 1320 add_excludes (const char *new_excludes) 1321 { 1322 char *local_copy; 1323 char *exclude_string; 1324 1325 local_copy = xstrdup (new_excludes); 1326 1327 exclude_string = strtok (local_copy, ",:"); 1328 for (; exclude_string; exclude_string = strtok (NULL, ",:")) 1329 { 1330 struct string_list *new_exclude; 1331 1332 new_exclude = ((struct string_list *) 1333 xmalloc (sizeof (struct string_list))); 1334 new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2); 1335 /* Don't add a leading underscore for fastcall symbols. */ 1336 if (*exclude_string == '@') 1337 sprintf (new_exclude->string, "%s", exclude_string); 1338 else 1339 sprintf (new_exclude->string, "_%s", exclude_string); 1340 new_exclude->next = excludes; 1341 excludes = new_exclude; 1342 1343 /* xgettext:c-format */ 1344 inform (_("Excluding symbol: %s"), exclude_string); 1345 } 1346 1347 free (local_copy); 1348 } 1349 1350 /* See if STRING is on the list of symbols to exclude. */ 1351 1352 static bfd_boolean 1353 match_exclude (const char *string) 1354 { 1355 struct string_list *excl_item; 1356 1357 for (excl_item = excludes; excl_item; excl_item = excl_item->next) 1358 if (strcmp (string, excl_item->string) == 0) 1359 return TRUE; 1360 return FALSE; 1361 } 1362 1363 /* Add the default list of symbols to exclude. */ 1364 1365 static void 1366 set_default_excludes (void) 1367 { 1368 add_excludes (default_excludes); 1369 } 1370 1371 /* Choose which symbols to export. */ 1372 1373 static long 1374 filter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size) 1375 { 1376 bfd_byte *from, *fromend, *to; 1377 asymbol *store; 1378 1379 store = bfd_make_empty_symbol (abfd); 1380 if (store == NULL) 1381 bfd_fatal (bfd_get_filename (abfd)); 1382 1383 from = (bfd_byte *) minisyms; 1384 fromend = from + symcount * size; 1385 to = (bfd_byte *) minisyms; 1386 1387 for (; from < fromend; from += size) 1388 { 1389 int keep = 0; 1390 asymbol *sym; 1391 1392 sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store); 1393 if (sym == NULL) 1394 bfd_fatal (bfd_get_filename (abfd)); 1395 1396 /* Check for external and defined only symbols. */ 1397 keep = (((sym->flags & BSF_GLOBAL) != 0 1398 || (sym->flags & BSF_WEAK) != 0 1399 || bfd_is_com_section (sym->section)) 1400 && ! bfd_is_und_section (sym->section)); 1401 1402 keep = keep && ! match_exclude (sym->name); 1403 1404 if (keep) 1405 { 1406 memcpy (to, from, size); 1407 to += size; 1408 } 1409 } 1410 1411 return (to - (bfd_byte *) minisyms) / size; 1412 } 1413 1414 /* Export all symbols in ABFD, except for ones we were told not to 1415 export. */ 1416 1417 static void 1418 scan_all_symbols (bfd *abfd) 1419 { 1420 long symcount; 1421 void *minisyms; 1422 unsigned int size; 1423 1424 /* Ignore bfds with an import descriptor table. We assume that any 1425 such BFD contains symbols which are exported from another DLL, 1426 and we don't want to reexport them from here. */ 1427 if (bfd_get_section_by_name (abfd, ".idata$4")) 1428 return; 1429 1430 if (! (bfd_get_file_flags (abfd) & HAS_SYMS)) 1431 { 1432 /* xgettext:c-format */ 1433 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 1434 return; 1435 } 1436 1437 symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size); 1438 if (symcount < 0) 1439 bfd_fatal (bfd_get_filename (abfd)); 1440 1441 if (symcount == 0) 1442 { 1443 /* xgettext:c-format */ 1444 non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); 1445 return; 1446 } 1447 1448 /* Discard the symbols we don't want to export. It's OK to do this 1449 in place; we'll free the storage anyway. */ 1450 1451 symcount = filter_symbols (abfd, minisyms, symcount, size); 1452 scan_filtered_symbols (abfd, minisyms, symcount, size); 1453 1454 free (minisyms); 1455 } 1456 1457 /* Look at the object file to decide which symbols to export. */ 1458 1459 static void 1460 scan_open_obj_file (bfd *abfd) 1461 { 1462 if (export_all_symbols) 1463 scan_all_symbols (abfd); 1464 else 1465 scan_drectve_symbols (abfd); 1466 1467 /* FIXME: we ought to read in and block out the base relocations. */ 1468 1469 /* xgettext:c-format */ 1470 inform (_("Done reading %s"), bfd_get_filename (abfd)); 1471 } 1472 1473 static void 1474 scan_obj_file (const char *filename) 1475 { 1476 bfd * f = bfd_openr (filename, 0); 1477 1478 if (!f) 1479 /* xgettext:c-format */ 1480 fatal (_("Unable to open object file: %s"), filename); 1481 1482 /* xgettext:c-format */ 1483 inform (_("Scanning object file %s"), filename); 1484 1485 if (bfd_check_format (f, bfd_archive)) 1486 { 1487 bfd *arfile = bfd_openr_next_archived_file (f, 0); 1488 while (arfile) 1489 { 1490 if (bfd_check_format (arfile, bfd_object)) 1491 scan_open_obj_file (arfile); 1492 bfd_close (arfile); 1493 arfile = bfd_openr_next_archived_file (f, arfile); 1494 } 1495 1496 #ifdef DLLTOOL_MCORE_ELF 1497 if (mcore_elf_out_file) 1498 inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename); 1499 #endif 1500 } 1501 else if (bfd_check_format (f, bfd_object)) 1502 { 1503 scan_open_obj_file (f); 1504 1505 #ifdef DLLTOOL_MCORE_ELF 1506 if (mcore_elf_out_file) 1507 mcore_elf_cache_filename ((char *) filename); 1508 #endif 1509 } 1510 1511 bfd_close (f); 1512 } 1513 1514 /**********************************************************************/ 1515 1516 static void 1517 dump_def_info (FILE *f) 1518 { 1519 int i; 1520 export_type *exp; 1521 fprintf (f, "%s ", ASM_C); 1522 for (i = 0; oav[i]; i++) 1523 fprintf (f, "%s ", oav[i]); 1524 fprintf (f, "\n"); 1525 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 1526 { 1527 fprintf (f, "%s %d = %s %s @ %d %s%s%s%s\n", 1528 ASM_C, 1529 i, 1530 exp->name, 1531 exp->internal_name, 1532 exp->ordinal, 1533 exp->noname ? "NONAME " : "", 1534 exp->private ? "PRIVATE " : "", 1535 exp->constant ? "CONSTANT" : "", 1536 exp->data ? "DATA" : ""); 1537 } 1538 } 1539 1540 /* Generate the .exp file. */ 1541 1542 static int 1543 sfunc (const void *a, const void *b) 1544 { 1545 return *(const long *) a - *(const long *) b; 1546 } 1547 1548 static void 1549 flush_page (FILE *f, long *need, int page_addr, int on_page) 1550 { 1551 int i; 1552 1553 /* Flush this page. */ 1554 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", 1555 ASM_LONG, 1556 page_addr, 1557 ASM_C); 1558 fprintf (f, "\t%s\t0x%x\t%s Size of block\n", 1559 ASM_LONG, 1560 (on_page * 2) + (on_page & 1) * 2 + 8, 1561 ASM_C); 1562 1563 for (i = 0; i < on_page; i++) 1564 { 1565 long needed = need[i]; 1566 1567 if (needed) 1568 needed = ((needed - page_addr) | 0x3000) & 0xffff; 1569 1570 fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, needed); 1571 } 1572 1573 /* And padding */ 1574 if (on_page & 1) 1575 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000); 1576 } 1577 1578 static void 1579 gen_def_file (void) 1580 { 1581 int i; 1582 export_type *exp; 1583 1584 inform (_("Adding exports to output file")); 1585 1586 fprintf (output_def, ";"); 1587 for (i = 0; oav[i]; i++) 1588 fprintf (output_def, " %s", oav[i]); 1589 1590 fprintf (output_def, "\nEXPORTS\n"); 1591 1592 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 1593 { 1594 char *quote = strchr (exp->name, '.') ? "\"" : ""; 1595 char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS); 1596 1597 if (res) 1598 { 1599 fprintf (output_def,";\t%s\n", res); 1600 free (res); 1601 } 1602 1603 if (strcmp (exp->name, exp->internal_name) == 0) 1604 { 1605 fprintf (output_def, "\t%s%s%s @ %d%s%s%s\n", 1606 quote, 1607 exp->name, 1608 quote, 1609 exp->ordinal, 1610 exp->noname ? " NONAME" : "", 1611 exp->private ? "PRIVATE " : "", 1612 exp->data ? " DATA" : ""); 1613 } 1614 else 1615 { 1616 char * quote1 = strchr (exp->internal_name, '.') ? "\"" : ""; 1617 /* char *alias = */ 1618 fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s%s\n", 1619 quote, 1620 exp->name, 1621 quote, 1622 quote1, 1623 exp->internal_name, 1624 quote1, 1625 exp->ordinal, 1626 exp->noname ? " NONAME" : "", 1627 exp->private ? "PRIVATE " : "", 1628 exp->data ? " DATA" : ""); 1629 } 1630 } 1631 1632 inform (_("Added exports to output file")); 1633 } 1634 1635 /* generate_idata_ofile generates the portable assembly source code 1636 for the idata sections. It appends the source code to the end of 1637 the file. */ 1638 1639 static void 1640 generate_idata_ofile (FILE *filvar) 1641 { 1642 iheadtype *headptr; 1643 ifunctype *funcptr; 1644 int headindex; 1645 int funcindex; 1646 int nheads; 1647 1648 if (import_list == NULL) 1649 return; 1650 1651 fprintf (filvar, "%s Import data sections\n", ASM_C); 1652 fprintf (filvar, "\n\t.section\t.idata$2\n"); 1653 fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL); 1654 fprintf (filvar, "doi_idata:\n"); 1655 1656 nheads = 0; 1657 for (headptr = import_list; headptr != NULL; headptr = headptr->next) 1658 { 1659 fprintf (filvar, "\t%slistone%d%s\t%s %s\n", 1660 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER, 1661 ASM_C, headptr->dllname); 1662 fprintf (filvar, "\t%s\t0\n", ASM_LONG); 1663 fprintf (filvar, "\t%s\t0\n", ASM_LONG); 1664 fprintf (filvar, "\t%sdllname%d%s\n", 1665 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); 1666 fprintf (filvar, "\t%slisttwo%d%s\n\n", 1667 ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); 1668 nheads++; 1669 } 1670 1671 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */ 1672 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */ 1673 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */ 1674 fprintf (filvar, "\t%s\t0\n", ASM_LONG); 1675 fprintf (filvar, "\t%s\t0\n", ASM_LONG); 1676 1677 fprintf (filvar, "\n\t.section\t.idata$4\n"); 1678 headindex = 0; 1679 for (headptr = import_list; headptr != NULL; headptr = headptr->next) 1680 { 1681 fprintf (filvar, "listone%d:\n", headindex); 1682 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) 1683 fprintf (filvar, "\t%sfuncptr%d_%d%s\n", 1684 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); 1685 fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */ 1686 headindex++; 1687 } 1688 1689 fprintf (filvar, "\n\t.section\t.idata$5\n"); 1690 headindex = 0; 1691 for (headptr = import_list; headptr != NULL; headptr = headptr->next) 1692 { 1693 fprintf (filvar, "listtwo%d:\n", headindex); 1694 for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) 1695 fprintf (filvar, "\t%sfuncptr%d_%d%s\n", 1696 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); 1697 fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */ 1698 headindex++; 1699 } 1700 1701 fprintf (filvar, "\n\t.section\t.idata$6\n"); 1702 headindex = 0; 1703 for (headptr = import_list; headptr != NULL; headptr = headptr->next) 1704 { 1705 funcindex = 0; 1706 for (funcptr = headptr->funchead; funcptr != NULL; 1707 funcptr = funcptr->next) 1708 { 1709 fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex); 1710 fprintf (filvar,"\t%s\t%d\n", ASM_SHORT, 1711 ((funcptr->ord) & 0xFFFF)); 1712 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name); 1713 fprintf (filvar,"\t%s\t0\n", ASM_BYTE); 1714 funcindex++; 1715 } 1716 headindex++; 1717 } 1718 1719 fprintf (filvar, "\n\t.section\t.idata$7\n"); 1720 headindex = 0; 1721 for (headptr = import_list; headptr != NULL; headptr = headptr->next) 1722 { 1723 fprintf (filvar,"dllname%d:\n", headindex); 1724 fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname); 1725 fprintf (filvar,"\t%s\t0\n", ASM_BYTE); 1726 headindex++; 1727 } 1728 } 1729 1730 /* Assemble the specified file. */ 1731 static void 1732 assemble_file (const char * source, const char * dest) 1733 { 1734 char * cmd; 1735 1736 cmd = (char *) alloca (strlen (ASM_SWITCHES) + strlen (as_flags) 1737 + strlen (source) + strlen (dest) + 50); 1738 1739 sprintf (cmd, "%s %s -o %s %s", ASM_SWITCHES, as_flags, dest, source); 1740 1741 run (as_name, cmd); 1742 } 1743 1744 static void 1745 gen_exp_file (void) 1746 { 1747 FILE *f; 1748 int i; 1749 export_type *exp; 1750 dlist_type *dl; 1751 1752 /* xgettext:c-format */ 1753 inform (_("Generating export file: %s"), exp_name); 1754 1755 f = fopen (TMP_ASM, FOPEN_WT); 1756 if (!f) 1757 /* xgettext:c-format */ 1758 fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM); 1759 1760 /* xgettext:c-format */ 1761 inform (_("Opened temporary file: %s"), TMP_ASM); 1762 1763 dump_def_info (f); 1764 1765 if (d_exports) 1766 { 1767 fprintf (f, "\t.section .edata\n\n"); 1768 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); 1769 fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0), 1770 ASM_C); 1771 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); 1772 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 1773 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C); 1774 1775 1776 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C); 1777 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n", 1778 ASM_C, 1779 d_named_nfuncs, d_low_ord, d_high_ord); 1780 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, 1781 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C); 1782 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 1783 1784 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", 1785 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 1786 1787 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 1788 1789 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name); 1790 1791 1792 fprintf(f,"%s Export address Table\n", ASM_C); 1793 fprintf(f,"\t%s\n", ASM_ALIGN_LONG); 1794 fprintf (f, "afuncs:\n"); 1795 i = d_low_ord; 1796 1797 for (exp = d_exports; exp; exp = exp->next) 1798 { 1799 if (exp->ordinal != i) 1800 { 1801 #if 0 1802 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n", 1803 ASM_SPACE, 1804 (exp->ordinal - i) * 4, 1805 ASM_C, 1806 i, exp->ordinal - 1); 1807 i = exp->ordinal; 1808 #endif 1809 while (i < exp->ordinal) 1810 { 1811 fprintf(f,"\t%s\t0\n", ASM_LONG); 1812 i++; 1813 } 1814 } 1815 1816 if (exp->forward == 0) 1817 { 1818 if (exp->internal_name[0] == '@') 1819 fprintf (f, "\t%s%s%s\t%s %d\n", ASM_RVA_BEFORE, 1820 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1821 else 1822 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, 1823 ASM_PREFIX, 1824 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1825 } 1826 else 1827 fprintf (f, "\t%sf%d%s\t%s %d\n", ASM_RVA_BEFORE, 1828 exp->forward, ASM_RVA_AFTER, ASM_C, exp->ordinal); 1829 i++; 1830 } 1831 1832 fprintf (f,"%s Export Name Pointer Table\n", ASM_C); 1833 fprintf (f, "anames:\n"); 1834 1835 for (i = 0; (exp = d_exports_lexically[i]); i++) 1836 { 1837 if (!exp->noname || show_allnames) 1838 fprintf (f, "\t%sn%d%s\n", 1839 ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER); 1840 } 1841 1842 fprintf (f,"%s Export Oridinal Table\n", ASM_C); 1843 fprintf (f, "anords:\n"); 1844 for (i = 0; (exp = d_exports_lexically[i]); i++) 1845 { 1846 if (!exp->noname || show_allnames) 1847 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord); 1848 } 1849 1850 fprintf(f,"%s Export Name Table\n", ASM_C); 1851 for (i = 0; (exp = d_exports_lexically[i]); i++) 1852 { 1853 if (!exp->noname || show_allnames) 1854 fprintf (f, "n%d: %s \"%s\"\n", 1855 exp->ordinal, ASM_TEXT, xlate (exp->name)); 1856 if (exp->forward != 0) 1857 fprintf (f, "f%d: %s \"%s\"\n", 1858 exp->forward, ASM_TEXT, exp->internal_name); 1859 } 1860 1861 if (a_list) 1862 { 1863 fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME); 1864 for (dl = a_list; dl; dl = dl->next) 1865 { 1866 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text); 1867 } 1868 } 1869 1870 if (d_list) 1871 { 1872 fprintf (f, "\t.section .rdata\n"); 1873 for (dl = d_list; dl; dl = dl->next) 1874 { 1875 char *p; 1876 int l; 1877 1878 /* We don't output as ascii because there can 1879 be quote characters in the string. */ 1880 l = 0; 1881 for (p = dl->text; *p; p++) 1882 { 1883 if (l == 0) 1884 fprintf (f, "\t%s\t", ASM_BYTE); 1885 else 1886 fprintf (f, ","); 1887 fprintf (f, "%d", *p); 1888 if (p[1] == 0) 1889 { 1890 fprintf (f, ",0\n"); 1891 break; 1892 } 1893 if (++l == 10) 1894 { 1895 fprintf (f, "\n"); 1896 l = 0; 1897 } 1898 } 1899 } 1900 } 1901 } 1902 1903 1904 /* Add to the output file a way of getting to the exported names 1905 without using the import library. */ 1906 if (add_indirect) 1907 { 1908 fprintf (f, "\t.section\t.rdata\n"); 1909 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 1910 if (!exp->noname || show_allnames) 1911 { 1912 /* We use a single underscore for MS compatibility, and a 1913 double underscore for backward compatibility with old 1914 cygwin releases. */ 1915 if (create_compat_implib) 1916 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); 1917 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); 1918 if (create_compat_implib) 1919 fprintf (f, "__imp_%s:\n", exp->name); 1920 fprintf (f, "_imp__%s:\n", exp->name); 1921 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name); 1922 } 1923 } 1924 1925 /* Dump the reloc section if a base file is provided. */ 1926 if (base_file) 1927 { 1928 int addr; 1929 long need[PAGE_SIZE]; 1930 long page_addr; 1931 int numbytes; 1932 int num_entries; 1933 long *copy; 1934 int j; 1935 int on_page; 1936 fprintf (f, "\t.section\t.init\n"); 1937 fprintf (f, "lab:\n"); 1938 1939 fseek (base_file, 0, SEEK_END); 1940 numbytes = ftell (base_file); 1941 fseek (base_file, 0, SEEK_SET); 1942 copy = xmalloc (numbytes); 1943 fread (copy, 1, numbytes, base_file); 1944 num_entries = numbytes / sizeof (long); 1945 1946 1947 fprintf (f, "\t.section\t.reloc\n"); 1948 if (num_entries) 1949 { 1950 int src; 1951 int dst = 0; 1952 int last = -1; 1953 qsort (copy, num_entries, sizeof (long), sfunc); 1954 /* Delete duplicates */ 1955 for (src = 0; src < num_entries; src++) 1956 { 1957 if (last != copy[src]) 1958 last = copy[dst++] = copy[src]; 1959 } 1960 num_entries = dst; 1961 addr = copy[0]; 1962 page_addr = addr & PAGE_MASK; /* work out the page addr */ 1963 on_page = 0; 1964 for (j = 0; j < num_entries; j++) 1965 { 1966 addr = copy[j]; 1967 if ((addr & PAGE_MASK) != page_addr) 1968 { 1969 flush_page (f, need, page_addr, on_page); 1970 on_page = 0; 1971 page_addr = addr & PAGE_MASK; 1972 } 1973 need[on_page++] = addr; 1974 } 1975 flush_page (f, need, page_addr, on_page); 1976 1977 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ 1978 } 1979 } 1980 1981 generate_idata_ofile (f); 1982 1983 fclose (f); 1984 1985 /* Assemble the file. */ 1986 assemble_file (TMP_ASM, exp_name); 1987 1988 if (dontdeltemps == 0) 1989 unlink (TMP_ASM); 1990 1991 inform (_("Generated exports file")); 1992 } 1993 1994 static const char * 1995 xlate (const char *name) 1996 { 1997 int lead_at = (*name == '@'); 1998 1999 if (add_underscore && !lead_at) 2000 { 2001 char *copy = xmalloc (strlen (name) + 2); 2002 2003 copy[0] = '_'; 2004 strcpy (copy + 1, name); 2005 name = copy; 2006 } 2007 2008 if (killat) 2009 { 2010 char *p; 2011 2012 name += lead_at; 2013 p = strchr (name, '@'); 2014 if (p) 2015 *p = 0; 2016 } 2017 return name; 2018 } 2019 2020 /**********************************************************************/ 2021 2022 #if 0 2023 2024 static void 2025 dump_iat (FILE *f, export_type *exp) 2026 { 2027 if (exp->noname && !show_allnames ) 2028 { 2029 fprintf (f, "\t%s\t0x%08x\n", 2030 ASM_LONG, 2031 exp->ordinal | 0x80000000); /* hint or orindal ?? */ 2032 } 2033 else 2034 { 2035 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE, 2036 exp->ordinal, 2037 ASM_RVA_AFTER); 2038 } 2039 } 2040 2041 #endif 2042 2043 typedef struct 2044 { 2045 int id; 2046 const char *name; 2047 int flags; 2048 int align; 2049 asection *sec; 2050 asymbol *sym; 2051 asymbol **sympp; 2052 int size; 2053 unsigned char *data; 2054 } sinfo; 2055 2056 #ifndef DLLTOOL_PPC 2057 2058 #define TEXT 0 2059 #define DATA 1 2060 #define BSS 2 2061 #define IDATA7 3 2062 #define IDATA5 4 2063 #define IDATA4 5 2064 #define IDATA6 6 2065 2066 #define NSECS 7 2067 2068 #define TEXT_SEC_FLAGS \ 2069 (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS) 2070 #define DATA_SEC_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA) 2071 #define BSS_SEC_FLAGS SEC_ALLOC 2072 2073 #define INIT_SEC_DATA(id, name, flags, align) \ 2074 { id, name, flags, align, NULL, NULL, NULL, 0, NULL } 2075 static sinfo secdata[NSECS] = 2076 { 2077 INIT_SEC_DATA (TEXT, ".text", TEXT_SEC_FLAGS, 2), 2078 INIT_SEC_DATA (DATA, ".data", DATA_SEC_FLAGS, 2), 2079 INIT_SEC_DATA (BSS, ".bss", BSS_SEC_FLAGS, 2), 2080 INIT_SEC_DATA (IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2), 2081 INIT_SEC_DATA (IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2), 2082 INIT_SEC_DATA (IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2), 2083 INIT_SEC_DATA (IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1) 2084 }; 2085 2086 #else 2087 2088 /* Sections numbered to make the order the same as other PowerPC NT 2089 compilers. This also keeps funny alignment thingies from happening. */ 2090 #define TEXT 0 2091 #define PDATA 1 2092 #define RDATA 2 2093 #define IDATA5 3 2094 #define IDATA4 4 2095 #define IDATA6 5 2096 #define IDATA7 6 2097 #define DATA 7 2098 #define BSS 8 2099 2100 #define NSECS 9 2101 2102 static sinfo secdata[NSECS] = 2103 { 2104 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3}, 2105 { PDATA, ".pdata", SEC_HAS_CONTENTS, 2}, 2106 { RDATA, ".reldata", SEC_HAS_CONTENTS, 2}, 2107 { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, 2108 { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, 2109 { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}, 2110 { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, 2111 { DATA, ".data", SEC_DATA, 2}, 2112 { BSS, ".bss", 0, 2} 2113 }; 2114 2115 #endif 2116 2117 /* This is what we're trying to make. We generate the imp symbols with 2118 both single and double underscores, for compatibility. 2119 2120 .text 2121 .global _GetFileVersionInfoSizeW@8 2122 .global __imp_GetFileVersionInfoSizeW@8 2123 _GetFileVersionInfoSizeW@8: 2124 jmp * __imp_GetFileVersionInfoSizeW@8 2125 .section .idata$7 # To force loading of head 2126 .long __version_a_head 2127 # Import Address Table 2128 .section .idata$5 2129 __imp_GetFileVersionInfoSizeW@8: 2130 .rva ID2 2131 2132 # Import Lookup Table 2133 .section .idata$4 2134 .rva ID2 2135 # Hint/Name table 2136 .section .idata$6 2137 ID2: .short 2 2138 .asciz "GetFileVersionInfoSizeW" 2139 2140 2141 For the PowerPC, here's the variation on the above scheme: 2142 2143 # Rather than a simple "jmp *", the code to get to the dll function 2144 # looks like: 2145 .text 2146 lwz r11,[tocv]__imp_function_name(r2) 2147 # RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name 2148 lwz r12,0(r11) 2149 stw r2,4(r1) 2150 mtctr r12 2151 lwz r2,4(r11) 2152 bctr */ 2153 2154 static char * 2155 make_label (const char *prefix, const char *name) 2156 { 2157 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); 2158 char *copy = xmalloc (len +1 ); 2159 2160 strcpy (copy, ASM_PREFIX); 2161 strcat (copy, prefix); 2162 strcat (copy, name); 2163 return copy; 2164 } 2165 2166 static char * 2167 make_imp_label (const char *prefix, const char *name) 2168 { 2169 int len; 2170 char *copy; 2171 2172 if (name[0] == '@') 2173 { 2174 len = strlen (prefix) + strlen (name); 2175 copy = xmalloc (len + 1); 2176 strcpy (copy, prefix); 2177 strcat (copy, name); 2178 } 2179 else 2180 { 2181 len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); 2182 copy = xmalloc (len + 1); 2183 strcpy (copy, prefix); 2184 strcat (copy, ASM_PREFIX); 2185 strcat (copy, name); 2186 } 2187 return copy; 2188 } 2189 2190 static bfd * 2191 make_one_lib_file (export_type *exp, int i) 2192 { 2193 #if 0 2194 { 2195 char *name; 2196 FILE *f; 2197 const char *prefix = "d"; 2198 char *dest; 2199 2200 name = (char *) alloca (strlen (prefix) + 10); 2201 sprintf (name, "%ss%05d.s", prefix, i); 2202 f = fopen (name, FOPEN_WT); 2203 fprintf (f, "\t.text\n"); 2204 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name); 2205 if (create_compat_implib) 2206 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); 2207 fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); 2208 if (create_compat_implib) 2209 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX, 2210 exp->name, ASM_JUMP, exp->name); 2211 2212 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C); 2213 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label); 2214 2215 2216 fprintf (f,"%s Import Address Table\n", ASM_C); 2217 2218 fprintf (f, "\t.section .idata$5\n"); 2219 if (create_compat_implib) 2220 fprintf (f, "__imp_%s:\n", exp->name); 2221 fprintf (f, "_imp__%s:\n", exp->name); 2222 2223 dump_iat (f, exp); 2224 2225 fprintf (f, "\n%s Import Lookup Table\n", ASM_C); 2226 fprintf (f, "\t.section .idata$4\n"); 2227 2228 dump_iat (f, exp); 2229 2230 if(!exp->noname || show_allnames) 2231 { 2232 fprintf (f, "%s Hint/Name table\n", ASM_C); 2233 fprintf (f, "\t.section .idata$6\n"); 2234 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint); 2235 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name)); 2236 } 2237 2238 fclose (f); 2239 2240 dest = (char *) alloca (strlen (prefix) + 10); 2241 sprintf (dest, "%ss%05d.o", prefix, i); 2242 assemble_file (name, dest); 2243 } 2244 #else /* if 0 */ 2245 { 2246 bfd * abfd; 2247 asymbol * exp_label; 2248 asymbol * iname = 0; 2249 asymbol * iname2; 2250 asymbol * iname_lab; 2251 asymbol ** iname_lab_pp; 2252 asymbol ** iname_pp; 2253 #ifdef DLLTOOL_PPC 2254 asymbol ** fn_pp; 2255 asymbol ** toc_pp; 2256 #define EXTRA 2 2257 #endif 2258 #ifndef EXTRA 2259 #define EXTRA 0 2260 #endif 2261 asymbol * ptrs[NSECS + 4 + EXTRA + 1]; 2262 flagword applicable; 2263 2264 char * outname = xmalloc (strlen (TMP_STUB) + 10); 2265 int oidx = 0; 2266 2267 2268 sprintf (outname, "%s%05d.o", TMP_STUB, i); 2269 2270 abfd = bfd_openw (outname, HOW_BFD_WRITE_TARGET); 2271 2272 if (!abfd) 2273 /* xgettext:c-format */ 2274 fatal (_("bfd_open failed open stub file: %s"), outname); 2275 2276 /* xgettext:c-format */ 2277 inform (_("Creating stub file: %s"), outname); 2278 2279 bfd_set_format (abfd, bfd_object); 2280 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); 2281 2282 #ifdef DLLTOOL_ARM 2283 if (machine == MARM_INTERWORK || machine == MTHUMB) 2284 bfd_set_private_flags (abfd, F_INTERWORK); 2285 #endif 2286 2287 applicable = bfd_applicable_section_flags (abfd); 2288 2289 /* First make symbols for the sections. */ 2290 for (i = 0; i < NSECS; i++) 2291 { 2292 sinfo *si = secdata + i; 2293 if (si->id != i) 2294 abort(); 2295 si->sec = bfd_make_section_old_way (abfd, si->name); 2296 bfd_set_section_flags (abfd, 2297 si->sec, 2298 si->flags & applicable); 2299 2300 bfd_set_section_alignment(abfd, si->sec, si->align); 2301 si->sec->output_section = si->sec; 2302 si->sym = bfd_make_empty_symbol(abfd); 2303 si->sym->name = si->sec->name; 2304 si->sym->section = si->sec; 2305 si->sym->flags = BSF_LOCAL; 2306 si->sym->value = 0; 2307 ptrs[oidx] = si->sym; 2308 si->sympp = ptrs + oidx; 2309 si->size = 0; 2310 si->data = NULL; 2311 2312 oidx++; 2313 } 2314 2315 if (! exp->data) 2316 { 2317 exp_label = bfd_make_empty_symbol (abfd); 2318 exp_label->name = make_imp_label ("", exp->name); 2319 2320 /* On PowerPC, the function name points to a descriptor in 2321 the rdata section, the first element of which is a 2322 pointer to the code (..function_name), and the second 2323 points to the .toc. */ 2324 #ifdef DLLTOOL_PPC 2325 if (machine == MPPC) 2326 exp_label->section = secdata[RDATA].sec; 2327 else 2328 #endif 2329 exp_label->section = secdata[TEXT].sec; 2330 2331 exp_label->flags = BSF_GLOBAL; 2332 exp_label->value = 0; 2333 2334 #ifdef DLLTOOL_ARM 2335 if (machine == MTHUMB) 2336 bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC); 2337 #endif 2338 ptrs[oidx++] = exp_label; 2339 } 2340 2341 /* Generate imp symbols with one underscore for Microsoft 2342 compatibility, and with two underscores for backward 2343 compatibility with old versions of cygwin. */ 2344 if (create_compat_implib) 2345 { 2346 iname = bfd_make_empty_symbol (abfd); 2347 iname->name = make_imp_label ("___imp", exp->name); 2348 iname->section = secdata[IDATA5].sec; 2349 iname->flags = BSF_GLOBAL; 2350 iname->value = 0; 2351 } 2352 2353 iname2 = bfd_make_empty_symbol (abfd); 2354 iname2->name = make_imp_label ("__imp_", exp->name); 2355 iname2->section = secdata[IDATA5].sec; 2356 iname2->flags = BSF_GLOBAL; 2357 iname2->value = 0; 2358 2359 iname_lab = bfd_make_empty_symbol(abfd); 2360 2361 iname_lab->name = head_label; 2362 iname_lab->section = (asection *)&bfd_und_section; 2363 iname_lab->flags = 0; 2364 iname_lab->value = 0; 2365 2366 iname_pp = ptrs + oidx; 2367 if (create_compat_implib) 2368 ptrs[oidx++] = iname; 2369 ptrs[oidx++] = iname2; 2370 2371 iname_lab_pp = ptrs + oidx; 2372 ptrs[oidx++] = iname_lab; 2373 2374 #ifdef DLLTOOL_PPC 2375 /* The symbol referring to the code (.text). */ 2376 { 2377 asymbol *function_name; 2378 2379 function_name = bfd_make_empty_symbol(abfd); 2380 function_name->name = make_label ("..", exp->name); 2381 function_name->section = secdata[TEXT].sec; 2382 function_name->flags = BSF_GLOBAL; 2383 function_name->value = 0; 2384 2385 fn_pp = ptrs + oidx; 2386 ptrs[oidx++] = function_name; 2387 } 2388 2389 /* The .toc symbol. */ 2390 { 2391 asymbol *toc_symbol; 2392 2393 toc_symbol = bfd_make_empty_symbol (abfd); 2394 toc_symbol->name = make_label (".", "toc"); 2395 toc_symbol->section = (asection *)&bfd_und_section; 2396 toc_symbol->flags = BSF_GLOBAL; 2397 toc_symbol->value = 0; 2398 2399 toc_pp = ptrs + oidx; 2400 ptrs[oidx++] = toc_symbol; 2401 } 2402 #endif 2403 2404 ptrs[oidx] = 0; 2405 2406 for (i = 0; i < NSECS; i++) 2407 { 2408 sinfo *si = secdata + i; 2409 asection *sec = si->sec; 2410 arelent *rel; 2411 arelent **rpp; 2412 2413 switch (i) 2414 { 2415 case TEXT: 2416 if (! exp->data) 2417 { 2418 si->size = HOW_JTAB_SIZE; 2419 si->data = xmalloc (HOW_JTAB_SIZE); 2420 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); 2421 2422 /* add the reloc into idata$5 */ 2423 rel = xmalloc (sizeof (arelent)); 2424 2425 rpp = xmalloc (sizeof (arelent *) * 2); 2426 rpp[0] = rel; 2427 rpp[1] = 0; 2428 2429 rel->address = HOW_JTAB_ROFF; 2430 rel->addend = 0; 2431 2432 if (machine == MPPC) 2433 { 2434 rel->howto = bfd_reloc_type_lookup (abfd, 2435 BFD_RELOC_16_GOTOFF); 2436 rel->sym_ptr_ptr = iname_pp; 2437 } 2438 else 2439 { 2440 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2441 rel->sym_ptr_ptr = secdata[IDATA5].sympp; 2442 } 2443 sec->orelocation = rpp; 2444 sec->reloc_count = 1; 2445 } 2446 break; 2447 case IDATA4: 2448 case IDATA5: 2449 /* An idata$4 or idata$5 is one word long, and has an 2450 rva to idata$6. */ 2451 2452 si->data = xmalloc (4); 2453 si->size = 4; 2454 2455 if (exp->noname) 2456 { 2457 si->data[0] = exp->ordinal ; 2458 si->data[1] = exp->ordinal >> 8; 2459 si->data[2] = exp->ordinal >> 16; 2460 si->data[3] = 0x80; 2461 } 2462 else 2463 { 2464 sec->reloc_count = 1; 2465 memset (si->data, 0, si->size); 2466 rel = xmalloc (sizeof (arelent)); 2467 rpp = xmalloc (sizeof (arelent *) * 2); 2468 rpp[0] = rel; 2469 rpp[1] = 0; 2470 rel->address = 0; 2471 rel->addend = 0; 2472 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 2473 rel->sym_ptr_ptr = secdata[IDATA6].sympp; 2474 sec->orelocation = rpp; 2475 } 2476 2477 break; 2478 2479 case IDATA6: 2480 if (!exp->noname) 2481 { 2482 /* This used to add 1 to exp->hint. I don't know 2483 why it did that, and it does not match what I see 2484 in programs compiled with the MS tools. */ 2485 int idx = exp->hint; 2486 si->size = strlen (xlate (exp->name)) + 3; 2487 si->data = xmalloc (si->size); 2488 si->data[0] = idx & 0xff; 2489 si->data[1] = idx >> 8; 2490 strcpy (si->data + 2, xlate (exp->name)); 2491 } 2492 break; 2493 case IDATA7: 2494 si->size = 4; 2495 si->data =xmalloc (4); 2496 memset (si->data, 0, si->size); 2497 rel = xmalloc (sizeof (arelent)); 2498 rpp = xmalloc (sizeof (arelent *) * 2); 2499 rpp[0] = rel; 2500 rel->address = 0; 2501 rel->addend = 0; 2502 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); 2503 rel->sym_ptr_ptr = iname_lab_pp; 2504 sec->orelocation = rpp; 2505 sec->reloc_count = 1; 2506 break; 2507 2508 #ifdef DLLTOOL_PPC 2509 case PDATA: 2510 { 2511 /* The .pdata section is 5 words long. 2512 Think of it as: 2513 struct 2514 { 2515 bfd_vma BeginAddress, [0x00] 2516 EndAddress, [0x04] 2517 ExceptionHandler, [0x08] 2518 HandlerData, [0x0c] 2519 PrologEndAddress; [0x10] 2520 }; */ 2521 2522 /* So this pdata section setups up this as a glue linkage to 2523 a dll routine. There are a number of house keeping things 2524 we need to do: 2525 2526 1. In the name of glue trickery, the ADDR32 relocs for 0, 2527 4, and 0x10 are set to point to the same place: 2528 "..function_name". 2529 2. There is one more reloc needed in the pdata section. 2530 The actual glue instruction to restore the toc on 2531 return is saved as the offset in an IMGLUE reloc. 2532 So we need a total of four relocs for this section. 2533 2534 3. Lastly, the HandlerData field is set to 0x03, to indicate 2535 that this is a glue routine. */ 2536 arelent *imglue, *ba_rel, *ea_rel, *pea_rel; 2537 2538 /* Alignment must be set to 2**2 or you get extra stuff. */ 2539 bfd_set_section_alignment(abfd, sec, 2); 2540 2541 si->size = 4 * 5; 2542 si->data = xmalloc (si->size); 2543 memset (si->data, 0, si->size); 2544 rpp = xmalloc (sizeof (arelent *) * 5); 2545 rpp[0] = imglue = xmalloc (sizeof (arelent)); 2546 rpp[1] = ba_rel = xmalloc (sizeof (arelent)); 2547 rpp[2] = ea_rel = xmalloc (sizeof (arelent)); 2548 rpp[3] = pea_rel = xmalloc (sizeof (arelent)); 2549 rpp[4] = 0; 2550 2551 /* Stick the toc reload instruction in the glue reloc. */ 2552 bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address); 2553 2554 imglue->addend = 0; 2555 imglue->howto = bfd_reloc_type_lookup (abfd, 2556 BFD_RELOC_32_GOTOFF); 2557 imglue->sym_ptr_ptr = fn_pp; 2558 2559 ba_rel->address = 0; 2560 ba_rel->addend = 0; 2561 ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2562 ba_rel->sym_ptr_ptr = fn_pp; 2563 2564 bfd_put_32 (abfd, 0x18, si->data + 0x04); 2565 ea_rel->address = 4; 2566 ea_rel->addend = 0; 2567 ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2568 ea_rel->sym_ptr_ptr = fn_pp; 2569 2570 /* Mark it as glue. */ 2571 bfd_put_32 (abfd, 0x03, si->data + 0x0c); 2572 2573 /* Mark the prolog end address. */ 2574 bfd_put_32 (abfd, 0x0D, si->data + 0x10); 2575 pea_rel->address = 0x10; 2576 pea_rel->addend = 0; 2577 pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2578 pea_rel->sym_ptr_ptr = fn_pp; 2579 2580 sec->orelocation = rpp; 2581 sec->reloc_count = 4; 2582 break; 2583 } 2584 case RDATA: 2585 /* Each external function in a PowerPC PE file has a two word 2586 descriptor consisting of: 2587 1. The address of the code. 2588 2. The address of the appropriate .toc 2589 We use relocs to build this. */ 2590 si->size = 8; 2591 si->data = xmalloc (8); 2592 memset (si->data, 0, si->size); 2593 2594 rpp = xmalloc (sizeof (arelent *) * 3); 2595 rpp[0] = rel = xmalloc (sizeof (arelent)); 2596 rpp[1] = xmalloc (sizeof (arelent)); 2597 rpp[2] = 0; 2598 2599 rel->address = 0; 2600 rel->addend = 0; 2601 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2602 rel->sym_ptr_ptr = fn_pp; 2603 2604 rel = rpp[1]; 2605 2606 rel->address = 4; 2607 rel->addend = 0; 2608 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); 2609 rel->sym_ptr_ptr = toc_pp; 2610 2611 sec->orelocation = rpp; 2612 sec->reloc_count = 2; 2613 break; 2614 #endif /* DLLTOOL_PPC */ 2615 } 2616 } 2617 2618 { 2619 bfd_vma vma = 0; 2620 /* Size up all the sections. */ 2621 for (i = 0; i < NSECS; i++) 2622 { 2623 sinfo *si = secdata + i; 2624 2625 bfd_set_section_size (abfd, si->sec, si->size); 2626 bfd_set_section_vma (abfd, si->sec, vma); 2627 2628 /* vma += si->size;*/ 2629 } 2630 } 2631 /* Write them out. */ 2632 for (i = 0; i < NSECS; i++) 2633 { 2634 sinfo *si = secdata + i; 2635 2636 if (i == IDATA5 && no_idata5) 2637 continue; 2638 2639 if (i == IDATA4 && no_idata4) 2640 continue; 2641 2642 bfd_set_section_contents (abfd, si->sec, 2643 si->data, 0, 2644 si->size); 2645 } 2646 2647 bfd_set_symtab (abfd, ptrs, oidx); 2648 bfd_close (abfd); 2649 abfd = bfd_openr (outname, HOW_BFD_READ_TARGET); 2650 return abfd; 2651 } 2652 #endif 2653 } 2654 2655 static bfd * 2656 make_head (void) 2657 { 2658 FILE *f = fopen (TMP_HEAD_S, FOPEN_WT); 2659 2660 if (f == NULL) 2661 { 2662 fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S); 2663 return NULL; 2664 } 2665 2666 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); 2667 fprintf (f, "\t.section .idata$2\n"); 2668 2669 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); 2670 2671 fprintf (f, "%s:\n", head_label); 2672 2673 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n", 2674 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); 2675 2676 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C); 2677 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C); 2678 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C); 2679 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); 2680 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n", 2681 ASM_RVA_BEFORE, 2682 imp_name_lab, 2683 ASM_RVA_AFTER, 2684 ASM_C); 2685 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n", 2686 ASM_RVA_BEFORE, 2687 ASM_RVA_AFTER, ASM_C); 2688 2689 fprintf (f, "%sStuff for compatibility\n", ASM_C); 2690 2691 if (!no_idata5) 2692 { 2693 fprintf (f, "\t.section\t.idata$5\n"); 2694 fprintf (f, "\t%s\t0\n", ASM_LONG); 2695 fprintf (f, "fthunk:\n"); 2696 } 2697 2698 if (!no_idata4) 2699 { 2700 fprintf (f, "\t.section\t.idata$4\n"); 2701 2702 fprintf (f, "\t%s\t0\n", ASM_LONG); 2703 fprintf (f, "\t.section .idata$4\n"); 2704 fprintf (f, "hname:\n"); 2705 } 2706 2707 fclose (f); 2708 2709 assemble_file (TMP_HEAD_S, TMP_HEAD_O); 2710 2711 return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET); 2712 } 2713 2714 static bfd * 2715 make_tail (void) 2716 { 2717 FILE *f = fopen (TMP_TAIL_S, FOPEN_WT); 2718 2719 if (f == NULL) 2720 { 2721 fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S); 2722 return NULL; 2723 } 2724 2725 if (!no_idata4) 2726 { 2727 fprintf (f, "\t.section .idata$4\n"); 2728 fprintf (f, "\t%s\t0\n", ASM_LONG); 2729 } 2730 2731 if (!no_idata5) 2732 { 2733 fprintf (f, "\t.section .idata$5\n"); 2734 fprintf (f, "\t%s\t0\n", ASM_LONG); 2735 } 2736 2737 #ifdef DLLTOOL_PPC 2738 /* Normally, we need to see a null descriptor built in idata$3 to 2739 act as the terminator for the list. The ideal way, I suppose, 2740 would be to mark this section as a comdat type 2 section, so 2741 only one would appear in the final .exe (if our linker supported 2742 comdat, that is) or cause it to be inserted by something else (say 2743 crt0). */ 2744 2745 fprintf (f, "\t.section .idata$3\n"); 2746 fprintf (f, "\t%s\t0\n", ASM_LONG); 2747 fprintf (f, "\t%s\t0\n", ASM_LONG); 2748 fprintf (f, "\t%s\t0\n", ASM_LONG); 2749 fprintf (f, "\t%s\t0\n", ASM_LONG); 2750 fprintf (f, "\t%s\t0\n", ASM_LONG); 2751 #endif 2752 2753 #ifdef DLLTOOL_PPC 2754 /* Other PowerPC NT compilers use idata$6 for the dllname, so I 2755 do too. Original, huh? */ 2756 fprintf (f, "\t.section .idata$6\n"); 2757 #else 2758 fprintf (f, "\t.section .idata$7\n"); 2759 #endif 2760 2761 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab); 2762 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n", 2763 imp_name_lab, ASM_TEXT, dll_name); 2764 2765 fclose (f); 2766 2767 assemble_file (TMP_TAIL_S, TMP_TAIL_O); 2768 2769 return bfd_openr (TMP_TAIL_O, HOW_BFD_READ_TARGET); 2770 } 2771 2772 static void 2773 gen_lib_file (void) 2774 { 2775 int i; 2776 export_type *exp; 2777 bfd *ar_head; 2778 bfd *ar_tail; 2779 bfd *outarch; 2780 bfd * head = 0; 2781 2782 unlink (imp_name); 2783 2784 outarch = bfd_openw (imp_name, HOW_BFD_WRITE_TARGET); 2785 2786 if (!outarch) 2787 /* xgettext:c-format */ 2788 fatal (_("Can't open .lib file: %s"), imp_name); 2789 2790 /* xgettext:c-format */ 2791 inform (_("Creating library file: %s"), imp_name); 2792 2793 bfd_set_format (outarch, bfd_archive); 2794 outarch->has_armap = 1; 2795 2796 /* Work out a reasonable size of things to put onto one line. */ 2797 ar_head = make_head (); 2798 ar_tail = make_tail(); 2799 2800 if (ar_head == NULL || ar_tail == NULL) 2801 return; 2802 2803 for (i = 0; (exp = d_exports_lexically[i]); i++) 2804 { 2805 bfd *n; 2806 /* Don't add PRIVATE entries to import lib. */ 2807 if (exp->private) 2808 continue; 2809 n = make_one_lib_file (exp, i); 2810 n->next = head; 2811 head = n; 2812 } 2813 2814 /* Now stick them all into the archive. */ 2815 ar_head->next = head; 2816 ar_tail->next = ar_head; 2817 head = ar_tail; 2818 2819 if (! bfd_set_archive_head (outarch, head)) 2820 bfd_fatal ("bfd_set_archive_head"); 2821 2822 if (! bfd_close (outarch)) 2823 bfd_fatal (imp_name); 2824 2825 while (head != NULL) 2826 { 2827 bfd *n = head->next; 2828 bfd_close (head); 2829 head = n; 2830 } 2831 2832 /* Delete all the temp files. */ 2833 if (dontdeltemps == 0) 2834 { 2835 unlink (TMP_HEAD_O); 2836 unlink (TMP_HEAD_S); 2837 unlink (TMP_TAIL_O); 2838 unlink (TMP_TAIL_S); 2839 } 2840 2841 if (dontdeltemps < 2) 2842 { 2843 char *name; 2844 2845 name = (char *) alloca (strlen (TMP_STUB) + 10); 2846 for (i = 0; (exp = d_exports_lexically[i]); i++) 2847 { 2848 /* Don't delete non-existent stubs for PRIVATE entries. */ 2849 if (exp->private) 2850 continue; 2851 sprintf (name, "%s%05d.o", TMP_STUB, i); 2852 if (unlink (name) < 0) 2853 /* xgettext:c-format */ 2854 non_fatal (_("cannot delete %s: %s"), name, strerror (errno)); 2855 } 2856 } 2857 2858 inform (_("Created lib file")); 2859 } 2860 2861 /* Run through the information gathered from the .o files and the 2862 .def file and work out the best stuff. */ 2863 2864 static int 2865 pfunc (const void *a, const void *b) 2866 { 2867 export_type *ap = *(export_type **) a; 2868 export_type *bp = *(export_type **) b; 2869 if (ap->ordinal == bp->ordinal) 2870 return 0; 2871 2872 /* Unset ordinals go to the bottom. */ 2873 if (ap->ordinal == -1) 2874 return 1; 2875 if (bp->ordinal == -1) 2876 return -1; 2877 return (ap->ordinal - bp->ordinal); 2878 } 2879 2880 static int 2881 nfunc (const void *a, const void *b) 2882 { 2883 export_type *ap = *(export_type **) a; 2884 export_type *bp = *(export_type **) b; 2885 2886 return (strcmp (ap->name, bp->name)); 2887 } 2888 2889 static void 2890 remove_null_names (export_type **ptr) 2891 { 2892 int src; 2893 int dst; 2894 2895 for (dst = src = 0; src < d_nfuncs; src++) 2896 { 2897 if (ptr[src]) 2898 { 2899 ptr[dst] = ptr[src]; 2900 dst++; 2901 } 2902 } 2903 d_nfuncs = dst; 2904 } 2905 2906 static void 2907 dtab (export_type **ptr ATTRIBUTE_UNUSED) 2908 { 2909 #ifdef SACDEBUG 2910 int i; 2911 for (i = 0; i < d_nfuncs; i++) 2912 { 2913 if (ptr[i]) 2914 { 2915 printf ("%d %s @ %d %s%s%s\n", 2916 i, ptr[i]->name, ptr[i]->ordinal, 2917 ptr[i]->noname ? "NONAME " : "", 2918 ptr[i]->constant ? "CONSTANT" : "", 2919 ptr[i]->data ? "DATA" : ""); 2920 } 2921 else 2922 printf ("empty\n"); 2923 } 2924 #endif 2925 } 2926 2927 static void 2928 process_duplicates (export_type **d_export_vec) 2929 { 2930 int more = 1; 2931 int i; 2932 2933 while (more) 2934 { 2935 more = 0; 2936 /* Remove duplicates. */ 2937 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); 2938 2939 dtab (d_export_vec); 2940 for (i = 0; i < d_nfuncs - 1; i++) 2941 { 2942 if (strcmp (d_export_vec[i]->name, 2943 d_export_vec[i + 1]->name) == 0) 2944 { 2945 export_type *a = d_export_vec[i]; 2946 export_type *b = d_export_vec[i + 1]; 2947 2948 more = 1; 2949 2950 /* xgettext:c-format */ 2951 inform (_("Warning, ignoring duplicate EXPORT %s %d,%d"), 2952 a->name, a->ordinal, b->ordinal); 2953 2954 if (a->ordinal != -1 2955 && b->ordinal != -1) 2956 /* xgettext:c-format */ 2957 fatal (_("Error, duplicate EXPORT with oridinals: %s"), 2958 a->name); 2959 2960 /* Merge attributes. */ 2961 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; 2962 b->constant |= a->constant; 2963 b->noname |= a->noname; 2964 b->data |= a->data; 2965 d_export_vec[i] = 0; 2966 } 2967 2968 dtab (d_export_vec); 2969 remove_null_names (d_export_vec); 2970 dtab (d_export_vec); 2971 } 2972 } 2973 2974 /* Count the names. */ 2975 for (i = 0; i < d_nfuncs; i++) 2976 if (!d_export_vec[i]->noname) 2977 d_named_nfuncs++; 2978 } 2979 2980 static void 2981 fill_ordinals (export_type **d_export_vec) 2982 { 2983 int lowest = -1; 2984 int i; 2985 char *ptr; 2986 int size = 65536; 2987 2988 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 2989 2990 /* Fill in the unset ordinals with ones from our range. */ 2991 ptr = (char *) xmalloc (size); 2992 2993 memset (ptr, 0, size); 2994 2995 /* Mark in our large vector all the numbers that are taken. */ 2996 for (i = 0; i < d_nfuncs; i++) 2997 { 2998 if (d_export_vec[i]->ordinal != -1) 2999 { 3000 ptr[d_export_vec[i]->ordinal] = 1; 3001 3002 if (lowest == -1 || d_export_vec[i]->ordinal < lowest) 3003 lowest = d_export_vec[i]->ordinal; 3004 } 3005 } 3006 3007 /* Start at 1 for compatibility with MS toolchain. */ 3008 if (lowest == -1) 3009 lowest = 1; 3010 3011 /* Now fill in ordinals where the user wants us to choose. */ 3012 for (i = 0; i < d_nfuncs; i++) 3013 { 3014 if (d_export_vec[i]->ordinal == -1) 3015 { 3016 int j; 3017 3018 /* First try within or after any user supplied range. */ 3019 for (j = lowest; j < size; j++) 3020 if (ptr[j] == 0) 3021 { 3022 ptr[j] = 1; 3023 d_export_vec[i]->ordinal = j; 3024 goto done; 3025 } 3026 3027 /* Then try before the range. */ 3028 for (j = lowest; j >0; j--) 3029 if (ptr[j] == 0) 3030 { 3031 ptr[j] = 1; 3032 d_export_vec[i]->ordinal = j; 3033 goto done; 3034 } 3035 done:; 3036 } 3037 } 3038 3039 free (ptr); 3040 3041 /* And resort. */ 3042 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); 3043 3044 /* Work out the lowest and highest ordinal numbers. */ 3045 if (d_nfuncs) 3046 { 3047 if (d_export_vec[0]) 3048 d_low_ord = d_export_vec[0]->ordinal; 3049 if (d_export_vec[d_nfuncs-1]) 3050 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal; 3051 } 3052 } 3053 3054 static int 3055 alphafunc (const void *av, const void *bv) 3056 { 3057 const export_type **a = (const export_type **) av; 3058 const export_type **b = (const export_type **) bv; 3059 3060 return strcmp ((*a)->name, (*b)->name); 3061 } 3062 3063 static void 3064 mangle_defs (void) 3065 { 3066 /* First work out the minimum ordinal chosen. */ 3067 export_type *exp; 3068 3069 int i; 3070 int hint = 0; 3071 export_type **d_export_vec = xmalloc (sizeof (export_type *) * d_nfuncs); 3072 3073 inform (_("Processing definitions")); 3074 3075 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 3076 d_export_vec[i] = exp; 3077 3078 process_duplicates (d_export_vec); 3079 fill_ordinals (d_export_vec); 3080 3081 /* Put back the list in the new order. */ 3082 d_exports = 0; 3083 for (i = d_nfuncs - 1; i >= 0; i--) 3084 { 3085 d_export_vec[i]->next = d_exports; 3086 d_exports = d_export_vec[i]; 3087 } 3088 3089 /* Build list in alpha order. */ 3090 d_exports_lexically = (export_type **) 3091 xmalloc (sizeof (export_type *) * (d_nfuncs + 1)); 3092 3093 for (i = 0, exp = d_exports; exp; i++, exp = exp->next) 3094 d_exports_lexically[i] = exp; 3095 3096 d_exports_lexically[i] = 0; 3097 3098 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc); 3099 3100 /* Fill exp entries with their hint values. */ 3101 for (i = 0; i < d_nfuncs; i++) 3102 if (!d_exports_lexically[i]->noname || show_allnames) 3103 d_exports_lexically[i]->hint = hint++; 3104 3105 inform (_("Processed definitions")); 3106 } 3107 3108 static void 3109 usage (FILE *file, int status) 3110 { 3111 /* xgetext:c-format */ 3112 fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name); 3113 /* xgetext:c-format */ 3114 fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname); 3115 fprintf (file, _(" possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n")); 3116 fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n")); 3117 fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n")); 3118 fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n")); 3119 fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n")); 3120 fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n")); 3121 fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n")); 3122 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n")); 3123 fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n")); 3124 fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n")); 3125 fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n")); 3126 fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n")); 3127 fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n")); 3128 fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n")); 3129 fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n")); 3130 fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n")); 3131 fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n")); 3132 fprintf (file, _(" -S --as <name> Use <name> for assembler.\n")); 3133 fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n")); 3134 fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n")); 3135 fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n")); 3136 fprintf (file, _(" -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n")); 3137 fprintf (file, _(" -v --verbose Be verbose.\n")); 3138 fprintf (file, _(" -V --version Display the program version.\n")); 3139 fprintf (file, _(" -h --help Display this information.\n")); 3140 #ifdef DLLTOOL_MCORE_ELF 3141 fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n")); 3142 fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n")); 3143 fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n")); 3144 #endif 3145 exit (status); 3146 } 3147 3148 #define OPTION_EXPORT_ALL_SYMS 150 3149 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1) 3150 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1) 3151 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1) 3152 3153 static const struct option long_options[] = 3154 { 3155 {"no-delete", no_argument, NULL, 'n'}, 3156 {"dllname", required_argument, NULL, 'D'}, 3157 {"no-idata4", no_argument, NULL, 'x'}, 3158 {"no-idata5", no_argument, NULL, 'c'}, 3159 {"output-exp", required_argument, NULL, 'e'}, 3160 {"output-def", required_argument, NULL, 'z'}, 3161 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS}, 3162 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS}, 3163 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS}, 3164 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 3165 {"output-lib", required_argument, NULL, 'l'}, 3166 {"def", required_argument, NULL, 'd'}, /* for compatibility with older versions */ 3167 {"input-def", required_argument, NULL, 'd'}, 3168 {"add-underscore", no_argument, NULL, 'U'}, 3169 {"kill-at", no_argument, NULL, 'k'}, 3170 {"add-stdcall-alias", no_argument, NULL, 'A'}, 3171 {"verbose", no_argument, NULL, 'v'}, 3172 {"version", no_argument, NULL, 'V'}, 3173 {"help", no_argument, NULL, 'h'}, 3174 {"machine", required_argument, NULL, 'm'}, 3175 {"add-indirect", no_argument, NULL, 'a'}, 3176 {"base-file", required_argument, NULL, 'b'}, 3177 {"as", required_argument, NULL, 'S'}, 3178 {"as-flags", required_argument, NULL, 'f'}, 3179 {"mcore-elf", required_argument, NULL, 'M'}, 3180 {"compat-implib", no_argument, NULL, 'C'}, 3181 {"temp-prefix", required_argument, NULL, 't'}, 3182 {NULL,0,NULL,0} 3183 }; 3184 3185 int main (int, char **); 3186 3187 int 3188 main (int ac, char **av) 3189 { 3190 int c; 3191 int i; 3192 char *firstarg = 0; 3193 program_name = av[0]; 3194 oav = av; 3195 3196 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 3197 setlocale (LC_MESSAGES, ""); 3198 #endif 3199 #if defined (HAVE_SETLOCALE) 3200 setlocale (LC_CTYPE, ""); 3201 #endif 3202 bindtextdomain (PACKAGE, LOCALEDIR); 3203 textdomain (PACKAGE); 3204 3205 while ((c = getopt_long (ac, av, 3206 #ifdef DLLTOOL_MCORE_ELF 3207 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVHhM:L:F:", 3208 #else 3209 "m:e:l:aD:d:z:b:xcCuUkAS:f:nvVHh", 3210 #endif 3211 long_options, 0)) 3212 != EOF) 3213 { 3214 switch (c) 3215 { 3216 case OPTION_EXPORT_ALL_SYMS: 3217 export_all_symbols = TRUE; 3218 break; 3219 case OPTION_NO_EXPORT_ALL_SYMS: 3220 export_all_symbols = FALSE; 3221 break; 3222 case OPTION_EXCLUDE_SYMS: 3223 add_excludes (optarg); 3224 break; 3225 case OPTION_NO_DEFAULT_EXCLUDES: 3226 do_default_excludes = FALSE; 3227 break; 3228 case 'x': 3229 no_idata4 = 1; 3230 break; 3231 case 'c': 3232 no_idata5 = 1; 3233 break; 3234 case 'S': 3235 as_name = optarg; 3236 break; 3237 case 't': 3238 tmp_prefix = optarg; 3239 break; 3240 case 'f': 3241 as_flags = optarg; 3242 break; 3243 3244 /* Ignored for compatibility. */ 3245 case 'u': 3246 break; 3247 case 'a': 3248 add_indirect = 1; 3249 break; 3250 case 'z': 3251 output_def = fopen (optarg, FOPEN_WT); 3252 break; 3253 case 'D': 3254 dll_name = optarg; 3255 break; 3256 case 'l': 3257 imp_name = optarg; 3258 break; 3259 case 'e': 3260 exp_name = optarg; 3261 break; 3262 case 'H': 3263 case 'h': 3264 usage (stdout, 0); 3265 break; 3266 case 'm': 3267 mname = optarg; 3268 break; 3269 case 'v': 3270 verbose = 1; 3271 break; 3272 case 'V': 3273 print_version (program_name); 3274 break; 3275 case 'U': 3276 add_underscore = 1; 3277 break; 3278 case 'k': 3279 killat = 1; 3280 break; 3281 case 'A': 3282 add_stdcall_alias = 1; 3283 break; 3284 case 'd': 3285 def_file = optarg; 3286 break; 3287 case 'n': 3288 dontdeltemps++; 3289 break; 3290 case 'b': 3291 base_file = fopen (optarg, FOPEN_RB); 3292 3293 if (!base_file) 3294 /* xgettext:c-format */ 3295 fatal (_("Unable to open base-file: %s"), optarg); 3296 3297 break; 3298 #ifdef DLLTOOL_MCORE_ELF 3299 case 'M': 3300 mcore_elf_out_file = optarg; 3301 break; 3302 case 'L': 3303 mcore_elf_linker = optarg; 3304 break; 3305 case 'F': 3306 mcore_elf_linker_flags = optarg; 3307 break; 3308 #endif 3309 case 'C': 3310 create_compat_implib = 1; 3311 break; 3312 default: 3313 usage (stderr, 1); 3314 break; 3315 } 3316 } 3317 3318 if (!tmp_prefix) 3319 tmp_prefix = prefix_encode ("d", getpid ()); 3320 3321 for (i = 0; mtable[i].type; i++) 3322 if (strcmp (mtable[i].type, mname) == 0) 3323 break; 3324 3325 if (!mtable[i].type) 3326 /* xgettext:c-format */ 3327 fatal (_("Machine '%s' not supported"), mname); 3328 3329 machine = i; 3330 3331 if (!dll_name && exp_name) 3332 { 3333 int len = strlen (exp_name) + 5; 3334 dll_name = xmalloc (len); 3335 strcpy (dll_name, exp_name); 3336 strcat (dll_name, ".dll"); 3337 } 3338 3339 if (as_name == NULL) 3340 as_name = deduce_name ("as"); 3341 3342 /* Don't use the default exclude list if we're reading only the 3343 symbols in the .drectve section. The default excludes are meant 3344 to avoid exporting DLL entry point and Cygwin32 impure_ptr. */ 3345 if (! export_all_symbols) 3346 do_default_excludes = FALSE; 3347 3348 if (do_default_excludes) 3349 set_default_excludes (); 3350 3351 if (def_file) 3352 process_def_file (def_file); 3353 3354 while (optind < ac) 3355 { 3356 if (!firstarg) 3357 firstarg = av[optind]; 3358 scan_obj_file (av[optind]); 3359 optind++; 3360 } 3361 3362 mangle_defs (); 3363 3364 if (exp_name) 3365 gen_exp_file (); 3366 3367 if (imp_name) 3368 { 3369 /* Make imp_name safe for use as a label. */ 3370 char *p; 3371 3372 imp_name_lab = xstrdup (imp_name); 3373 for (p = imp_name_lab; *p; p++) 3374 { 3375 if (!ISALNUM (*p)) 3376 *p = '_'; 3377 } 3378 head_label = make_label("_head_", imp_name_lab); 3379 gen_lib_file (); 3380 } 3381 3382 if (output_def) 3383 gen_def_file (); 3384 3385 #ifdef DLLTOOL_MCORE_ELF 3386 if (mcore_elf_out_file) 3387 mcore_elf_gen_out_file (); 3388 #endif 3389 3390 return 0; 3391 } 3392 3393 /* Look for the program formed by concatenating PROG_NAME and the 3394 string running from PREFIX to END_PREFIX. If the concatenated 3395 string contains a '/', try appending EXECUTABLE_SUFFIX if it is 3396 appropriate. */ 3397 3398 static char * 3399 look_for_prog (const char *prog_name, const char *prefix, int end_prefix) 3400 { 3401 struct stat s; 3402 char *cmd; 3403 3404 cmd = xmalloc (strlen (prefix) 3405 + strlen (prog_name) 3406 #ifdef HAVE_EXECUTABLE_SUFFIX 3407 + strlen (EXECUTABLE_SUFFIX) 3408 #endif 3409 + 10); 3410 strcpy (cmd, prefix); 3411 3412 sprintf (cmd + end_prefix, "%s", prog_name); 3413 3414 if (strchr (cmd, '/') != NULL) 3415 { 3416 int found; 3417 3418 found = (stat (cmd, &s) == 0 3419 #ifdef HAVE_EXECUTABLE_SUFFIX 3420 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 3421 #endif 3422 ); 3423 3424 if (! found) 3425 { 3426 /* xgettext:c-format */ 3427 inform (_("Tried file: %s"), cmd); 3428 free (cmd); 3429 return NULL; 3430 } 3431 } 3432 3433 /* xgettext:c-format */ 3434 inform (_("Using file: %s"), cmd); 3435 3436 return cmd; 3437 } 3438 3439 /* Deduce the name of the program we are want to invoke. 3440 PROG_NAME is the basic name of the program we want to run, 3441 eg "as" or "ld". The catch is that we might want actually 3442 run "i386-pe-as" or "ppc-pe-ld". 3443 3444 If argv[0] contains the full path, then try to find the program 3445 in the same place, with and then without a target-like prefix. 3446 3447 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool, 3448 deduce_name("as") uses the following search order: 3449 3450 /usr/local/bin/i586-cygwin32-as 3451 /usr/local/bin/as 3452 as 3453 3454 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each 3455 name, it'll try without and then with EXECUTABLE_SUFFIX. 3456 3457 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as" 3458 as the fallback, but rather return i586-cygwin32-as. 3459 3460 Oh, and given, argv[0] = dlltool, it'll return "as". 3461 3462 Returns a dynamically allocated string. */ 3463 3464 static char * 3465 deduce_name (const char *prog_name) 3466 { 3467 char *cmd; 3468 char *dash, *slash, *cp; 3469 3470 dash = NULL; 3471 slash = NULL; 3472 for (cp = program_name; *cp != '\0'; ++cp) 3473 { 3474 if (*cp == '-') 3475 dash = cp; 3476 if ( 3477 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) 3478 *cp == ':' || *cp == '\\' || 3479 #endif 3480 *cp == '/') 3481 { 3482 slash = cp; 3483 dash = NULL; 3484 } 3485 } 3486 3487 cmd = NULL; 3488 3489 if (dash != NULL) 3490 { 3491 /* First, try looking for a prefixed PROG_NAME in the 3492 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */ 3493 cmd = look_for_prog (prog_name, program_name, dash - program_name + 1); 3494 } 3495 3496 if (slash != NULL && cmd == NULL) 3497 { 3498 /* Next, try looking for a PROG_NAME in the same directory as 3499 that of this program. */ 3500 cmd = look_for_prog (prog_name, program_name, slash - program_name + 1); 3501 } 3502 3503 if (cmd == NULL) 3504 { 3505 /* Just return PROG_NAME as is. */ 3506 cmd = xstrdup (prog_name); 3507 } 3508 3509 return cmd; 3510 } 3511 3512 #ifdef DLLTOOL_MCORE_ELF 3513 typedef struct fname_cache 3514 { 3515 char * filename; 3516 struct fname_cache * next; 3517 } 3518 fname_cache; 3519 3520 static fname_cache fnames; 3521 3522 static void 3523 mcore_elf_cache_filename (char * filename) 3524 { 3525 fname_cache * ptr; 3526 3527 ptr = & fnames; 3528 3529 while (ptr->next != NULL) 3530 ptr = ptr->next; 3531 3532 ptr->filename = filename; 3533 ptr->next = (fname_cache *) malloc (sizeof (fname_cache)); 3534 if (ptr->next != NULL) 3535 ptr->next->next = NULL; 3536 } 3537 3538 #define MCORE_ELF_TMP_OBJ "mcoreelf.o" 3539 #define MCORE_ELF_TMP_EXP "mcoreelf.exp" 3540 #define MCORE_ELF_TMP_LIB "mcoreelf.lib" 3541 3542 static void 3543 mcore_elf_gen_out_file (void) 3544 { 3545 fname_cache * ptr; 3546 dyn_string_t ds; 3547 3548 /* Step one. Run 'ld -r' on the input object files in order to resolve 3549 any internal references and to generate a single .exports section. */ 3550 ptr = & fnames; 3551 3552 ds = dyn_string_new (100); 3553 dyn_string_append_cstr (ds, "-r "); 3554 3555 if (mcore_elf_linker_flags != NULL) 3556 dyn_string_append_cstr (ds, mcore_elf_linker_flags); 3557 3558 while (ptr->next != NULL) 3559 { 3560 dyn_string_append_cstr (ds, ptr->filename); 3561 dyn_string_append_cstr (ds, " "); 3562 3563 ptr = ptr->next; 3564 } 3565 3566 dyn_string_append_cstr (ds, "-o "); 3567 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 3568 3569 if (mcore_elf_linker == NULL) 3570 mcore_elf_linker = deduce_name ("ld"); 3571 3572 run (mcore_elf_linker, ds->s); 3573 3574 dyn_string_delete (ds); 3575 3576 /* Step two. Create a .exp file and a .lib file from the temporary file. 3577 Do this by recursively invoking dlltool... */ 3578 ds = dyn_string_new (100); 3579 3580 dyn_string_append_cstr (ds, "-S "); 3581 dyn_string_append_cstr (ds, as_name); 3582 3583 dyn_string_append_cstr (ds, " -e "); 3584 dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP); 3585 dyn_string_append_cstr (ds, " -l "); 3586 dyn_string_append_cstr (ds, MCORE_ELF_TMP_LIB); 3587 dyn_string_append_cstr (ds, " " ); 3588 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 3589 3590 if (verbose) 3591 dyn_string_append_cstr (ds, " -v"); 3592 3593 if (dontdeltemps) 3594 { 3595 dyn_string_append_cstr (ds, " -n"); 3596 3597 if (dontdeltemps > 1) 3598 dyn_string_append_cstr (ds, " -n"); 3599 } 3600 3601 /* XXX - FIME: ought to check/copy other command line options as well. */ 3602 run (program_name, ds->s); 3603 3604 dyn_string_delete (ds); 3605 3606 /* Step four. Feed the .exp and object files to ld -shared to create the dll. */ 3607 ds = dyn_string_new (100); 3608 3609 dyn_string_append_cstr (ds, "-shared "); 3610 3611 if (mcore_elf_linker_flags) 3612 dyn_string_append_cstr (ds, mcore_elf_linker_flags); 3613 3614 dyn_string_append_cstr (ds, " "); 3615 dyn_string_append_cstr (ds, MCORE_ELF_TMP_EXP); 3616 dyn_string_append_cstr (ds, " "); 3617 dyn_string_append_cstr (ds, MCORE_ELF_TMP_OBJ); 3618 dyn_string_append_cstr (ds, " -o "); 3619 dyn_string_append_cstr (ds, mcore_elf_out_file); 3620 3621 run (mcore_elf_linker, ds->s); 3622 3623 dyn_string_delete (ds); 3624 3625 if (dontdeltemps == 0) 3626 unlink (MCORE_ELF_TMP_EXP); 3627 3628 if (dontdeltemps < 2) 3629 unlink (MCORE_ELF_TMP_OBJ); 3630 } 3631 #endif /* DLLTOOL_MCORE_ELF */ 3632