/mingw-w64-v2.0.999/binutils/src/binutils/dlltool.c
C | 4544 lines | 4064 code | 144 blank | 336 comment | 109 complexity | d28cb539443f2c2cdefe31cef0b1c95b MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, LGPL-3.0, Unlicense, GPL-2.0, LGPL-2.0, BSD-3-Clause, GPL-3.0
Large files files are truncated, but you can click here to view the full file
- /* dlltool.c -- tool to generate stuff for PE style DLLs
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
- This file is part of GNU Binutils.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
- /* This program allows you to build the files necessary to create
- DLLs to run on a system which understands PE format image files.
- (eg, Windows NT)
- See "Peering Inside the PE: A Tour of the Win32 Portable Executable
- File Format", MSJ 1994, Volume 9 for more information.
- Also see "Microsoft Portable Executable and Common Object File Format,
- Specification 4.1" for more information.
- A DLL contains an export table which contains the information
- which the runtime loader needs to tie up references from a
- referencing program.
- The export table is generated by this program by reading
- in a .DEF file or scanning the .a and .o files which will be in the
- DLL. A .o file can contain information in special ".drectve" sections
- with export information.
- A DEF file contains any number of the following commands:
- NAME <name> [ , <base> ]
- The result is going to be <name>.EXE
- LIBRARY <name> [ , <base> ]
- The result is going to be <name>.DLL
- EXPORTS ( ( ( <name1> [ = <name2> ] )
- | ( <name1> = <module-name> . <external-name>))
- [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] [PRIVATE] ) *
- Declares name1 as an exported symbol from the
- DLL, with optional ordinal number <integer>.
- Or declares name1 as an alias (forward) of the function <external-name>
- in the DLL <module-name>.
- IMPORTS ( ( <internal-name> = <module-name> . <integer> )
- | ( [ <internal-name> = ] <module-name> . <external-name> )) *
- Declares that <external-name> or the exported function whose ordinal number
- is <integer> is to be imported from the file <module-name>. If
- <internal-name> is specified then this is the name that the imported
- function will be refereed to in the body of the DLL.
- DESCRIPTION <string>
- Puts <string> into output .exp file in the .rdata section
- [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
- Generates --stack|--heap <number-reserve>,<number-commit>
- in the output .drectve section. The linker will
- see this and act upon it.
- [CODE|DATA] <attr>+
- SECTIONS ( <sectionname> <attr>+ )*
- <attr> = READ | WRITE | EXECUTE | SHARED
- Generates --attr <sectionname> <attr> in the output
- .drectve section. The linker will see this and act
- upon it.
- A -export:<name> in a .drectve section in an input .o or .a
- file to this program is equivalent to a EXPORTS <name>
- in a .DEF file.
- The program generates output files with the prefix supplied
- on the command line, or in the def file, or taken from the first
- supplied argument.
- The .exp.s file contains the information necessary to export
- the routines in the DLL. The .lib.s file contains the information
- necessary to use the DLL's routines from a referencing program.
- Example:
- file1.c:
- asm (".section .drectve");
- asm (".ascii \"-export:adef\"");
- void adef (char * s)
- {
- printf ("hello from the dll %s\n", s);
- }
- void bdef (char * s)
- {
- printf ("hello from the dll and the other entry point %s\n", s);
- }
- file2.c:
- asm (".section .drectve");
- asm (".ascii \"-export:cdef\"");
- asm (".ascii \"-export:ddef\"");
- void cdef (char * s)
- {
- printf ("hello from the dll %s\n", s);
- }
- void ddef (char * s)
- {
- printf ("hello from the dll and the other entry point %s\n", s);
- }
- int printf (void)
- {
- return 9;
- }
- themain.c:
- int main (void)
- {
- cdef ();
- return 0;
- }
- thedll.def
- LIBRARY thedll
- HEAPSIZE 0x40000, 0x2000
- EXPORTS bdef @ 20
- cdef @ 30 NONAME
- SECTIONS donkey READ WRITE
- aardvark EXECUTE
- # Compile up the parts of the dll and the program
- gcc -c file1.c file2.c themain.c
- # Optional: put the dll objects into a library
- # (you don't have to, you could name all the object
- # files on the dlltool line)
- ar qcv thedll.in file1.o file2.o
- ranlib thedll.in
- # Run this tool over the DLL's .def file and generate an exports
- # file (thedll.o) and an imports file (thedll.a).
- # (You may have to use -S to tell dlltool where to find the assembler).
- dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
- # Build the dll with the library and the export table
- ld -o thedll.dll thedll.o thedll.in
- # Link the executable with the import library
- gcc -o themain.exe themain.o thedll.a
- This example can be extended if relocations are needed in the DLL:
- # Compile up the parts of the dll and the program
- gcc -c file1.c file2.c themain.c
- # Run this tool over the DLL's .def file and generate an imports file.
- dlltool --def thedll.def --output-lib thedll.lib
- # Link the executable with the import library and generate a base file
- # at the same time
- gcc -o themain.exe themain.o thedll.lib -Wl,--base-file -Wl,themain.base
- # Run this tool over the DLL's .def file and generate an exports file
- # which includes the relocations from the base file.
- dlltool --def thedll.def --base-file themain.base --output-exp thedll.exp
- # Build the dll with file1.o, file2.o and the export table
- ld -o thedll.dll thedll.exp file1.o file2.o */
- /* .idata section description
- The .idata section is the import table. It is a collection of several
- subsections used to keep the pieces for each dll together: .idata$[234567].
- IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
- .idata$2 = Import Directory Table
- = array of IMAGE_IMPORT_DESCRIPTOR's.
- DWORD Import Lookup Table; - pointer to .idata$4
- DWORD TimeDateStamp; - currently always 0
- DWORD ForwarderChain; - currently always 0
- DWORD Name; - pointer to dll's name
- PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
- .idata$3 = null terminating entry for .idata$2.
- .idata$4 = Import Lookup Table
- = array of array of pointers to hint name table.
- There is one for each dll being imported from, and each dll's set is
- terminated by a trailing NULL.
- .idata$5 = Import Address Table
- = array of array of pointers to hint name table.
- There is one for each dll being imported from, and each dll's set is
- terminated by a trailing NULL.
- Initially, this table is identical to the Import Lookup Table. However,
- at load time, the loader overwrites the entries with the address of the
- function.
- .idata$6 = Hint Name Table
- = Array of { short, asciz } entries, one for each imported function.
- The `short' is the function's ordinal number.
- .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */
- #include "sysdep.h"
- #include "bfd.h"
- #include "libiberty.h"
- #include "getopt.h"
- #include "demangle.h"
- #include "dyn-string.h"
- #include "bucomm.h"
- #include "dlltool.h"
- #include "safe-ctype.h"
- #include <time.h>
- #include <assert.h>
- #ifdef DLLTOOL_ARM
- #include "coff/arm.h"
- #include "coff/internal.h"
- #endif
- #ifdef DLLTOOL_DEFAULT_MX86_64
- #include "coff/x86_64.h"
- #endif
- #ifdef DLLTOOL_DEFAULT_I386
- #include "coff/i386.h"
- #endif
- #ifndef COFF_PAGE_SIZE
- #define COFF_PAGE_SIZE ((bfd_vma) 4096)
- #endif
- #ifndef PAGE_MASK
- #define PAGE_MASK ((bfd_vma) (- COFF_PAGE_SIZE))
- #endif
- /* Get current BFD error message. */
- #define bfd_get_errmsg() (bfd_errmsg (bfd_get_error ()))
- /* Forward references. */
- static char *look_for_prog (const char *, const char *, int);
- static char *deduce_name (const char *);
- #ifdef DLLTOOL_MCORE_ELF
- static void mcore_elf_cache_filename (const char *);
- static void mcore_elf_gen_out_file (void);
- #endif
- #ifdef HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #else /* ! HAVE_SYS_WAIT_H */
- #if ! defined (_WIN32) || defined (__CYGWIN32__)
- #ifndef WIFEXITED
- #define WIFEXITED(w) (((w) & 0377) == 0)
- #endif
- #ifndef WIFSIGNALED
- #define WIFSIGNALED(w) (((w) & 0377) != 0177 && ((w) & ~0377) == 0)
- #endif
- #ifndef WTERMSIG
- #define WTERMSIG(w) ((w) & 0177)
- #endif
- #ifndef WEXITSTATUS
- #define WEXITSTATUS(w) (((w) >> 8) & 0377)
- #endif
- #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
- #ifndef WIFEXITED
- #define WIFEXITED(w) (((w) & 0xff) == 0)
- #endif
- #ifndef WIFSIGNALED
- #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
- #endif
- #ifndef WTERMSIG
- #define WTERMSIG(w) ((w) & 0x7f)
- #endif
- #ifndef WEXITSTATUS
- #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
- #endif
- #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
- #endif /* ! HAVE_SYS_WAIT_H */
- #define show_allnames 0
- /* ifunc and ihead data structures: ttk@cygnus.com 1997
- When IMPORT declarations are encountered in a .def file the
- function import information is stored in a structure referenced by
- the global variable IMPORT_LIST. The structure is a linked list
- containing the names of the dll files each function is imported
- from and a linked list of functions being imported from that dll
- file. This roughly parallels the structure of the .idata section
- in the PE object file.
- The contents of .def file are interpreted from within the
- process_def_file function. Every time an IMPORT declaration is
- encountered, it is broken up into its component parts and passed to
- def_import. IMPORT_LIST is initialized to NULL in function main. */
- typedef struct ifunct
- {
- char * name; /* Name of function being imported. */
- char * its_name; /* Optional import table symbol name. */
- int ord; /* Two-byte ordinal value associated with function. */
- struct ifunct *next;
- } ifunctype;
- typedef struct iheadt
- {
- char * dllname; /* Name of dll file imported from. */
- long nfuncs; /* Number of functions in list. */
- struct ifunct *funchead; /* First function in list. */
- struct ifunct *functail; /* Last function in list. */
- struct iheadt *next; /* Next dll file in list. */
- } iheadtype;
- /* Structure containing all import information as defined in .def file
- (qv "ihead structure"). */
- static iheadtype *import_list = NULL;
- static char *as_name = NULL;
- static char * as_flags = "";
- static char *tmp_prefix;
- static int no_idata4;
- static int no_idata5;
- static char *exp_name;
- static char *imp_name;
- static char *delayimp_name;
- static char *identify_imp_name;
- static bfd_boolean identify_strict;
- /* Types used to implement a linked list of dllnames associated
- with the specified import lib. Used by the identify_* code.
- The head entry is acts as a sentinal node and is always empty
- (head->dllname is NULL). */
- typedef struct dll_name_list_node_t
- {
- char * dllname;
- struct dll_name_list_node_t * next;
- } dll_name_list_node_type;
- typedef struct dll_name_list_t
- {
- dll_name_list_node_type * head;
- dll_name_list_node_type * tail;
- } dll_name_list_type;
- /* Types used to pass data to iterator functions. */
- typedef struct symname_search_data_t
- {
- const char * symname;
- bfd_boolean found;
- } symname_search_data_type;
- typedef struct identify_data_t
- {
- dll_name_list_type * list;
- bfd_boolean ms_style_implib;
- } identify_data_type;
- static char *head_label;
- static char *imp_name_lab;
- static char *dll_name;
- static int dll_name_set_by_exp_name;
- static int add_indirect = 0;
- static int add_underscore = 0;
- static int add_stdcall_underscore = 0;
- /* This variable can hold three different values. The value
- -1 (default) means that default underscoring should be used,
- zero means that no underscoring should be done, and one
- indicates that underscoring should be done. */
- static int leading_underscore = -1;
- static int dontdeltemps = 0;
- /* TRUE if we should export all symbols. Otherwise, we only export
- symbols listed in .drectve sections or in the def file. */
- static bfd_boolean export_all_symbols;
- /* TRUE if we should exclude the symbols in DEFAULT_EXCLUDES when
- exporting all symbols. */
- static bfd_boolean do_default_excludes = TRUE;
- static bfd_boolean use_nul_prefixed_import_tables = FALSE;
- /* Default symbols to exclude when exporting all the symbols. */
- static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
- /* TRUE if we should add __imp_<SYMBOL> to import libraries for backward
- compatibility to old Cygwin releases. */
- static bfd_boolean create_compat_implib;
- /* TRUE if we have to write PE+ import libraries. */
- static bfd_boolean create_for_pep;
- static char *def_file;
- extern char * program_name;
- static int machine;
- static int killat;
- static int add_stdcall_alias;
- static const char *ext_prefix_alias;
- static int verbose;
- static FILE *output_def;
- static FILE *base_file;
- #ifdef DLLTOOL_DEFAULT_ARM
- static const char *mname = "arm";
- #endif
- #ifdef DLLTOOL_DEFAULT_ARM_EPOC
- static const char *mname = "arm-epoc";
- #endif
- #ifdef DLLTOOL_DEFAULT_ARM_WINCE
- static const char *mname = "arm-wince";
- #endif
- #ifdef DLLTOOL_DEFAULT_I386
- static const char *mname = "i386";
- #endif
- #ifdef DLLTOOL_DEFAULT_MX86_64
- static const char *mname = "i386:x86-64";
- #endif
- #ifdef DLLTOOL_DEFAULT_PPC
- static const char *mname = "ppc";
- #endif
- #ifdef DLLTOOL_DEFAULT_SH
- static const char *mname = "sh";
- #endif
- #ifdef DLLTOOL_DEFAULT_MIPS
- static const char *mname = "mips";
- #endif
- #ifdef DLLTOOL_DEFAULT_MCORE
- static const char * mname = "mcore-le";
- #endif
- #ifdef DLLTOOL_DEFAULT_MCORE_ELF
- static const char * mname = "mcore-elf";
- static char * mcore_elf_out_file = NULL;
- static char * mcore_elf_linker = NULL;
- static char * mcore_elf_linker_flags = NULL;
- #define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
- #endif
- #ifndef DRECTVE_SECTION_NAME
- #define DRECTVE_SECTION_NAME ".drectve"
- #endif
- /* What's the right name for this ? */
- #define PATHMAX 250
- /* External name alias numbering starts here. */
- #define PREFIX_ALIAS_BASE 20000
- char *tmp_asm_buf;
- char *tmp_head_s_buf;
- char *tmp_head_o_buf;
- char *tmp_tail_s_buf;
- char *tmp_tail_o_buf;
- char *tmp_stub_buf;
- #define TMP_ASM dlltmp (&tmp_asm_buf, "%sc.s")
- #define TMP_HEAD_S dlltmp (&tmp_head_s_buf, "%sh.s")
- #define TMP_HEAD_O dlltmp (&tmp_head_o_buf, "%sh.o")
- #define TMP_TAIL_S dlltmp (&tmp_tail_s_buf, "%st.s")
- #define TMP_TAIL_O dlltmp (&tmp_tail_o_buf, "%st.o")
- #define TMP_STUB dlltmp (&tmp_stub_buf, "%ss")
- /* This bit of assembly does jmp * .... */
- static const unsigned char i386_jtab[] =
- {
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
- };
- static const unsigned char i386_dljtab[] =
- {
- 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function */
- 0xB8, 0x00, 0x00, 0x00, 0x00, /* mov eax, offset __imp__function */
- 0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
- };
- static const unsigned char i386_x64_dljtab[] =
- {
- 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function */
- 0x48, 0x8d, 0x05, /* leaq rax, (__imp__function) */
- 0x00, 0x00, 0x00, 0x00,
- 0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
- };
- static const unsigned char arm_jtab[] =
- {
- 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
- 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
- 0, 0, 0, 0
- };
- static const unsigned char arm_interwork_jtab[] =
- {
- 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
- 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */
- 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */
- 0, 0, 0, 0
- };
- static const unsigned char thumb_jtab[] =
- {
- 0x40, 0xb4, /* push {r6} */
- 0x02, 0x4e, /* ldr r6, [pc, #8] */
- 0x36, 0x68, /* ldr r6, [r6] */
- 0xb4, 0x46, /* mov ip, r6 */
- 0x40, 0xbc, /* pop {r6} */
- 0x60, 0x47, /* bx ip */
- 0, 0, 0, 0
- };
- static const unsigned char mcore_be_jtab[] =
- {
- 0x71, 0x02, /* lrw r1,2 */
- 0x81, 0x01, /* ld.w r1,(r1,0) */
- 0x00, 0xC1, /* jmp r1 */
- 0x12, 0x00, /* nop */
- 0x00, 0x00, 0x00, 0x00 /* <address> */
- };
- static const unsigned char mcore_le_jtab[] =
- {
- 0x02, 0x71, /* lrw r1,2 */
- 0x01, 0x81, /* ld.w r1,(r1,0) */
- 0xC1, 0x00, /* jmp r1 */
- 0x00, 0x12, /* nop */
- 0x00, 0x00, 0x00, 0x00 /* <address> */
- };
- /* This is the glue sequence for PowerPC PE. There is a
- tocrel16-tocdefn reloc against the first instruction.
- We also need a IMGLUE reloc against the glue function
- to restore the toc saved by the third instruction in
- the glue. */
- static const unsigned char ppc_jtab[] =
- {
- 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
- /* Reloc TOCREL16 __imp_xxx */
- 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
- 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
- 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
- 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
- 0x20, 0x04, 0x80, 0x4E /* bctr */
- };
- #ifdef DLLTOOL_PPC
- /* The glue instruction, picks up the toc from the stw in
- the above code: "lwz r2,4(r1)". */
- static bfd_vma ppc_glue_insn = 0x80410004;
- #endif
- static const char i386_trampoline[] =
- "\tpushl %%ecx\n"
- "\tpushl %%edx\n"
- "\tpushl %%eax\n"
- "\tpushl $__DELAY_IMPORT_DESCRIPTOR_%s\n"
- "\tcall ___delayLoadHelper2@8\n"
- "\tpopl %%edx\n"
- "\tpopl %%ecx\n"
- "\tjmp *%%eax\n";
- static const char i386_x64_trampoline[] =
- "\tpushq %%rcx\n"
- "\tpushq %%rdx\n"
- "\tpushq %%r8\n"
- "\tpushq %%r9\n"
- "\tsubq $40, %%rsp\n"
- "\tmovq %%rax, %%rdx\n"
- "\tleaq __DELAY_IMPORT_DESCRIPTOR_%s(%%rip), %%rcx\n"
- "\tcall __delayLoadHelper2\n"
- "\taddq $40, %%rsp\n"
- "\tpopq %%r9\n"
- "\tpopq %%r8\n"
- "\tpopq %%rdx\n"
- "\tpopq %%rcx\n"
- "\tjmp *%%rax\n";
- struct mac
- {
- const char *type;
- const char *how_byte;
- const char *how_short;
- const char *how_long;
- const char *how_asciz;
- const char *how_comment;
- const char *how_jump;
- const char *how_global;
- const char *how_space;
- const char *how_align_short;
- const char *how_align_long;
- const char *how_default_as_switches;
- const char *how_bfd_target;
- enum bfd_architecture how_bfd_arch;
- const unsigned char *how_jtab;
- int how_jtab_size; /* Size of the jtab entry. */
- int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5. */
- const unsigned char *how_dljtab;
- int how_dljtab_size; /* Size of the dljtab entry. */
- int how_dljtab_roff1; /* Offset for the ind 32 reloc into idata 5. */
- int how_dljtab_roff2; /* Offset for the ind 32 reloc into idata 5. */
- int how_dljtab_roff3; /* Offset for the ind 32 reloc into idata 5. */
- const char *trampoline;
- };
- static const struct mac
- mtable[] =
- {
- {
- #define MARM 0
- "arm", ".byte", ".short", ".long", ".asciz", "@",
- "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
- ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
- "pe-arm-little", bfd_arch_arm,
- arm_jtab, sizeof (arm_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define M386 1
- "i386", ".byte", ".short", ".long", ".asciz", "#",
- "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
- "pe-i386",bfd_arch_i386,
- i386_jtab, sizeof (i386_jtab), 2,
- i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, i386_trampoline
- }
- ,
- {
- #define MPPC 2
- "ppc", ".byte", ".short", ".long", ".asciz", "#",
- "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
- "pe-powerpcle",bfd_arch_powerpc,
- ppc_jtab, sizeof (ppc_jtab), 0,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MTHUMB 3
- "thumb", ".byte", ".short", ".long", ".asciz", "@",
- "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
- ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
- "pe-arm-little", bfd_arch_arm,
- thumb_jtab, sizeof (thumb_jtab), 12,
- 0, 0, 0, 0, 0, 0
- }
- ,
- #define MARM_INTERWORK 4
- {
- "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
- "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
- ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
- "pe-arm-little", bfd_arch_arm,
- arm_interwork_jtab, sizeof (arm_interwork_jtab), 12,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MMCORE_BE 5
- "mcore-be", ".byte", ".short", ".long", ".asciz", "//",
- "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
- ".global", ".space", ".align\t2",".align\t4", "",
- "pe-mcore-big", bfd_arch_mcore,
- mcore_be_jtab, sizeof (mcore_be_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MMCORE_LE 6
- "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
- "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
- ".global", ".space", ".align\t2",".align\t4", "-EL",
- "pe-mcore-little", bfd_arch_mcore,
- mcore_le_jtab, sizeof (mcore_le_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MMCORE_ELF 7
- "mcore-elf-be", ".byte", ".short", ".long", ".asciz", "//",
- "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
- ".global", ".space", ".align\t2",".align\t4", "",
- "elf32-mcore-big", bfd_arch_mcore,
- mcore_be_jtab, sizeof (mcore_be_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MMCORE_ELF_LE 8
- "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
- "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
- ".global", ".space", ".align\t2",".align\t4", "-EL",
- "elf32-mcore-little", bfd_arch_mcore,
- mcore_le_jtab, sizeof (mcore_le_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MARM_EPOC 9
- "arm-epoc", ".byte", ".short", ".long", ".asciz", "@",
- "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
- ".global", ".space", ".align\t2",".align\t4", "",
- "epoc-pe-arm-little", bfd_arch_arm,
- arm_jtab, sizeof (arm_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MARM_WINCE 10
- "arm-wince", ".byte", ".short", ".long", ".asciz", "@",
- "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
- ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
- "pe-arm-wince-little", bfd_arch_arm,
- arm_jtab, sizeof (arm_jtab), 8,
- 0, 0, 0, 0, 0, 0
- }
- ,
- {
- #define MX86 11
- "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
- "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
- "pe-x86-64",bfd_arch_i386,
- i386_jtab, sizeof (i386_jtab), 2,
- i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, i386_x64_trampoline
- }
- ,
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
- };
- typedef struct dlist
- {
- char *text;
- struct dlist *next;
- }
- dlist_type;
- typedef struct export
- {
- const char *name;
- const char *internal_name;
- const char *import_name;
- const char *its_name;
- int ordinal;
- int constant;
- int noname; /* Don't put name in image file. */
- int private; /* Don't put reference in import lib. */
- int data;
- int hint;
- int forward; /* Number of forward label, 0 means no forward. */
- struct export *next;
- }
- export_type;
- /* A list of symbols which we should not export. */
- struct string_list
- {
- struct string_list *next;
- char *string;
- };
- static struct string_list *excludes;
- static const char *rvaafter (int);
- static const char *rvabefore (int);
- static const char *asm_prefix (int, const char *);
- static void process_def_file (const char *);
- static void new_directive (char *);
- static void append_import (const char *, const char *, int, const char *);
- static void run (const char *, char *);
- static void scan_drectve_symbols (bfd *);
- static void scan_filtered_symbols (bfd *, void *, long, unsigned int);
- static void add_excludes (const char *);
- static bfd_boolean match_exclude (const char *);
- static void set_default_excludes (void);
- static long filter_symbols (bfd *, void *, long, unsigned int);
- static void scan_all_symbols (bfd *);
- static void scan_open_obj_file (bfd *);
- static void scan_obj_file (const char *);
- static void dump_def_info (FILE *);
- static int sfunc (const void *, const void *);
- static void flush_page (FILE *, bfd_vma *, bfd_vma, int);
- static void gen_def_file (void);
- static void generate_idata_ofile (FILE *);
- static void assemble_file (const char *, const char *);
- static void gen_exp_file (void);
- static const char *xlate (const char *);
- static char *make_label (const char *, const char *);
- static char *make_imp_label (const char *, const char *);
- static bfd *make_one_lib_file (export_type *, int, int);
- static bfd *make_head (void);
- static bfd *make_tail (void);
- static bfd *make_delay_head (void);
- static void gen_lib_file (int);
- static void dll_name_list_append (dll_name_list_type *, bfd_byte *);
- static int dll_name_list_count (dll_name_list_type *);
- static void dll_name_list_print (dll_name_list_type *);
- static void dll_name_list_free_contents (dll_name_list_node_type *);
- static void dll_name_list_free (dll_name_list_type *);
- static dll_name_list_type * dll_name_list_create (void);
- static void identify_dll_for_implib (void);
- static void identify_search_archive
- (bfd *, void (*) (bfd *, bfd *, void *), void *);
- static void identify_search_member (bfd *, bfd *, void *);
- static bfd_boolean identify_process_section_p (asection *, bfd_boolean);
- static void identify_search_section (bfd *, asection *, void *);
- static void identify_member_contains_symname (bfd *, bfd *, void *);
- static int pfunc (const void *, const void *);
- static int nfunc (const void *, const void *);
- static void remove_null_names (export_type **);
- static void process_duplicates (export_type **);
- static void fill_ordinals (export_type **);
- static void mangle_defs (void);
- static void usage (FILE *, int);
- static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
- static void set_dll_name_from_def (const char *name, char is_dll);
- static char *
- prefix_encode (char *start, unsigned code)
- {
- static char alpha[26] = "abcdefghijklmnopqrstuvwxyz";
- static char buf[32];
- char *p;
- strcpy (buf, start);
- p = strchr (buf, '\0');
- do
- *p++ = alpha[code % sizeof (alpha)];
- while ((code /= sizeof (alpha)) != 0);
- *p = '\0';
- return buf;
- }
- static char *
- dlltmp (char **buf, const char *fmt)
- {
- if (!*buf)
- {
- *buf = malloc (strlen (tmp_prefix) + 64);
- sprintf (*buf, fmt, tmp_prefix);
- }
- return *buf;
- }
- static void
- inform VPARAMS ((const char * message, ...))
- {
- VA_OPEN (args, message);
- VA_FIXEDARG (args, const char *, message);
- if (!verbose)
- return;
- report (message, args);
- VA_CLOSE (args);
- }
- static const char *
- rvaafter (int mach)
- {
- switch (mach)
- {
- case MARM:
- case M386:
- case MX86:
- case MPPC:
- case MTHUMB:
- case MARM_INTERWORK:
- case MMCORE_BE:
- case MMCORE_LE:
- case MMCORE_ELF:
- case MMCORE_ELF_LE:
- case MARM_EPOC:
- case MARM_WINCE:
- break;
- default:
- /* xgettext:c-format */
- fatal (_("Internal error: Unknown machine type: %d"), mach);
- break;
- }
- return "";
- }
- static const char *
- rvabefore (int mach)
- {
- switch (mach)
- {
- case MARM:
- case M386:
- case MX86:
- case MPPC:
- case MTHUMB:
- case MARM_INTERWORK:
- case MMCORE_BE:
- case MMCORE_LE:
- case MMCORE_ELF:
- case MMCORE_ELF_LE:
- case MARM_EPOC:
- case MARM_WINCE:
- return ".rva\t";
- default:
- /* xgettext:c-format */
- fatal (_("Internal error: Unknown machine type: %d"), mach);
- break;
- }
- return "";
- }
- static const char *
- asm_prefix (int mach, const char *name)
- {
- switch (mach)
- {
- case MARM:
- case MPPC:
- case MTHUMB:
- case MARM_INTERWORK:
- case MMCORE_BE:
- case MMCORE_LE:
- case MMCORE_ELF:
- case MMCORE_ELF_LE:
- case MARM_EPOC:
- case MARM_WINCE:
- break;
- case M386:
- case MX86:
- /* Symbol names starting with ? do not have a leading underscore. */
- if ((name && *name == '?') || leading_underscore == 0)
- break;
- else
- return "_";
- default:
- /* xgettext:c-format */
- fatal (_("Internal error: Unknown machine type: %d"), mach);
- break;
- }
- return "";
- }
- #define ASM_BYTE mtable[machine].how_byte
- #define ASM_SHORT mtable[machine].how_short
- #define ASM_LONG mtable[machine].how_long
- #define ASM_TEXT mtable[machine].how_asciz
- #define ASM_C mtable[machine].how_comment
- #define ASM_JUMP mtable[machine].how_jump
- #define ASM_GLOBAL mtable[machine].how_global
- #define ASM_SPACE mtable[machine].how_space
- #define ASM_ALIGN_SHORT mtable[machine].how_align_short
- #define ASM_RVA_BEFORE rvabefore (machine)
- #define ASM_RVA_AFTER rvaafter (machine)
- #define ASM_PREFIX(NAME) asm_prefix (machine, (NAME))
- #define ASM_ALIGN_LONG mtable[machine].how_align_long
- #define HOW_BFD_READ_TARGET 0 /* Always default. */
- #define HOW_BFD_WRITE_TARGET mtable[machine].how_bfd_target
- #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
- #define HOW_JTAB (delay ? mtable[machine].how_dljtab \
- : mtable[machine].how_jtab)
- #define HOW_JTAB_SIZE (delay ? mtable[machine].how_dljtab_size \
- : mtable[machine].how_jtab_size)
- #define HOW_JTAB_ROFF (delay ? mtable[machine].how_dljtab_roff1 \
- : mtable[machine].how_jtab_roff)
- #define HOW_JTAB_ROFF2 (delay ? mtable[machine].how_dljtab_roff2 : 0)
- #define HOW_JTAB_ROFF3 (delay ? mtable[machine].how_dljtab_roff3 : 0)
- #define ASM_SWITCHES mtable[machine].how_default_as_switches
- static char **oav;
- static void
- process_def_file (const char *name)
- {
- FILE *f = fopen (name, FOPEN_RT);
- if (!f)
- /* xgettext:c-format */
- fatal (_("Can't open def file: %s"), name);
- yyin = f;
- /* xgettext:c-format */
- inform (_("Processing def file: %s"), name);
- yyparse ();
- inform (_("Processed def file"));
- }
- /**********************************************************************/
- /* Communications with the parser. */
- static int d_nfuncs; /* Number of functions exported. */
- static int d_named_nfuncs; /* Number of named functions exported. */
- static int d_low_ord; /* Lowest ordinal index. */
- static int d_high_ord; /* Highest ordinal index. */
- static export_type *d_exports; /* List of exported functions. */
- static export_type **d_exports_lexically; /* Vector of exported functions in alpha order. */
- static dlist_type *d_list; /* Descriptions. */
- static dlist_type *a_list; /* Stuff to go in directives. */
- static int d_nforwards = 0; /* Number of forwarded exports. */
- static int d_is_dll;
- static int d_is_exe;
- int
- yyerror (const char * err ATTRIBUTE_UNUSED)
- {
- /* xgettext:c-format */
- non_fatal (_("Syntax error in def file %s:%d"), def_file, linenumber);
- return 0;
- }
- void
- def_exports (const char *name, const char *internal_name, int ordinal,
- int noname, int constant, int data, int private,
- const char *its_name)
- {
- struct export *p = (struct export *) xmalloc (sizeof (*p));
- p->name = name;
- p->internal_name = internal_name ? internal_name : name;
- p->its_name = its_name;
- p->import_name = name;
- p->ordinal = ordinal;
- p->constant = constant;
- p->noname = noname;
- p->private = private;
- p->data = data;
- p->next = d_exports;
- d_exports = p;
- d_nfuncs++;
- if ((internal_name != NULL)
- && (strchr (internal_name, '.') != NULL))
- p->forward = ++d_nforwards;
- else
- p->forward = 0; /* no forward */
- }
- static void
- set_dll_name_from_def (const char *name, char is_dll)
- {
- const char *image_basename = lbasename (name);
- if (image_basename != name)
- non_fatal (_("%s: Path components stripped from image name, '%s'."),
- def_file, name);
- /* Append the default suffix, if none specified. */
- if (strchr (image_basename, '.') == 0)
- {
- const char * suffix = is_dll ? ".dll" : ".exe";
- dll_name = xmalloc (strlen (image_basename) + strlen (suffix) + 1);
- sprintf (dll_name, "%s%s", image_basename, suffix);
- }
- else
- dll_name = xstrdup (image_basename);
- }
- void
- def_name (const char *name, int base)
- {
- /* xgettext:c-format */
- inform (_("NAME: %s base: %x"), name, base);
- if (d_is_dll)
- non_fatal (_("Can't have LIBRARY and NAME"));
- if (dll_name_set_by_exp_name && name && *name != 0)
- {
- dll_name = NULL;
- dll_name_set_by_exp_name = 0;
- }
- /* If --dllname not provided, use the one in the DEF file.
- FIXME: Is this appropriate for executables? */
- if (!dll_name)
- set_dll_name_from_def (name, 0);
- d_is_exe = 1;
- }
- void
- def_library (const char *name, int base)
- {
- /* xgettext:c-format */
- inform (_("LIBRARY: %s base: %x"), name, base);
- if (d_is_exe)
- non_fatal (_("Can't have LIBRARY and NAME"));
- if (dll_name_set_by_exp_name && name && *name != 0)
- {
- dll_name = NULL;
- dll_name_set_by_exp_name = 0;
- }
- /* If --dllname not provided, use the one in the DEF file. */
- if (!dll_name)
- set_dll_name_from_def (name, 1);
- d_is_dll = 1;
- }
- void
- def_description (const char *desc)
- {
- dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
- d->text = xstrdup (desc);
- d->next = d_list;
- d_list = d;
- }
- static void
- new_directive (char *dir)
- {
- dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
- d->text = xstrdup (dir);
- d->next = a_list;
- a_list = d;
- }
- void
- def_heapsize (int reserve, int commit)
- {
- char b[200];
- if (commit > 0)
- sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
- else
- sprintf (b, "-heap 0x%x ", reserve);
- new_directive (xstrdup (b));
- }
- void
- def_stacksize (int reserve, int commit)
- {
- char b[200];
- if (commit > 0)
- sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
- else
- sprintf (b, "-stack 0x%x ", reserve);
- new_directive (xstrdup (b));
- }
- /* append_import simply adds the given import definition to the global
- import_list. It is used by def_import. */
- static void
- append_import (const char *symbol_name, const char *dllname, int func_ordinal,
- const char *its_name)
- {
- iheadtype **pq;
- iheadtype *q;
- for (pq = &import_list; *pq != NULL; pq = &(*pq)->next)
- {
- if (strcmp ((*pq)->dllname, dllname) == 0)
- {
- q = *pq;
- q->functail->next = xmalloc (sizeof (ifunctype));
- q->functail = q->functail->next;
- q->functail->ord = func_ordinal;
- q->functail->name = xstrdup (symbol_name);
- q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
- q->functail->next = NULL;
- q->nfuncs++;
- return;
- }
- }
- q = xmalloc (sizeof (iheadtype));
- q->dllname = xstrdup (dllname);
- q->nfuncs = 1;
- q->funchead = xmalloc (sizeof (ifunctype));
- q->functail = q->funchead;
- q->next = NULL;
- q->functail->name = xstrdup (symbol_name);
- q->functail->its_name = (its_name ? xstrdup (its_name) : NULL);
- q->functail->ord = func_ordinal;
- q->functail->next = NULL;
- *pq = q;
- }
- /* def_import is called from within defparse.y when an IMPORT
- declaration is encountered. Depending on the form of the
- declaration, the module name may or may not need ".dll" to be
- appended to it, the name of the function may be stored in internal
- or entry, and there may or may not be an ordinal value associated
- with it. */
- /* A note regarding the parse modes:
- In defparse.y we have to accept import declarations which follow
- any one of the following forms:
- <func_name_in_app> = <dll_name>.<func_name_in_dll>
- <func_name_in_app> = <dll_name>.<number>
- <dll_name>.<func_name_in_dll>
- <dll_name>.<number>
- Furthermore, the dll's name may or may not end with ".dll", which
- complicates the parsing a little. Normally the dll's name is
- passed to def_import() in the "module" parameter, but when it ends
- with ".dll" it gets passed in "module" sans ".dll" and that needs
- to be reappended.
- def_import gets five parameters:
- APP_NAME - the name of the function in the application, if
- present, or NULL if not present.
- MODULE - the name of the dll, possibly sans extension (ie, '.dll').
- DLLEXT - the extension of the dll, if present, NULL if not present.
- ENTRY - the name of the function in the dll, if present, or NULL.
- ORD_VAL - the numerical tag of the function in the dll, if present,
- or NULL. Exactly one of <entry> or <ord_val> must be
- present (i.e., not NULL). */
- void
- def_import (const char *app_name, const char *module, const char *dllext,
- const char *entry, int ord_val, const char *its_name)
- {
- const char *application_name;
- char *buf;
- if (entry != NULL)
- application_name = entry;
- else
- {
- if (app_name != NULL)
- application_name = app_name;
- else
- application_name = "";
- }
- if (dllext != NULL)
- {
- buf = (char *) alloca (strlen (module) + strlen (dllext) + 2);
- sprintf (buf, "%s.%s", module, dllext);
- module = buf;
- }
- append_import (application_name, module, ord_val, its_name);
- }
- void
- def_version (int major, int minor)
- {
- printf (_("VERSION %d.%d\n"), major, minor);
- }
- void
- def_section (const char *name, int attr)
- {
- char buf[200];
- char atts[5];
- char *d = atts;
- if (attr & 1)
- *d++ = 'R';
- if (attr & 2)
- *d++ = 'W';
- if (attr & 4)
- *d++ = 'X';
- if (attr & 8)
- *d++ = 'S';
- *d++ = 0;
- sprintf (buf, "-attr %s %s", name, atts);
- new_directive (xstrdup (buf));
- }
- void
- def_code (int attr)
- {
- def_section ("CODE", attr);
- }
- void
- def_data (int attr)
- {
- def_section ("DATA", attr);
- }
- /**********************************************************************/
- static void
- run (const char *what, char *args)
- {
- char *s;
- int pid, wait_status;
- int i;
- const char **argv;
- char *errmsg_fmt, *errmsg_arg;
- char *temp_base = choose_temp_base ();
- inform (_("run: %s %s"), what, args);
- /* Count the args */
- i = 0;
- for (s = args; *s; s++)
- if (*s == ' ')
- i++;
- i++;
- argv = alloca (sizeof (char *) * (i + 3));
- i = 0;
- argv[i++] = what;
- s = args;
- while (1)
- {
- while (*s == ' ')
- ++s;
- argv[i++] = s;
- while (*s != ' ' && *s != 0)
- s++;
- if (*s == 0)
- break;
- *s++ = 0;
- }
- argv[i++] = NULL;
- pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
- &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
- if (pid == -1)
- {
- inform ("%s", strerror (errno));
- fatal (errmsg_fmt, errmsg_arg);
- }
- pid = pwait (pid, & wait_status, 0);
- if (pid == -1)
- {
- /* xgettext:c-format */
- fatal (_("wait: %s"), strerror (errno));
- }
- else if (WIFSIGNALED (wait_status))
- {
- /* xgettext:c-format */
- fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
- }
- else if (WIFEXITED (wait_status))
- {
- if (WEXITSTATUS (wait_status) != 0)
- /* xgettext:c-format */
- non_fatal (_("%s exited with status %d"),
- what, WEXITSTATUS (wait_status));
- }
- else
- abort ();
- }
- /* Look for a list of symbols to export in the .drectve section of
- ABFD. Pass each one to def_exports. */
- static void
- scan_drectve_symbols (bfd *abfd)
- {
- asection * s;
- int size;
- char * buf;
- char * p;
- char * e;
- /* Look for .drectve's */
- s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
- if (s == NULL)
- return;
- size = bfd_get_section_size (s);
- buf = xmalloc (size);
- bfd_get_section_contents (abfd, s, buf, 0, size);
- /* xgettext:c-format */
- inform (_("Sucking in info from %s section in %s"),
- DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
- /* Search for -export: strings. The exported symbols can optionally
- have type tags (eg., -export:foo,data), so handle those as well.
- Currently only data tag is supported. */
- p = buf;
- e = buf + size;
- while (p < e)
- {
- if (p[0] == '-'
- && CONST_STRNEQ (p, "-export:"))
- {
- char * name;
- char * c;
- flagword flags = BSF_FUNCTION;
- p += 8;
- /* Do we have a quoted export? */
- if (*p == '"')
- {
- p++;
- name = p;
- while (p < e && *p != '"')
- ++p;
- }
- else
- {
- name = p;
- while (p < e && *p != ',' && *p != ' ' && *p != '-')
- p++;
- }
- c = xmalloc (p - name + 1);
- memcpy (c, name, p - name);
- c[p - name] = 0;
- /* Advance over trailing quote. */
- if (p < e && *p == '"')
- ++p;
- if (p < e && *p == ',') /* found type tag. */
- {
- char *tag_start = ++p;
- while (p < e && *p != ' ' && *p != '-')
- p++;
- if (CONST_STRNEQ (tag_start, "data"))
- flags &= ~BSF_FUNCTION;
- }
- /* FIXME: The 5th arg is for the `constant' field.
- What should it be? Not that it matters since it's not
- currently useful. */
- def_exports (c, 0, -1, 0, 0, ! (flags & BSF_FUNCTION), 0, NULL);
- if (add_stdcall_alias && strchr (c, '@'))
- {
- int lead_at = (*c == '@') ;
- char *exported_name = xstrdup (c + lead_at);
- char *atsym = strchr (exported_name, '@');
- *atsym = '\0';
- /* Note: stdcall alias symbols can never be data. */
- def_exports (exported_name, xstrdup (c), -1, 0, 0, 0, 0, NULL);
- }
- }
- else
- p++;
- }
- free (buf);
- }
- /* Look through the symbols in MINISYMS, and add each one to list of
- symbols to export. */
- static void
- scan_filtered_symbols (bfd *abfd, void *minisyms, long symcount,
- unsigned int size)
- {
- asymbol *store;
- bfd_byte *from, *fromend;
- store = bfd_make_empty_symbol (abfd);
- if (store == NULL)
- bfd_fatal (bfd_get_filename (abfd));
- from = (bfd_byte *) minisyms;
- fromend = from + symcount * size;
- for (; from < fromend; from += size)
- {
- asymbol *sym;
- const char *symbol_name;
- sym = bfd_minisymbol_to_symbol (abfd, FALSE, from, store);
- if (sym == NULL)
- bfd_fatal (bfd_get_filename (abfd));
- symbol_name = bfd_asymbol_name (sym);
- if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
- ++symbol_name;
- def_exports (xstrdup (symbol_name) , 0, -1, 0, 0,
- ! (sym->flags & BSF_FUNCTION), 0, NULL);
- if (add_stdcall_alias && strchr (symbol_name, '@'))
- {
- int lead_at = (*symbol_name == '@');
- char *exported_name = xstrdup (symbol_name + lead_at);
- char *atsym = strchr (exported_name, '@');
- *atsym = '\0';
- /* Note: stdcall alias symbols can never be data. */
- def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0, 0, NULL);
- }
- }
- }
- /* Add a list of symbols to exclude. */
- static void
- add_excludes (const char *new_excludes)
- {
- char *local_copy;
- char *exclude_string;
- local_copy = xstrdup (new_excludes);
- exclude_string = strtok (local_copy, ",:");
- for (; exclude_string; exclude_string = strtok (NULL, ",:"))
- {
- struct string_list *new_exclude;
- new_exclude = ((struct string_list *)
- xmalloc (sizeof (struct string_list)));
- new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
- /* Don't add a leading underscore for fastcall symbols. */
- if (*exclude_string == '@')
- sprintf (new_exclude->string, "%s", exclude_string);
- else
- sprintf (new_exclude->string, "%s%s", (!leading_underscore ? "" : "_"),
- exclude_string);
- new_exclude->next = excludes;
- excludes = new_exclude;
- /* xgettext:c-format */
- inform (_("Excluding symbol: %s"), exclude_string);
- }
- free (local_copy);
- }
- /* See if STRING is on the list of symbols to exclude. */
- static bfd_boolean
- match_exclude (const char *string)
- {
- struct string_list *excl_item;
- for (excl_item = excludes; excl_item; excl_item = excl_item->next)
- if (strcmp (string, excl_item->string) == 0)
- return TRUE;
- return FALSE;
- }
- /* Add the default list of symbols to exclude. */
- static void
- set_default_excludes (void)
- {
- add_excludes (default_excludes);
- }
- /* Choose which symbols to export. */
- static long
- filter_symbols (bfd *abfd, void *minisyms, long symcount, unsigned int size)
- {
- bfd_byte *from, *fromend, *to;
- asymbol *store;
- store = bfd_make_empty_symbol (abfd);
- if (store == NULL)
- bfd_fatal (bfd_get_filename (abfd));
- from = (bfd_byte *) minisyms;
- fromend = from + symcount * size;
- to = (bfd_byte *) minisyms;
- for (; from < fromend; from += size)
- {
- int keep = 0;
- asymbol *sym;
- sym = bfd_minisymbol_to_symbol (abfd, FALSE, (const void *) from, store);
- if (sym == NULL)
- bfd_fatal (bfd_get_filename (abfd));
- /* Check for external and defined only symbols. */
- keep = (((sym->flags & BSF_GLOBAL) != 0
- || (sym->flags & BSF_WEAK) != 0
- || bfd_is_com_section (sym->section))
- && ! bfd_is_und_section (sym->section));
- keep = keep && ! match_exclude (sym->name);
- if (keep)
- {
- memcpy (to, from, size);
- to += size;
- }
- }
- return (to - (bfd_byte *) minisyms) / size;
- }
- /* Export all symbols in ABFD, except for ones we were told not to
- export. */
- static void
- scan_all_symbols (bfd *abfd)
- {
- long symcount;
- void *minisyms;
- unsigned int size;
- /* Ignore bfds with an import descriptor table. We assume that any
- such BFD contains symbols which are exported from another DLL,
- and we don't want to reexport them from here. */
- if (bfd_get_section_by_name (abfd, ".idata$4"))
- return;
- if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
- {
- /* xgettext:c-format */
- non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
- return;
- }
- symcount = bfd_read_minisymbols (abfd, FALSE, &minisyms, &size);
- if (symcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
- if (symcount == 0)
- {
- /* xgettext:c-format */
- non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
- return;
- }
- /* Discard the symbols we don't want to export. It's OK to do this
- in place; we'll free the storage anyway. */
- symcount = filter_symbols (abfd, minisyms, symcount, size);
- scan_filtered_symbols (abfd, minisyms, symcount, size);
- free (minisyms);
- }
- /* Look at the object file to decide which symbols to export. */
- static void
- scan_open_obj_file (bfd *abfd)
- {
- if (export_all_symbols)
- scan_all_symbols (abfd);
- else
- scan_drectve_symbols (abfd);
- /* FIXME: we ought to read in and block out the base relocations. */
- /* xgettext:c-format */
- inform (_("Done reading %s"), bfd_get_filename (abfd));
- }
- static void
- scan_obj_file (const char *filename)
- {
- bfd * f = bfd_openr (filename, 0);
- if (!f)
- /* xgettext:c-format */
- fatal (_("Unable to open object file: %s: %s"), filename, bfd_get_errmsg ());
- /* xgettext:c-format */
- inform (_("Scanning object file %s"), filename);
- if (bfd_check_format (f, bfd_archive))
- {
- bfd *arfile = bfd_openr_next_archived_file (f, 0);
- while (arfile)
- {
- if (bfd_check_format (arfile, bfd_object))
- scan_open_obj_file (arfile);
- bfd_close (arfile);
- arfile = bfd_openr_next_archived_file (f, arfile);
- }
- #ifdef DLLTOOL_MCORE_ELF
- if (mcore_elf_out_file)
- inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
- #endif
- }
- else if (bfd_check_format (f, bfd_object))
- {
- scan_open_obj_file (f);
- #ifdef DLLTOOL_MCORE_ELF
- if (mcore_elf_out_file)
- mcore_elf_cache_filename (filename);
- #endif
- }
- bfd_close (f);
- }
- static void
- dump_def_info (FILE *f)
- {
- int i;
- export_type *exp;
- fprintf (f, "%s ", ASM_C);
- for (i = 0; oav[i]; i++)
- fprintf (f, "%s ", oav[i]);
- fprintf (f, "\n");
- for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
- {
- fprintf (f, "%s %d = %s %s @ %d %s%s%s%s%s%s\n",
- ASM_C,
- i,
- exp->name,
- exp->internal_name,
- exp->ordinal,
- exp->noname ? "NONAME " : "",
- exp->private ? "PRIVATE " : "",
- exp->constant ? "CONSTANT" : "",
- exp->data ? "DATA" : "",
- exp->its_name ? " ==" : "",
- exp->its_name ? exp->its_name : "");
- }
- }
- /* Generate the .exp file. */
- static int
- sfunc (const void *a, const void *b)
- {
- if (*(const bfd_vma *) a == *(const bfd_vma *) b)
- return 0;
- return ((*(const bfd_vma *) a > *(const bfd_vma *) b) ? 1 : -1);
- }
- static void
- flush_page (FILE *f, bfd_vma *need, bfd_vma page_addr, int on_page)
- {
- int i;
- /* Flush this page. */
- fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
- ASM_LONG,
- (int) page_addr,
- ASM_C);
- fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
- ASM_LONG,
- (on_page * 2) + (on_page & 1) * 2 + 8,
- ASM_C);
- for (i = 0; i < on_page; i++)
- {
- bfd_vma needed = need[i];
- if (needed)
- {
- if (!create_for_pep)
- {
- /* Relocation via HIGHLOW. */
- needed = ((needed - page_addr) | 0x3000) & 0xffff;
- }
- else
- {
- /* Relocation via DIR64. */
- needed = ((needed - page_addr) | 0xa000) & 0xffff;
- }
- }
- fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (long) needed);
- }
- /* And padding */
- if (on_page & 1)
- fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
- }
- static void
- gen_def_file (void)
- {
- int i;
- export_type *exp;
- inform (_("Adding exports to output file"));
- fprintf (output_def, ";");
- for (i = 0; oav[i]; i++)
- fprintf (output_def, " %s", oav[i]);
- fprintf (output_def, "\nEXPORTS\n");
- for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
- {
- char *quote = strchr (exp->name, '.') ? "\"" : "";
- char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
- if (res)
- {
- fprintf (output_def,";\t%s\n", res);
- free (res);
- }
- if (strcmp (exp->name, exp->internal_name) == 0)
- {
- fprintf (outp…
Large files files are truncated, but you can click here to view the full file