changeset 436:91152e505b77

Move tccpe.c into the win32 subdirectory, and fix makefile to know about it.
author Rob Landley <rob@landley.net>
date Thu, 03 May 2007 12:10:26 -0400
parents f16b04be31b6
children 3f48bed56ab4
files Makefile tcc.c tcccoff.c tccpe.c win32/tccpe.c
diffstat 5 files changed, 1248 insertions(+), 1248 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed May 02 18:05:36 2007 -0400
+++ b/Makefile	Thu May 03 12:10:26 2007 -0400
@@ -136,7 +136,7 @@
 
 # Host Tiny C Compiler
 ifdef CONFIG_WIN32
-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c
+tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h win32/tccpe.c
 	$(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS)
 else
 ifeq ($(ARCH),i386)
@@ -159,7 +159,7 @@
 arm-tcc$(EXESUF): tcc.c arm-gen.c tccelf.c tccasm.c tcctok.h libtcc.h
 	$(CC) $(CFLAGS) -DTCC_TARGET_ARM -DTCC_ARM_EABI -o $@ $< $(LIBS)
 
-i386-win32-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h tccpe.c
+i386-win32-tcc$(EXESUF): tcc.c i386-gen.c tccelf.c tccasm.c i386-asm.c tcctok.h libtcc.h i386-asm.h win32/tccpe.c
 	$(CC) $(CFLAGS) -DTCC_TARGET_PE -o $@ $< $(LIBS)
 
 # windows utilities
--- a/tcc.c	Wed May 02 18:05:36 2007 -0400
+++ b/tcc.c	Thu May 03 12:10:26 2007 -0400
@@ -8728,7 +8728,7 @@
 #endif
 
 #ifdef TCC_TARGET_PE
-#include "tccpe.c"
+#include "win32/tccpe.c"
 #endif
 
 /* do all relocations (needed before using tcc_get_symbol()) */
--- a/tcccoff.c	Wed May 02 18:05:36 2007 -0400
+++ b/tcccoff.c	Thu May 03 12:10:26 2007 -0400
@@ -1,5 +1,5 @@
 /*
- *  COFF file handling for TCC
+ *  COFF file handling for TCC  (Needed for c67 target)
  * 
  *  Copyright (c) 2003, 2004 TK
  *  Copyright (c) 2004 Fabrice Bellard
--- a/tccpe.c	Wed May 02 18:05:36 2007 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1244 +0,0 @@
-/*
- *  TCCPE.C - PE file output for the TinyC Compiler
- * 
- *  Copyright (c) 2005 grischka
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-#define ST static
-
-/* XXX: move that to TCC ? */
-int verbose = 0;
-
-/* definitions below are from winnt.h */
-
-typedef struct _IMAGE_DOS_HEADER {	/* DOS .EXE header */
-    WORD e_magic;		/* Magic number */
-    WORD e_cblp;		/* Bytes on last page of file */
-    WORD e_cp;			/* Pages in file */
-    WORD e_crlc;		/* Relocations */
-    WORD e_cparhdr;		/* Size of header in paragraphs */
-    WORD e_minalloc;		/* Minimum extra paragraphs needed */
-    WORD e_maxalloc;		/* Maximum extra paragraphs needed */
-    WORD e_ss;			/* Initial (relative) SS value */
-    WORD e_sp;			/* Initial SP value */
-    WORD e_csum;		/* Checksum */
-    WORD e_ip;			/* Initial IP value */
-    WORD e_cs;			/* Initial (relative) CS value */
-    WORD e_lfarlc;		/* File address of relocation table */
-    WORD e_ovno;		/* Overlay number */
-    WORD e_res[4];		/* Reserved words */
-    WORD e_oemid;		/* OEM identifier (for e_oeminfo) */
-    WORD e_oeminfo;		/* OEM information; e_oemid specific */
-    WORD e_res2[10];		/* Reserved words */
-    DWORD e_lfanew;		/* File address of new exe header */
-    BYTE e_code[0x40];
-
-} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
-
-#define IMAGE_NT_SIGNATURE  0x00004550	/* PE00 */
-#define SIZE_OF_NT_SIGNATURE 4
-
-typedef struct _IMAGE_FILE_HEADER {
-    WORD Machine;
-    WORD NumberOfSections;
-    DWORD TimeDateStamp;
-    DWORD PointerToSymbolTable;
-    DWORD NumberOfSymbols;
-    WORD SizeOfOptionalHeader;
-    WORD Characteristics;
-} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
-
-
-#define IMAGE_SIZEOF_FILE_HEADER 20
-
-typedef struct _IMAGE_DATA_DIRECTORY {
-    DWORD VirtualAddress;
-    DWORD Size;
-} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
-
-
-typedef struct _IMAGE_OPTIONAL_HEADER {
-    /* Standard fields. */
-    WORD Magic;
-    BYTE MajorLinkerVersion;
-    BYTE MinorLinkerVersion;
-    DWORD SizeOfCode;
-    DWORD SizeOfInitializedData;
-    DWORD SizeOfUninitializedData;
-    DWORD AddressOfEntryPoint;
-    DWORD BaseOfCode;
-    DWORD BaseOfData;
-
-    /* NT additional fields. */
-    DWORD ImageBase;
-    DWORD SectionAlignment;
-    DWORD FileAlignment;
-    WORD MajorOperatingSystemVersion;
-    WORD MinorOperatingSystemVersion;
-    WORD MajorImageVersion;
-    WORD MinorImageVersion;
-    WORD MajorSubsystemVersion;
-    WORD MinorSubsystemVersion;
-    DWORD Win32VersionValue;
-    DWORD SizeOfImage;
-    DWORD SizeOfHeaders;
-    DWORD CheckSum;
-    WORD Subsystem;
-    WORD DllCharacteristics;
-    DWORD SizeOfStackReserve;
-    DWORD SizeOfStackCommit;
-    DWORD SizeOfHeapReserve;
-    DWORD SizeOfHeapCommit;
-    DWORD LoaderFlags;
-    DWORD NumberOfRvaAndSizes;
-    IMAGE_DATA_DIRECTORY DataDirectory[16];
-
-} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
-
-
-#define IMAGE_DIRECTORY_ENTRY_EXPORT          0	/* Export Directory */
-#define IMAGE_DIRECTORY_ENTRY_IMPORT          1	/* Import Directory */
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2	/* Resource Directory */
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3	/* Exception Directory */
-#define IMAGE_DIRECTORY_ENTRY_SECURITY        4	/* Security Directory */
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5	/* Base Relocation Table */
-#define IMAGE_DIRECTORY_ENTRY_DEBUG           6	/* Debug Directory */
-/*      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7      (X86 usage) */
-#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7	/* Architecture Specific Data */
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8	/* RVA of GP */
-#define IMAGE_DIRECTORY_ENTRY_TLS             9	/* TLS Directory */
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10	/* Load Configuration Directory */
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11	/* Bound Import Directory in headers */
-#define IMAGE_DIRECTORY_ENTRY_IAT            12	/* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13	/* Delay Load Import Descriptors */
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14	/* COM Runtime descriptor */
-
-/* Section header format. */
-#define IMAGE_SIZEOF_SHORT_NAME              8
-
-typedef struct _IMAGE_SECTION_HEADER {
-    BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
-    union {
-	DWORD PhysicalAddress;
-	DWORD VirtualSize;
-    } Misc;
-    DWORD VirtualAddress;
-    DWORD SizeOfRawData;
-    DWORD PointerToRawData;
-    DWORD PointerToRelocations;
-    DWORD PointerToLinenumbers;
-    WORD NumberOfRelocations;
-    WORD NumberOfLinenumbers;
-    DWORD Characteristics;
-} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
-
-#define IMAGE_SIZEOF_SECTION_HEADER          40
-
-/* ----------------------------------------------------------- */
-typedef struct _IMAGE_BASE_RELOCATION {
-    DWORD VirtualAddress;
-    DWORD SizeOfBlock;
-//  WORD    TypeOffset[1];
-} IMAGE_BASE_RELOCATION;
-
-#define IMAGE_SIZEOF_BASE_RELOCATION         8
-
-#define IMAGE_REL_BASED_ABSOLUTE              0
-#define IMAGE_REL_BASED_HIGH                  1
-#define IMAGE_REL_BASED_LOW                   2
-#define IMAGE_REL_BASED_HIGHLOW               3
-#define IMAGE_REL_BASED_HIGHADJ               4
-#define IMAGE_REL_BASED_MIPS_JMPADDR          5
-#define IMAGE_REL_BASED_SECTION               6
-#define IMAGE_REL_BASED_REL32                 7
-
-/* ----------------------------------------------------------- */
-
-/* ----------------------------------------------------------- */
-IMAGE_DOS_HEADER pe_dos_hdr = {
-    0x5A4D,			/*WORD e_magic;         Magic number */
-    0x0090,			/*WORD e_cblp;          Bytes on last page of file */
-    0x0003,			/*WORD e_cp;            Pages in file */
-    0x0000,			/*WORD e_crlc;          Relocations */
-
-    0x0004,			/*WORD e_cparhdr;       Size of header in paragraphs */
-    0x0000,			/*WORD e_minalloc;      Minimum extra paragraphs needed */
-    0xFFFF,			/*WORD e_maxalloc;      Maximum extra paragraphs needed */
-    0x0000,			/*WORD e_ss;            Initial (relative) SS value */
-
-    0x00B8,			/*WORD e_sp;            Initial SP value */
-    0x0000,			/*WORD e_csum;          Checksum */
-    0x0000,			/*WORD e_ip;            Initial IP value */
-    0x0000,			/*WORD e_cs;            Initial (relative) CS value */
-    0x0040,			/*WORD e_lfarlc;        File address of relocation table */
-    0x0000,			/*WORD e_ovno;          Overlay number */
-    {0, 0, 0, 0},		/*WORD e_res[4];     Reserved words */
-    0x0000,			/*WORD e_oemid;         OEM identifier (for e_oeminfo) */
-    0x0000,			/*WORD e_oeminfo;       OEM information; e_oemid specific */
-    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*WORD e_res2[10];      Reserved words */
-    0x00000080,			/*DWORD   e_lfanew;        File address of new exe header */
-    {				/* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
-     /*0040 */ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8,
-     0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
-     /*0050 */ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
-     0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
-     /*0060 */ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69,
-     0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
-     /*0070 */ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     /*0080 */
-     }
-};
-
-DWORD pe_magic = IMAGE_NT_SIGNATURE;
-
-IMAGE_FILE_HEADER pe_file_hdr = {
-    0x014C,			/*WORD    Machine; */
-    0x0003,			/*WORD    NumberOfSections; */
-    0x00000000,			/*DWORD   TimeDateStamp; */
-    0x00000000,			/*DWORD   PointerToSymbolTable; */
-    0x00000000,			/*DWORD   NumberOfSymbols; */
-    0x00E0,			/*WORD    SizeOfOptionalHeader; */
-    0x030F			/*WORD    Characteristics; */
-};
-
-IMAGE_OPTIONAL_HEADER32 pe_opt_hdr = {
-    /* Standard fields. */
-    0x010B,			/*WORD    Magic; */
-    0x06,			/*BYTE    MajorLinkerVersion; */
-    0x00,			/*BYTE    MinorLinkerVersion; */
-    0x00000000,			/*DWORD   SizeOfCode; */
-    0x00000000,			/*DWORD   SizeOfInitializedData; */
-    0x00000000,			/*DWORD   SizeOfUninitializedData; */
-    0x00000000,			/*DWORD   AddressOfEntryPoint; */
-    0x00000000,			/*DWORD   BaseOfCode; */
-    0x00000000,			/*DWORD   BaseOfData; */
-
-    /* NT additional fields. */
-    0x00400000,			/*DWORD   ImageBase; */
-    0x00001000,			/*DWORD   SectionAlignment; */
-    0x00000200,			/*DWORD   FileAlignment; */
-    0x0004,			/*WORD    MajorOperatingSystemVersion; */
-    0x0000,			/*WORD    MinorOperatingSystemVersion; */
-    0x0000,			/*WORD    MajorImageVersion; */
-    0x0000,			/*WORD    MinorImageVersion; */
-    0x0004,			/*WORD    MajorSubsystemVersion; */
-    0x0000,			/*WORD    MinorSubsystemVersion; */
-    0x00000000,			/*DWORD   Win32VersionValue; */
-    0x00000000,			/*DWORD   SizeOfImage; */
-    0x00000200,			/*DWORD   SizeOfHeaders; */
-    0x00000000,			/*DWORD   CheckSum; */
-    0x0002,			/*WORD    Subsystem; */
-    0x0000,			/*WORD    DllCharacteristics; */
-    0x00100000,			/*DWORD   SizeOfStackReserve; */
-    0x00001000,			/*DWORD   SizeOfStackCommit; */
-    0x00100000,			/*DWORD   SizeOfHeapReserve; */
-    0x00001000,			/*DWORD   SizeOfHeapCommit; */
-    0x00000000,			/*DWORD   LoaderFlags; */
-    0x00000010,			/*DWORD   NumberOfRvaAndSizes; */
-
-    /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
-    {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
-     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}
-};
-
-/*----------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------------*/
-
-struct pe_import_header {
-    DWORD first_entry;
-    DWORD time_date;
-    DWORD forwarder;
-    DWORD lib_name_offset;
-    DWORD first_thunk;
-};
-
-struct pe_export_header {
-    DWORD Characteristics;
-    DWORD TimeDateStamp;
-    DWORD Version;
-    DWORD Name;
-    DWORD Base;
-    DWORD NumberOfFunctions;
-    DWORD NumberOfNames;
-    DWORD AddressOfFunctions;
-    DWORD AddressOfNames;
-    DWORD AddressOfNameOrdinals;
-};
-
-struct pe_reloc_header {
-    DWORD offset;
-    DWORD size;
-};
-
-/* ------------------------------------------------------------- */
-/* internal temporary structures */
-
-ST const char *pe_sec_names[] = {
-    ".text",
-    ".data",
-    ".bss",
-    ".rsrc",
-    ".reloc",
-    ".stab",
-    ".stabstr"
-};
-
-enum {
-    sec_text = 0,
-    sec_data,
-    sec_bss,
-    sec_rsrc,
-    sec_reloc,
-    sec_stab,
-    sec_stabstr,
-    pe_sec_number
-};
-
-ST DWORD pe_flags[] = {
-    0x60000020,			/* ".text", */
-    0xC0000040,			/* ".data", */
-    0xC0000080,			/* ".bss", */
-    0x40000040,			/* ".rsrc", */
-    0x42000040,			/* ".reloc", */
-    0x42000802,			/* ".stab", */
-    0x42000802			/* ".stabstr", */
-};
-
-struct section_info {
-    struct section_info *next;
-    int id;
-    DWORD sh_addr;
-    DWORD sh_size;
-    unsigned char *data;
-    DWORD data_size;
-};
-
-struct import_symbol {
-    int sym_index;
-    int offset;
-};
-
-struct pe_import_info {
-    int dll_index;
-    int sym_count;
-    struct import_symbol **symbols;
-};
-
-struct pe_info {
-    const char *filename;
-    DWORD sizeofheaders;
-    DWORD imagebase;
-    DWORD start_addr;
-    DWORD imp_offs;
-    DWORD imp_size;
-    DWORD iat_offs;
-    DWORD iat_size;
-    DWORD exp_offs;
-    DWORD exp_size;
-    struct section_info sh_info[pe_sec_number];
-    int sec_count;
-    struct pe_import_info **imp_info;
-    int imp_count;
-    Section *reloc;
-    Section *thunk;
-    TCCState *s1;
-};
-
-/* ------------------------------------------------------------- */
-#define PE_MERGE_DATA
-// #define PE_PRINT_SECTIONS
-
-#ifndef MAX_PATH
-#define MAX_PATH 260
-#endif
-
-void error_noabort(const char *, ...);
-
-ST char pe_type;
-
-#define PE_NUL 0
-#define PE_DLL 1
-#define PE_GUI 2
-#define PE_EXE 3
-
-ST int pe_find_import(TCCState * s1, const char *symbol, char *ret)
-{
-    int sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
-    if (0 == sym_index) {
-	/* Hm, maybe it's '_symbol' instead of 'symbol' or '__imp__symbol' */
-	char buffer[100];
-	if (0 == memcmp(symbol, "__imp__", 7))
-	    symbol += 6;
-	else
-	    buffer[0] = '_', strcpy(buffer + 1, symbol), symbol = buffer;
-	sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
-    }
-    if (ret)
-	strcpy(ret, symbol);
-    return sym_index;
-}
-
-#ifdef WIN32
-ST void **pe_imp;
-ST int nb_pe_imp;
-
-void *resolve_sym(struct TCCState *s1, const char *symbol, int type)
-{
-    char buffer[100], *p = buffer;
-    void *a = NULL;
-    int sym_index = pe_find_import(s1, symbol, p);
-    int dll_index;
-    const char *dll_name;
-    void *hm;
-
-    if (sym_index) {
-	dll_index = ((Elf32_Sym *) s1->dynsymtab_section->data)[sym_index].
-	    st_other;
-        dll_name = s1->loaded_dlls[dll_index]->name;
-	hm = GetModuleHandleA(dll_name);
-        if (NULL == hm)
-            hm = LoadLibraryA(dll_name);
-        if (hm) {
-            a = GetProcAddress(hm, buffer);
-            if (a && STT_OBJECT == type) {
-                // need to return a pointer to the address for data objects
-                dynarray_add(&pe_imp, &nb_pe_imp, a);
-                a = &pe_imp[nb_pe_imp - 1];
-            }
-        }
-    }
-    return a;
-}
-#endif
-
-#define for_sym_in_symtab(sym) \
-for (sym = (Elf32_Sym *)symtab_section->data + 1; \
-	 sym < (Elf32_Sym *)(symtab_section->data + \
-		symtab_section->data_offset); \
-	 ++sym)
-
-#define pe_set_datadir(dir,addr,size) \
-	pe_opt_hdr.DataDirectory[dir].VirtualAddress = addr, \
-	pe_opt_hdr.DataDirectory[dir].Size = size
-
-/*----------------------------------------------------------------------------*/
-ST void dynarray_reset(void ***pp, int *n)
-{
-    int i;
-    for (i = 0; i < *n; ++i)
-	tcc_free((*pp)[i]);
-    tcc_free(*pp);
-    *pp = NULL;
-    *n = 0;
-}
-
-ST int dynarray_assoc(void **pp, int n, int key)
-{
-    int i;
-    for (i = 0; i < n; ++i, ++pp)
-	if (key == **(int **) pp)
-	    return i;
-    return -1;
-}
-
-#if 0
-ST DWORD umin(DWORD a, DWORD b)
-{
-    return a < b ? a : b;
-}
-#endif
-
-ST DWORD umax(DWORD a, DWORD b)
-{
-    return a < b ? b : a;
-}
-
-ST void pe_fpad(FILE * fp, DWORD new_pos)
-{
-    DWORD pos = ftell(fp);
-    while (++pos <= new_pos)
-	fputc(0, fp);
-}
-
-ST DWORD pe_file_align(DWORD n)
-{
-    return (n + (0x200 - 1)) & ~(0x200 - 1);
-}
-
-ST DWORD pe_virtual_align(DWORD n)
-{
-    return (n + (0x1000 - 1)) & ~(0x1000 - 1);
-}
-
-ST void pe_align_section(Section * s, int a)
-{
-    int i = s->data_offset & (a - 1);
-    if (i)
-	section_ptr_add(s, a - i);
-}
-
-
-/*----------------------------------------------------------------------------*/
-ST int pe_write_pe(struct pe_info *pe)
-{
-    int i;
-    FILE *op;
-    DWORD file_offset;
-    IMAGE_SECTION_HEADER ish[pe_sec_number], *psh;
-    int sec_index = 0;
-
-    op = fopen(pe->filename, "wb");
-    if (NULL == op) {
-	error_noabort("could not create file: %s", pe->filename);
-	return 1;
-    }
-
-    memset(&ish, 0, sizeof ish);
-
-    pe->sizeofheaders = pe_file_align(sizeof pe_dos_hdr
-				      + sizeof pe_magic
-				      + sizeof pe_file_hdr
-				      + sizeof pe_opt_hdr
-				      +
-				      pe->sec_count *
-				      sizeof(IMAGE_SECTION_HEADER)
-	);
-
-    file_offset = pe->sizeofheaders;
-    pe_fpad(op, file_offset);
-
-    if (2 == verbose)
-	printf("-------------------------------"
-	       "\n  virt   file   size  section" "\n");
-
-    for (i = 0; i < pe->sec_count; ++i) {
-	struct section_info *si = pe->sh_info + i;
-	const char *sh_name = pe_sec_names[si->id];
-	unsigned long addr = si->sh_addr - pe->imagebase;
-	unsigned long size = si->sh_size;
-
-	if (2 == verbose)
-	    printf("%6lx %6lx %6lx  %s\n",
-		   addr, file_offset, size, sh_name);
-
-	switch (si->id) {
-	case sec_text:
-	    pe_opt_hdr.BaseOfCode = addr;
-	    pe_opt_hdr.AddressOfEntryPoint = addr + pe->start_addr;
-	    break;
-
-	case sec_data:
-	    pe_opt_hdr.BaseOfData = addr;
-	    if (pe->imp_size) {
-		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
-			       pe->imp_offs + addr, pe->imp_size);
-		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
-			       pe->iat_offs + addr, pe->iat_size);
-	    }
-	    if (pe->exp_size) {
-		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
-			       pe->exp_offs + addr, pe->exp_size);
-	    }
-	    break;
-
-	case sec_bss:
-	    break;
-
-	case sec_reloc:
-	    pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
-	    break;
-
-	case sec_rsrc:
-	    pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
-	    break;
-
-	case sec_stab:
-	    break;
-
-	case sec_stabstr:
-	    break;
-	}
-
-	psh = &ish[sec_index++];
-	strcpy((char *) psh->Name, sh_name);
-
-	psh->Characteristics = pe_flags[si->id];
-	psh->VirtualAddress = addr;
-	psh->Misc.VirtualSize = size;
-	pe_opt_hdr.SizeOfImage =
-	    umax(psh->VirtualAddress + psh->Misc.VirtualSize,
-		 pe_opt_hdr.SizeOfImage);
-
-	if (si->data_size) {
-	    psh->PointerToRawData = file_offset;
-	    fwrite(si->data, 1, si->data_size, op);
-	    file_offset = pe_file_align(file_offset + si->data_size);
-	    psh->SizeOfRawData = file_offset - psh->PointerToRawData;
-	    pe_fpad(op, file_offset);
-	}
-    }
-
-	/*----------------------------------------------------- */
-
-    pe_file_hdr.NumberOfSections = sec_index;
-    pe_opt_hdr.SizeOfHeaders = pe->sizeofheaders;
-    pe_opt_hdr.ImageBase = pe->imagebase;
-    if (PE_DLL == pe_type)
-	pe_file_hdr.Characteristics = 0x230E;
-    else if (PE_GUI != pe_type)
-	pe_opt_hdr.Subsystem = 3;
-
-    fseek(op, SEEK_SET, 0);
-    fwrite(&pe_dos_hdr, 1, sizeof pe_dos_hdr, op);
-    fwrite(&pe_magic, 1, sizeof pe_magic, op);
-    fwrite(&pe_file_hdr, 1, sizeof pe_file_hdr, op);
-    fwrite(&pe_opt_hdr, 1, sizeof pe_opt_hdr, op);
-    for (i = 0; i < sec_index; ++i)
-	fwrite(&ish[i], 1, sizeof(IMAGE_SECTION_HEADER), op);
-    fclose(op);
-
-    if (2 == verbose)
-	printf("-------------------------------\n");
-    if (verbose)
-	printf("<-- %s (%lu bytes)\n", pe->filename, file_offset);
-
-    return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-ST int pe_add_import(struct pe_info *pe, int sym_index, DWORD offset)
-{
-    int i;
-    int dll_index;
-    struct pe_import_info *p;
-    struct import_symbol *s;
-
-    dll_index =
-	((Elf32_Sym *) pe->s1->dynsymtab_section->data)[sym_index].
-	st_other;
-    i = dynarray_assoc((void **) pe->imp_info, pe->imp_count, dll_index);
-    if (-1 != i) {
-	p = pe->imp_info[i];
-	goto found_dll;
-    }
-    p = tcc_mallocz(sizeof *p);
-    p->dll_index = dll_index;
-    dynarray_add((void ***) &pe->imp_info, &pe->imp_count, p);
-
-  found_dll:
-    i = dynarray_assoc((void **) p->symbols, p->sym_count, sym_index);
-    if (-1 != i)
-	goto found_sym;
-    s = tcc_mallocz(sizeof *s);
-    s->sym_index = sym_index;
-    s->offset = offset;
-    dynarray_add((void ***) &p->symbols, &p->sym_count, s);
-
-  found_sym:
-    return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-ST void pe_build_imports(struct pe_info *pe)
-{
-    int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
-    DWORD voffset = pe->thunk->sh_addr - pe->imagebase;
-    int ndlls = pe->imp_count;
-
-    for (sym_cnt = i = 0; i < ndlls; ++i)
-	sym_cnt += pe->imp_info[i]->sym_count;
-
-    if (0 == sym_cnt)
-	return;
-
-    pe_align_section(pe->thunk, 16);
-
-    pe->imp_offs = dll_ptr = pe->thunk->data_offset;
-    pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header);
-    pe->iat_offs = dll_ptr + pe->imp_size;
-    pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD);
-    section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size);
-
-    thk_ptr = pe->iat_offs;
-    ent_ptr = pe->iat_offs + pe->iat_size;
-    for (i = 0; i < pe->imp_count; ++i) {
-	struct pe_import_header *hdr;
-	int k, n, v;
-	struct pe_import_info *p = pe->imp_info[i];
-	const char *name = pe->s1->loaded_dlls[p->dll_index]->name;
-
-	/* put the dll name into the import header */
-	if (0 == strncmp(name, "lib", 3))
-	    name += 3;
-	v = put_elf_str(pe->thunk, name);
-
-	hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr);
-	hdr->first_thunk = thk_ptr + voffset;
-	hdr->first_entry = ent_ptr + voffset;
-	hdr->lib_name_offset = v + voffset;
-
-	for (k = 0, n = p->sym_count; k <= n; ++k) {
-	    if (k < n) {
-		DWORD offset = p->symbols[k]->offset;
-		int sym_index = p->symbols[k]->sym_index;
-		Elf32_Sym *sym =
-		    (Elf32_Sym *) pe->s1->dynsymtab_section->data +
-		    sym_index;
-		const char *name =
-		    pe->s1->dynsymtab_section->link->data + sym->st_name;
-
-		if (offset & 0x80000000) {	/* ref to data */
-		    Elf32_Sym *sym =
-			&((Elf32_Sym *) symtab_section->
-			  data)[offset & 0x7FFFFFFF];
-		    sym->st_value = thk_ptr;
-		    sym->st_shndx = pe->thunk->sh_num;
-		} else {	/* ref to function */
-
-		    char buffer[100];
-		    sprintf(buffer, "IAT.%s", name);
-		    sym_index =
-			put_elf_sym(symtab_section, thk_ptr, sizeof(DWORD),
-				    ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
-				    0, pe->thunk->sh_num, buffer);
-
-		    put_elf_reloc(symtab_section, text_section, offset, R_386_32,	/*R_JMP_SLOT, */
-				  sym_index);
-		}
-		v = pe->thunk->data_offset + voffset;
-		section_ptr_add(pe->thunk, sizeof(WORD));	/* hint, not used */
-		put_elf_str(pe->thunk, name);
-	    } else {
-		v = 0;		// last entry is zero
-	    }
-	    *(DWORD *) (pe->thunk->data + thk_ptr) =
-		*(DWORD *) (pe->thunk->data + ent_ptr) = v;
-	    thk_ptr += sizeof(DWORD);
-	    ent_ptr += sizeof(DWORD);
-	}
-	dll_ptr += sizeof(struct pe_import_header);
-	dynarray_reset((void ***) &p->symbols, &p->sym_count);
-    }
-    dynarray_reset((void ***) &pe->imp_info, &pe->imp_count);
-}
-
-/* ------------------------------------------------------------- */
-ST int sym_cmp(const void *va, const void *vb)
-{
-    Elf32_Sym *sa = (Elf32_Sym *)symtab_section->data + *(int*)va;
-    Elf32_Sym *sb = (Elf32_Sym *)symtab_section->data + *(int*)vb;
-    const char *ca = symtab_section->link->data + sa->st_name;
-    const char *cb = symtab_section->link->data + sb->st_name;
-    return strcmp(ca, cb);
-}
-
-ST void pe_build_exports(struct pe_info *pe)
-{
-    Elf32_Sym *sym;
-    DWORD func_offset, voffset;
-    struct pe_export_header *hdr;
-    int sym_count, n, ord, *sorted;
-
-    voffset = pe->thunk->sh_addr - pe->imagebase;
-    sym_count = 0, n = 1, sorted = NULL;
-
-    // for simplicity only functions are exported
-    for_sym_in_symtab(sym)
-    {
-        if ((sym->st_other & 1)
-            && sym->st_shndx == text_section->sh_num)
-            dynarray_add((void***)&sorted, &sym_count, (void*)n);
-        ++n;
-    }
-
-    if (0 == sym_count)
-	return;
-
-    qsort (sorted, sym_count, sizeof sorted[0], sym_cmp);
-    pe_align_section(pe->thunk, 16);
-
-    pe->exp_offs = pe->thunk->data_offset;
-    hdr = section_ptr_add(pe->thunk,
-			  sizeof(struct pe_export_header) +
-			  sym_count * (2 * sizeof(DWORD) + sizeof(WORD)));
-
-    func_offset = pe->exp_offs + sizeof(struct pe_export_header);
-
-    hdr->Characteristics = 0;
-    hdr->Base = 1;
-    hdr->NumberOfFunctions = sym_count;
-    hdr->NumberOfNames = sym_count;
-    hdr->AddressOfFunctions = func_offset + voffset;
-    hdr->AddressOfNames         = hdr->AddressOfFunctions + sym_count * sizeof(DWORD);
-    hdr->AddressOfNameOrdinals  = hdr->AddressOfNames + sym_count * sizeof(DWORD);
-    hdr->Name = pe->thunk->data_offset + voffset;
-    put_elf_str(pe->thunk, tcc_basename(pe->filename));
-
-    for (ord = 0; ord < sym_count; ++ord)
-    {
-        char *name; DWORD *p, *pfunc, *pname; WORD *pord;
-        sym = (Elf32_Sym *)symtab_section->data + sorted[ord];
-        name = symtab_section->link->data + sym->st_name;
-        p = (DWORD*)(pe->thunk->data + func_offset);
-        pfunc = p + ord;
-        pname = p + sym_count + ord;
-        pord = (WORD *)(p + 2*sym_count) + ord;
-        *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase;
-	*pname = pe->thunk->data_offset + voffset;
-        *pord  = ord;
-	put_elf_str(pe->thunk, name);
-	/* printf("export: %s\n", name); */
-    }
-    pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
-    tcc_free(sorted);
-}
-
-/* ------------------------------------------------------------- */
-ST void pe_build_reloc(struct pe_info *pe, int *section_order,
-		       int section_count)
-{
-    DWORD offset, block_ptr, addr;
-    int count, i;
-    Elf32_Rel *rel, *rel_end;
-    Section *s = NULL, *sr;
-    offset = addr = block_ptr = count = i = 0;
-    rel = rel_end = NULL;
-    for (;;) {
-	if (rel < rel_end) {
-	    int type = ELF32_R_TYPE(rel->r_info);
-	    addr = rel->r_offset + s->sh_addr;
-	    ++rel;
-	    if (type != R_386_32)
-		continue;
-	    if (count == 0) {	/* new block */
-		block_ptr = pe->reloc->data_offset;
-		section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
-		offset = addr & 0xFFFFFFFF << 12;
-	    }
-	    if ((addr -= offset) < (1 << 12)) {	/* one block spans 4k addresses */
-		WORD *wp = section_ptr_add(pe->reloc, sizeof(WORD));
-		*wp = addr | IMAGE_REL_BASED_HIGHLOW << 12;
-		++count;
-		continue;
-	    }
-	    --rel;
-	} else if (i < section_count) {
-	    sr = (s = pe->s1->sections[section_order[i++]])->reloc;
-	    if (sr) {
-		rel = (Elf32_Rel *) sr->data;
-		rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
-	    }
-	    continue;
-	}
-
-	if (count) {		/* store the last block and ready for a new one */
-	    struct pe_reloc_header *hdr;
-	    if (count & 1)
-		section_ptr_add(pe->reloc, 2), ++count;
-	    hdr = (struct pe_reloc_header *) (pe->reloc->data + block_ptr);
-	    hdr->offset = offset - pe->imagebase;
-	    hdr->size =
-		count * sizeof(WORD) + sizeof(struct pe_reloc_header);
-	    count = 0;
-	}
-	if (rel >= rel_end)
-	    break;
-    }
-}
-
-/* ------------------------------------------------------------- */
-ST int pe_assign_addresses(struct pe_info *pe)
-{
-    int i, k, n;
-    DWORD addr;
-    int section_order[pe_sec_number];
-    struct section_info *si_data = NULL;
-
-    pe->imagebase = PE_DLL == pe_type ? 0x10000000 : 0x00400000;
-    addr = pe->imagebase + 1;
-
-    if (PE_DLL == pe_type)
-	pe->reloc = new_section(pe->s1, ".reloc", SHT_DYNAMIC, SHF_ALLOC);
-
-    for (n = k = 0; n < pe_sec_number; ++n) {
-	for (i = 1; i < pe->s1->nb_sections; ++i) {
-	    Section *s = pe->s1->sections[i];
-	    if (0 == strcmp(s->name, pe_sec_names[n])) {
-		struct section_info *si = &pe->sh_info[pe->sec_count];
-#ifdef PE_MERGE_DATA
-		if (n == sec_bss && si_data) {
-		    /* append .bss to .data */
-		    s->sh_addr = addr = ((addr - 1) | 15) + 1;
-		    addr += s->data_offset;
-		    si_data->sh_size = addr - si_data->sh_addr;
-		} else
-#endif
-		{
-		    si->sh_addr = s->sh_addr = addr =
-			pe_virtual_align(addr);
-		    si->id = n;
-
-		    if (n == sec_data) {
-			pe->thunk = s;
-			si_data = si;
-			pe_build_imports(pe);
-			pe_build_exports(pe);
-		    } else if (n == sec_reloc) {
-			pe_build_reloc(pe, section_order, k);
-		    }
-
-		    if (s->data_offset) {
-			if (n != sec_bss) {
-			    si->data = s->data;
-			    si->data_size = s->data_offset;
-			}
-
-			addr += s->data_offset;
-			si->sh_size = s->data_offset;
-			++pe->sec_count;
-		    }
-		    //printf("Section %08X %04X %s\n", si->sh_addr, si->data_size, s->name);
-		}
-		section_order[k] = i, ++k;
-	    }
-	}
-    }
-    return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-ST int pe_check_symbols(struct pe_info *pe)
-{
-    Elf32_Sym *sym;
-    int ret = 0;
-
-    pe_align_section(text_section, 8);
-
-    for_sym_in_symtab(sym) {
-	if (sym->st_shndx == SHN_UNDEF) {
-	    const char *symbol = symtab_section->link->data + sym->st_name;
-	    unsigned type = ELF32_ST_TYPE(sym->st_info);
-	    int sym_index = pe_find_import(pe->s1, symbol, NULL);
-	    if (sym_index) {
-		if (type == STT_FUNC) {
-		    unsigned long offset = text_section->data_offset;
-		    if (pe_add_import(pe, sym_index, offset + 2)) {
-			/* add the 'jmp IAT[x]' instruction */
-			*(WORD *) section_ptr_add(text_section, 8) =
-			    0x25FF;
-			/* patch the symbol */
-			sym->st_shndx = text_section->sh_num;
-			sym->st_value = offset;
-			continue;
-		    }
-		} else if (type == STT_OBJECT) {	/* data, ptr to that should be */
-		    if (pe_add_import(pe, sym_index,
-				      (sym -
-				      (Elf32_Sym *) symtab_section->data) | 
-                                      0x80000000))
-			continue;
-		}
-	    }
-	    error_noabort("undefined symbol '%s'", symbol);
-	    ret = 1;
-	} else
-	    if (pe->s1->rdynamic
-		&& ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
-	    /* if -rdynamic option, then export all non local symbols */
-	    sym->st_other |= 1;
-	}
-    }
-    return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-#ifdef PE_PRINT_SECTIONS
-ST void pe_print_section(FILE * f, Section * s)
-{				/* just if you'r curious */
-    BYTE *p, *e, b;
-    int i, n, l, m;
-    p = s->data;
-    e = s->data + s->data_offset;
-    l = e - p;
-
-    fprintf(f, "section  \"%s\"", s->name);
-    if (s->link)
-	fprintf(f, "\nlink     \"%s\"", s->link->name);
-    if (s->reloc)
-	fprintf(f, "\nreloc    \"%s\"", s->reloc->name);
-    fprintf(f, "\nv_addr   %08X", s->sh_addr);
-    fprintf(f, "\ncontents %08X", l);
-    fprintf(f, "\n\n");
-
-    if (s->sh_type == SHT_NOBITS)
-	return;
-
-    if (s->sh_type == SHT_SYMTAB)
-	m = sizeof(Elf32_Sym);
-    if (s->sh_type == SHT_REL)
-	m = sizeof(Elf32_Rel);
-    else
-	m = 16;
-
-    for (i = 0; i < l;) {
-	fprintf(f, "%08X", i);
-	for (n = 0; n < m; ++n) {
-	    if (n + i < l)
-		fprintf(f, " %02X", p[i + n]);
-	    else
-		fprintf(f, "   ");
-	}
-
-	if (s->sh_type == SHT_SYMTAB) {
-	    Elf32_Sym *sym = (Elf32_Sym *) (p + i);
-	    const char *name = s->link->data + sym->st_name;
-	    fprintf(f,
-		    "  name:%04X"
-		    "  value:%04X"
-		    "  size:%04X"
-		    "  bind:%02X"
-		    "  type:%02X"
-		    "  other:%02X"
-		    "  shndx:%04X"
-		    "  \"%s\"",
-		    sym->st_name,
-		    sym->st_value,
-		    sym->st_size,
-		    ELF32_ST_BIND(sym->st_info),
-		    ELF32_ST_TYPE(sym->st_info),
-		    sym->st_other, sym->st_shndx, name);
-	} else if (s->sh_type == SHT_REL) {
-	    Elf32_Rel *rel = (Elf32_Rel *) (p + i);
-	    Elf32_Sym *sym =
-		(Elf32_Sym *) s->link->data + ELF32_R_SYM(rel->r_info);
-	    const char *name = s->link->link->data + sym->st_name;
-	    fprintf(f,
-		    "  offset:%04X"
-		    "  type:%02X"
-		    "  symbol:%04X"
-		    "  \"%s\"",
-		    rel->r_offset,
-		    ELF32_R_TYPE(rel->r_info),
-		    ELF32_R_SYM(rel->r_info), name);
-	} else {
-	    fprintf(f, "   ");
-	    for (n = 0; n < m; ++n) {
-		if (n + i < l) {
-		    b = p[i + n];
-		    if (b < 32 || b >= 127)
-			b = '.';
-		    fprintf(f, "%c", b);
-		}
-	    }
-	}
-	i += m;
-	fprintf(f, "\n");
-    }
-    fprintf(f, "\n\n");
-}
-#endif
-
-static int pe_test_cmd(const char **pp, const char *cmd)
-{
-    const char *p;
-    char *q, buf[16];
-    int ret;
-
-    p = *pp;
-    q = buf;
-    while (*p != '\0' && !is_space(*p)) {
-        if ((q - buf) < sizeof(buf) - 1)
-            *q++ = toup(*p);
-        p++;
-    }
-    *q = '\0';
-    ret = !strcmp(buf, cmd);
-    *pp = p;
-    return ret;
-}
-
-/* ------------------------------------------------------------- */
-int pe_load_def_file(TCCState * s1, FILE * fp)
-{
-    DLLReference *dllref;
-    int f = 0, sym_index;
-    char *p, line[120], dllname[40];
-    while (fgets(line, sizeof line, fp)) {
-	p = strchr(line, 0);
-	while (p > line && p[-1] <= ' ')
-	    --p;
-	*p = 0;
-	p = line;
-	while (*p && *p <= ' ')
-	    ++p;
-
-	if (*p && ';' != *p)
-	    switch (f) {
-	    case 0:
-                if (!pe_test_cmd((const char **)&p, "LIBRARY"))
-		    return -1;
-                while (is_space(*p))
-                    p++;
-		pstrcpy(dllname, sizeof(dllname), p);
-		++f;
-		continue;
-
-	    case 1:
-                if (!pe_test_cmd((const char **)&p, "EXPORTS"))
-		    return -1;
-		++f;
-		continue;
-
-	    case 2:
-		dllref =
-		    tcc_malloc(sizeof(DLLReference) + strlen(dllname));
-		strcpy(dllref->name, dllname);
-		dllref->level = 0;
-		dynarray_add((void ***) &s1->loaded_dlls,
-			     &s1->nb_loaded_dlls, dllref);
-		++f;
-
-	    default:
-		/* tccpe needs to know from what dll it should import
-                   the sym */
-		sym_index = add_elf_sym(s1->dynsymtab_section,
-					0, 0, ELF32_ST_INFO(STB_GLOBAL,
-							    STT_FUNC),
-                                        s1->nb_loaded_dlls - 1,
-					text_section->sh_num, p);
-		continue;
-	    }
-    }
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-void pe_guess_outfile(char *objfilename, int output_type)
-{
-    char *ext = strrchr(objfilename, '.');
-    if (NULL == ext)
-        ext = strchr(objfilename, 0);
-    if (output_type == TCC_OUTPUT_DLL)
-        strcpy(ext, ".dll");
-    else
-    if (output_type == TCC_OUTPUT_EXE)
-        strcpy(ext, ".exe");
-    else
-    if (output_type == TCC_OUTPUT_OBJ && strcmp(ext, ".o"))
-        strcpy(ext, ".o");
-    else
-        error("no outputfile given");
-}
-
-/* ------------------------------------------------------------- */
-unsigned long pe_add_runtime(TCCState * s1)
-{
-    const char *start_symbol;
-    unsigned long addr;
-
-    if (find_elf_sym(symtab_section, "WinMain"))
-	pe_type = PE_GUI;
-    else
-    if (TCC_OUTPUT_DLL == s1->output_type)
-    {
-        pe_type = PE_DLL;
-        // need this for 'tccelf.c:relocate_section()'
-        s1->output_type = TCC_OUTPUT_EXE;
-    }
-
-    start_symbol =
-	TCC_OUTPUT_MEMORY == s1->output_type
-	? PE_GUI == pe_type ? "_runwinmain" : NULL
-	: PE_DLL == pe_type ? "_dllstart"
-	: PE_GUI == pe_type ? "_winstart" : "_start";
-
-    /* grab the startup code from libtcc1 */
-    if (start_symbol)
-	add_elf_sym(symtab_section,
-		    0, 0,
-		    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
-		    SHN_UNDEF, start_symbol);
-
-    if (0 == s1->nostdlib) {
-	tcc_add_library(s1, "tcc1");
-	tcc_add_library(s1, "msvcrt");
-	if (PE_DLL == pe_type || PE_GUI == pe_type) {
-	    tcc_add_library(s1, "kernel32");
-	    tcc_add_library(s1, "user32");
-	    tcc_add_library(s1, "gdi32");
-	}
-    }
-
-    addr = start_symbol ?
-	(unsigned long) tcc_get_symbol_err(s1, start_symbol) : 0;
-
-    if (s1->output_type == TCC_OUTPUT_MEMORY && addr) {
-	/* for -run GUI's, put '_runwinmain' instead of 'main' */
-	add_elf_sym(symtab_section,
-		    addr, 0,
-		    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
-		    text_section->sh_num, "main");
-
-	/* FreeConsole(); */
-    }
-    return addr;
-}
-
-int tcc_output_pe(TCCState * s1, const char *filename)
-{
-    int ret;
-    struct pe_info pe;
-    int i;
-    memset(&pe, 0, sizeof pe);
-    pe.filename = filename;
-    pe.s1 = s1;
-    pe.start_addr = pe_add_runtime(s1);
-
-    relocate_common_syms();	/* assign bss adresses */
-    ret = pe_check_symbols(&pe);
-    if (0 == ret) {
-	pe_assign_addresses(&pe);
-	relocate_syms(s1, 0);
-	for (i = 1; i < s1->nb_sections; ++i) {
-	    Section *s = s1->sections[i];
-	    if (s->reloc)
-		relocate_section(s1, s);
-	}
-	ret = pe_write_pe(&pe);
-    }
-#ifdef PE_PRINT_SECTIONS
-    {
-	Section *s;
-	FILE *f;
-        f = fopen("tccpe.log", "wt");
-	for (i = 1; i < s1->nb_sections; ++i) {
-	    s = s1->sections[i];
-	    pe_print_section(f, s);
-	}
-	pe_print_section(f, s1->dynsymtab_section);
-	fclose(f);
-    }
-#endif
-    return ret;
-}
-
-/*----------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/win32/tccpe.c	Thu May 03 12:10:26 2007 -0400
@@ -0,0 +1,1244 @@
+/*
+ *  TCCPE.C - PE file output for the TinyC Compiler
+ * 
+ *  Copyright (c) 2005 grischka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+#define ST static
+
+/* XXX: move that to TCC ? */
+int verbose = 0;
+
+/* definitions below are from winnt.h */
+
+typedef struct _IMAGE_DOS_HEADER {	/* DOS .EXE header */
+    WORD e_magic;		/* Magic number */
+    WORD e_cblp;		/* Bytes on last page of file */
+    WORD e_cp;			/* Pages in file */
+    WORD e_crlc;		/* Relocations */
+    WORD e_cparhdr;		/* Size of header in paragraphs */
+    WORD e_minalloc;		/* Minimum extra paragraphs needed */
+    WORD e_maxalloc;		/* Maximum extra paragraphs needed */
+    WORD e_ss;			/* Initial (relative) SS value */
+    WORD e_sp;			/* Initial SP value */
+    WORD e_csum;		/* Checksum */
+    WORD e_ip;			/* Initial IP value */
+    WORD e_cs;			/* Initial (relative) CS value */
+    WORD e_lfarlc;		/* File address of relocation table */
+    WORD e_ovno;		/* Overlay number */
+    WORD e_res[4];		/* Reserved words */
+    WORD e_oemid;		/* OEM identifier (for e_oeminfo) */
+    WORD e_oeminfo;		/* OEM information; e_oemid specific */
+    WORD e_res2[10];		/* Reserved words */
+    DWORD e_lfanew;		/* File address of new exe header */
+    BYTE e_code[0x40];
+
+} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+#define IMAGE_NT_SIGNATURE  0x00004550	/* PE00 */
+#define SIZE_OF_NT_SIGNATURE 4
+
+typedef struct _IMAGE_FILE_HEADER {
+    WORD Machine;
+    WORD NumberOfSections;
+    DWORD TimeDateStamp;
+    DWORD PointerToSymbolTable;
+    DWORD NumberOfSymbols;
+    WORD SizeOfOptionalHeader;
+    WORD Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+
+#define IMAGE_SIZEOF_FILE_HEADER 20
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+    DWORD VirtualAddress;
+    DWORD Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+    /* Standard fields. */
+    WORD Magic;
+    BYTE MajorLinkerVersion;
+    BYTE MinorLinkerVersion;
+    DWORD SizeOfCode;
+    DWORD SizeOfInitializedData;
+    DWORD SizeOfUninitializedData;
+    DWORD AddressOfEntryPoint;
+    DWORD BaseOfCode;
+    DWORD BaseOfData;
+
+    /* NT additional fields. */
+    DWORD ImageBase;
+    DWORD SectionAlignment;
+    DWORD FileAlignment;
+    WORD MajorOperatingSystemVersion;
+    WORD MinorOperatingSystemVersion;
+    WORD MajorImageVersion;
+    WORD MinorImageVersion;
+    WORD MajorSubsystemVersion;
+    WORD MinorSubsystemVersion;
+    DWORD Win32VersionValue;
+    DWORD SizeOfImage;
+    DWORD SizeOfHeaders;
+    DWORD CheckSum;
+    WORD Subsystem;
+    WORD DllCharacteristics;
+    DWORD SizeOfStackReserve;
+    DWORD SizeOfStackCommit;
+    DWORD SizeOfHeapReserve;
+    DWORD SizeOfHeapCommit;
+    DWORD LoaderFlags;
+    DWORD NumberOfRvaAndSizes;
+    IMAGE_DATA_DIRECTORY DataDirectory[16];
+
+} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
+
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT          0	/* Export Directory */
+#define IMAGE_DIRECTORY_ENTRY_IMPORT          1	/* Import Directory */
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2	/* Resource Directory */
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3	/* Exception Directory */
+#define IMAGE_DIRECTORY_ENTRY_SECURITY        4	/* Security Directory */
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5	/* Base Relocation Table */
+#define IMAGE_DIRECTORY_ENTRY_DEBUG           6	/* Debug Directory */
+/*      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7      (X86 usage) */
+#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7	/* Architecture Specific Data */
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8	/* RVA of GP */
+#define IMAGE_DIRECTORY_ENTRY_TLS             9	/* TLS Directory */
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10	/* Load Configuration Directory */
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11	/* Bound Import Directory in headers */
+#define IMAGE_DIRECTORY_ENTRY_IAT            12	/* Import Address Table */
+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13	/* Delay Load Import Descriptors */
+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14	/* COM Runtime descriptor */
+
+/* Section header format. */
+#define IMAGE_SIZEOF_SHORT_NAME              8
+
+typedef struct _IMAGE_SECTION_HEADER {
+    BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
+    union {
+	DWORD PhysicalAddress;
+	DWORD VirtualSize;
+    } Misc;
+    DWORD VirtualAddress;
+    DWORD SizeOfRawData;
+    DWORD PointerToRawData;
+    DWORD PointerToRelocations;
+    DWORD PointerToLinenumbers;
+    WORD NumberOfRelocations;
+    WORD NumberOfLinenumbers;
+    DWORD Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define IMAGE_SIZEOF_SECTION_HEADER          40
+
+/* ----------------------------------------------------------- */
+typedef struct _IMAGE_BASE_RELOCATION {
+    DWORD VirtualAddress;
+    DWORD SizeOfBlock;
+//  WORD    TypeOffset[1];
+} IMAGE_BASE_RELOCATION;
+
+#define IMAGE_SIZEOF_BASE_RELOCATION         8
+
+#define IMAGE_REL_BASED_ABSOLUTE              0
+#define IMAGE_REL_BASED_HIGH                  1
+#define IMAGE_REL_BASED_LOW                   2
+#define IMAGE_REL_BASED_HIGHLOW               3
+#define IMAGE_REL_BASED_HIGHADJ               4
+#define IMAGE_REL_BASED_MIPS_JMPADDR          5
+#define IMAGE_REL_BASED_SECTION               6
+#define IMAGE_REL_BASED_REL32                 7
+
+/* ----------------------------------------------------------- */
+
+/* ----------------------------------------------------------- */
+IMAGE_DOS_HEADER pe_dos_hdr = {
+    0x5A4D,			/*WORD e_magic;         Magic number */
+    0x0090,			/*WORD e_cblp;          Bytes on last page of file */
+    0x0003,			/*WORD e_cp;            Pages in file */
+    0x0000,			/*WORD e_crlc;          Relocations */
+
+    0x0004,			/*WORD e_cparhdr;       Size of header in paragraphs */
+    0x0000,			/*WORD e_minalloc;      Minimum extra paragraphs needed */
+    0xFFFF,			/*WORD e_maxalloc;      Maximum extra paragraphs needed */
+    0x0000,			/*WORD e_ss;            Initial (relative) SS value */
+
+    0x00B8,			/*WORD e_sp;            Initial SP value */
+    0x0000,			/*WORD e_csum;          Checksum */
+    0x0000,			/*WORD e_ip;            Initial IP value */
+    0x0000,			/*WORD e_cs;            Initial (relative) CS value */
+    0x0040,			/*WORD e_lfarlc;        File address of relocation table */
+    0x0000,			/*WORD e_ovno;          Overlay number */
+    {0, 0, 0, 0},		/*WORD e_res[4];     Reserved words */
+    0x0000,			/*WORD e_oemid;         OEM identifier (for e_oeminfo) */
+    0x0000,			/*WORD e_oeminfo;       OEM information; e_oemid specific */
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},	/*WORD e_res2[10];      Reserved words */
+    0x00000080,			/*DWORD   e_lfanew;        File address of new exe header */
+    {				/* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
+     /*0040 */ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8,
+     0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
+     /*0050 */ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+     0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+     /*0060 */ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69,
+     0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+     /*0070 */ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     /*0080 */
+     }
+};
+
+DWORD pe_magic = IMAGE_NT_SIGNATURE;
+
+IMAGE_FILE_HEADER pe_file_hdr = {
+    0x014C,			/*WORD    Machine; */
+    0x0003,			/*WORD    NumberOfSections; */
+    0x00000000,			/*DWORD   TimeDateStamp; */
+    0x00000000,			/*DWORD   PointerToSymbolTable; */
+    0x00000000,			/*DWORD   NumberOfSymbols; */
+    0x00E0,			/*WORD    SizeOfOptionalHeader; */
+    0x030F			/*WORD    Characteristics; */
+};
+
+IMAGE_OPTIONAL_HEADER32 pe_opt_hdr = {
+    /* Standard fields. */
+    0x010B,			/*WORD    Magic; */
+    0x06,			/*BYTE    MajorLinkerVersion; */
+    0x00,			/*BYTE    MinorLinkerVersion; */
+    0x00000000,			/*DWORD   SizeOfCode; */
+    0x00000000,			/*DWORD   SizeOfInitializedData; */
+    0x00000000,			/*DWORD   SizeOfUninitializedData; */
+    0x00000000,			/*DWORD   AddressOfEntryPoint; */
+    0x00000000,			/*DWORD   BaseOfCode; */
+    0x00000000,			/*DWORD   BaseOfData; */
+
+    /* NT additional fields. */
+    0x00400000,			/*DWORD   ImageBase; */
+    0x00001000,			/*DWORD   SectionAlignment; */
+    0x00000200,			/*DWORD   FileAlignment; */
+    0x0004,			/*WORD    MajorOperatingSystemVersion; */
+    0x0000,			/*WORD    MinorOperatingSystemVersion; */
+    0x0000,			/*WORD    MajorImageVersion; */
+    0x0000,			/*WORD    MinorImageVersion; */
+    0x0004,			/*WORD    MajorSubsystemVersion; */
+    0x0000,			/*WORD    MinorSubsystemVersion; */
+    0x00000000,			/*DWORD   Win32VersionValue; */
+    0x00000000,			/*DWORD   SizeOfImage; */
+    0x00000200,			/*DWORD   SizeOfHeaders; */
+    0x00000000,			/*DWORD   CheckSum; */
+    0x0002,			/*WORD    Subsystem; */
+    0x0000,			/*WORD    DllCharacteristics; */
+    0x00100000,			/*DWORD   SizeOfStackReserve; */
+    0x00001000,			/*DWORD   SizeOfStackCommit; */
+    0x00100000,			/*DWORD   SizeOfHeapReserve; */
+    0x00001000,			/*DWORD   SizeOfHeapCommit; */
+    0x00000000,			/*DWORD   LoaderFlags; */
+    0x00000010,			/*DWORD   NumberOfRvaAndSizes; */
+
+    /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
+    {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}
+};
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+
+struct pe_import_header {
+    DWORD first_entry;
+    DWORD time_date;
+    DWORD forwarder;
+    DWORD lib_name_offset;
+    DWORD first_thunk;
+};
+
+struct pe_export_header {
+    DWORD Characteristics;
+    DWORD TimeDateStamp;
+    DWORD Version;
+    DWORD Name;
+    DWORD Base;
+    DWORD NumberOfFunctions;
+    DWORD NumberOfNames;
+    DWORD AddressOfFunctions;
+    DWORD AddressOfNames;
+    DWORD AddressOfNameOrdinals;
+};
+
+struct pe_reloc_header {
+    DWORD offset;
+    DWORD size;
+};
+
+/* ------------------------------------------------------------- */
+/* internal temporary structures */
+
+ST const char *pe_sec_names[] = {
+    ".text",
+    ".data",
+    ".bss",
+    ".rsrc",
+    ".reloc",
+    ".stab",
+    ".stabstr"
+};
+
+enum {
+    sec_text = 0,
+    sec_data,
+    sec_bss,
+    sec_rsrc,
+    sec_reloc,
+    sec_stab,
+    sec_stabstr,
+    pe_sec_number
+};
+
+ST DWORD pe_flags[] = {
+    0x60000020,			/* ".text", */
+    0xC0000040,			/* ".data", */
+    0xC0000080,			/* ".bss", */
+    0x40000040,			/* ".rsrc", */
+    0x42000040,			/* ".reloc", */
+    0x42000802,			/* ".stab", */
+    0x42000802			/* ".stabstr", */
+};
+
+struct section_info {
+    struct section_info *next;
+    int id;
+    DWORD sh_addr;
+    DWORD sh_size;
+    unsigned char *data;
+    DWORD data_size;
+};
+
+struct import_symbol {
+    int sym_index;
+    int offset;
+};
+
+struct pe_import_info {
+    int dll_index;
+    int sym_count;
+    struct import_symbol **symbols;
+};
+
+struct pe_info {
+    const char *filename;
+    DWORD sizeofheaders;
+    DWORD imagebase;
+    DWORD start_addr;
+    DWORD imp_offs;
+    DWORD imp_size;
+    DWORD iat_offs;
+    DWORD iat_size;
+    DWORD exp_offs;
+    DWORD exp_size;
+    struct section_info sh_info[pe_sec_number];
+    int sec_count;
+    struct pe_import_info **imp_info;
+    int imp_count;
+    Section *reloc;
+    Section *thunk;
+    TCCState *s1;
+};
+
+/* ------------------------------------------------------------- */
+#define PE_MERGE_DATA
+// #define PE_PRINT_SECTIONS
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+void error_noabort(const char *, ...);
+
+ST char pe_type;
+
+#define PE_NUL 0
+#define PE_DLL 1
+#define PE_GUI 2
+#define PE_EXE 3
+
+ST int pe_find_import(TCCState * s1, const char *symbol, char *ret)
+{
+    int sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
+    if (0 == sym_index) {
+	/* Hm, maybe it's '_symbol' instead of 'symbol' or '__imp__symbol' */
+	char buffer[100];
+	if (0 == memcmp(symbol, "__imp__", 7))
+	    symbol += 6;
+	else
+	    buffer[0] = '_', strcpy(buffer + 1, symbol), symbol = buffer;
+	sym_index = find_elf_sym(s1->dynsymtab_section, symbol);
+    }
+    if (ret)
+	strcpy(ret, symbol);
+    return sym_index;
+}
+
+#ifdef WIN32
+ST void **pe_imp;
+ST int nb_pe_imp;
+
+void *resolve_sym(struct TCCState *s1, const char *symbol, int type)
+{
+    char buffer[100], *p = buffer;
+    void *a = NULL;
+    int sym_index = pe_find_import(s1, symbol, p);
+    int dll_index;
+    const char *dll_name;
+    void *hm;
+
+    if (sym_index) {
+	dll_index = ((Elf32_Sym *) s1->dynsymtab_section->data)[sym_index].
+	    st_other;
+        dll_name = s1->loaded_dlls[dll_index]->name;
+	hm = GetModuleHandleA(dll_name);
+        if (NULL == hm)
+            hm = LoadLibraryA(dll_name);
+        if (hm) {
+            a = GetProcAddress(hm, buffer);
+            if (a && STT_OBJECT == type) {
+                // need to return a pointer to the address for data objects
+                dynarray_add(&pe_imp, &nb_pe_imp, a);
+                a = &pe_imp[nb_pe_imp - 1];
+            }
+        }
+    }
+    return a;
+}
+#endif
+
+#define for_sym_in_symtab(sym) \
+for (sym = (Elf32_Sym *)symtab_section->data + 1; \
+	 sym < (Elf32_Sym *)(symtab_section->data + \
+		symtab_section->data_offset); \
+	 ++sym)
+
+#define pe_set_datadir(dir,addr,size) \
+	pe_opt_hdr.DataDirectory[dir].VirtualAddress = addr, \
+	pe_opt_hdr.DataDirectory[dir].Size = size
+
+/*----------------------------------------------------------------------------*/
+ST void dynarray_reset(void ***pp, int *n)
+{
+    int i;
+    for (i = 0; i < *n; ++i)
+	tcc_free((*pp)[i]);
+    tcc_free(*pp);
+    *pp = NULL;
+    *n = 0;
+}
+
+ST int dynarray_assoc(void **pp, int n, int key)
+{
+    int i;
+    for (i = 0; i < n; ++i, ++pp)
+	if (key == **(int **) pp)
+	    return i;
+    return -1;
+}
+
+#if 0
+ST DWORD umin(DWORD a, DWORD b)
+{
+    return a < b ? a : b;
+}
+#endif
+
+ST DWORD umax(DWORD a, DWORD b)
+{
+    return a < b ? b : a;
+}
+
+ST void pe_fpad(FILE * fp, DWORD new_pos)
+{
+    DWORD pos = ftell(fp);
+    while (++pos <= new_pos)
+	fputc(0, fp);
+}
+
+ST DWORD pe_file_align(DWORD n)
+{
+    return (n + (0x200 - 1)) & ~(0x200 - 1);
+}
+
+ST DWORD pe_virtual_align(DWORD n)
+{
+    return (n + (0x1000 - 1)) & ~(0x1000 - 1);
+}
+
+ST void pe_align_section(Section * s, int a)
+{
+    int i = s->data_offset & (a - 1);
+    if (i)
+	section_ptr_add(s, a - i);
+}
+
+
+/*----------------------------------------------------------------------------*/
+ST int pe_write_pe(struct pe_info *pe)
+{
+    int i;
+    FILE *op;
+    DWORD file_offset;
+    IMAGE_SECTION_HEADER ish[pe_sec_number], *psh;
+    int sec_index = 0;
+
+    op = fopen(pe->filename, "wb");
+    if (NULL == op) {
+	error_noabort("could not create file: %s", pe->filename);
+	return 1;
+    }
+
+    memset(&ish, 0, sizeof ish);
+
+    pe->sizeofheaders = pe_file_align(sizeof pe_dos_hdr
+				      + sizeof pe_magic
+				      + sizeof pe_file_hdr
+				      + sizeof pe_opt_hdr
+				      +
+				      pe->sec_count *
+				      sizeof(IMAGE_SECTION_HEADER)
+	);
+
+    file_offset = pe->sizeofheaders;
+    pe_fpad(op, file_offset);
+
+    if (2 == verbose)
+	printf("-------------------------------"
+	       "\n  virt   file   size  section" "\n");
+
+    for (i = 0; i < pe->sec_count; ++i) {
+	struct section_info *si = pe->sh_info + i;
+	const char *sh_name = pe_sec_names[si->id];
+	unsigned long addr = si->sh_addr - pe->imagebase;
+	unsigned long size = si->sh_size;
+
+	if (2 == verbose)
+	    printf("%6lx %6lx %6lx  %s\n",
+		   addr, file_offset, size, sh_name);
+
+	switch (si->id) {
+	case sec_text:
+	    pe_opt_hdr.BaseOfCode = addr;
+	    pe_opt_hdr.AddressOfEntryPoint = addr + pe->start_addr;
+	    break;
+
+	case sec_data:
+	    pe_opt_hdr.BaseOfData = addr;
+	    if (pe->imp_size) {
+		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
+			       pe->imp_offs + addr, pe->imp_size);
+		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
+			       pe->iat_offs + addr, pe->iat_size);
+	    }
+	    if (pe->exp_size) {
+		pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
+			       pe->exp_offs + addr, pe->exp_size);
+	    }
+	    break;
+
+	case sec_bss:
+	    break;
+
+	case sec_reloc:
+	    pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
+	    break;
+
+	case sec_rsrc:
+	    pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
+	    break;
+
+	case sec_stab:
+	    break;
+
+	case sec_stabstr:
+	    break;
+	}
+
+	psh = &ish[sec_index++];
+	strcpy((char *) psh->Name, sh_name);
+
+	psh->Characteristics = pe_flags[si->id];
+	psh->VirtualAddress = addr;
+	psh->Misc.VirtualSize = size;
+	pe_opt_hdr.SizeOfImage =
+	    umax(psh->VirtualAddress + psh->Misc.VirtualSize,
+		 pe_opt_hdr.SizeOfImage);
+
+	if (si->data_size) {
+	    psh->PointerToRawData = file_offset;
+	    fwrite(si->data, 1, si->data_size, op);
+	    file_offset = pe_file_align(file_offset + si->data_size);
+	    psh->SizeOfRawData = file_offset - psh->PointerToRawData;
+	    pe_fpad(op, file_offset);
+	}
+    }
+
+	/*----------------------------------------------------- */
+
+    pe_file_hdr.NumberOfSections = sec_index;
+    pe_opt_hdr.SizeOfHeaders = pe->sizeofheaders;
+    pe_opt_hdr.ImageBase = pe->imagebase;
+    if (PE_DLL == pe_type)
+	pe_file_hdr.Characteristics = 0x230E;
+    else if (PE_GUI != pe_type)
+	pe_opt_hdr.Subsystem = 3;
+
+    fseek(op, SEEK_SET, 0);
+    fwrite(&pe_dos_hdr, 1, sizeof pe_dos_hdr, op);
+    fwrite(&pe_magic, 1, sizeof pe_magic, op);
+    fwrite(&pe_file_hdr, 1, sizeof pe_file_hdr, op);
+    fwrite(&pe_opt_hdr, 1, sizeof pe_opt_hdr, op);
+    for (i = 0; i < sec_index; ++i)
+	fwrite(&ish[i], 1, sizeof(IMAGE_SECTION_HEADER), op);
+    fclose(op);
+
+    if (2 == verbose)
+	printf("-------------------------------\n");
+    if (verbose)
+	printf("<-- %s (%lu bytes)\n", pe->filename, file_offset);
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+ST int pe_add_import(struct pe_info *pe, int sym_index, DWORD offset)
+{
+    int i;
+    int dll_index;
+    struct pe_import_info *p;
+    struct import_symbol *s;
+
+    dll_index =
+	((Elf32_Sym *) pe->s1->dynsymtab_section->data)[sym_index].
+	st_other;
+    i = dynarray_assoc((void **) pe->imp_info, pe->imp_count, dll_index);
+    if (-1 != i) {
+	p = pe->imp_info[i];
+	goto found_dll;
+    }
+    p = tcc_mallocz(sizeof *p);
+    p->dll_index = dll_index;
+    dynarray_add((void ***) &pe->imp_info, &pe->imp_count, p);
+
+  found_dll:
+    i = dynarray_assoc((void **) p->symbols, p->sym_count, sym_index);
+    if (-1 != i)
+	goto found_sym;
+    s = tcc_mallocz(sizeof *s);
+    s->sym_index = sym_index;
+    s->offset = offset;
+    dynarray_add((void ***) &p->symbols, &p->sym_count, s);
+
+  found_sym:
+    return 1;
+}
+
+/*----------------------------------------------------------------------------*/
+ST void pe_build_imports(struct pe_info *pe)
+{
+    int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
+    DWORD voffset = pe->thunk->sh_addr - pe->imagebase;
+    int ndlls = pe->imp_count;
+
+    for (sym_cnt = i = 0; i < ndlls; ++i)
+	sym_cnt += pe->imp_info[i]->sym_count;
+
+    if (0 == sym_cnt)
+	return;
+
+    pe_align_section(pe->thunk, 16);
+
+    pe->imp_offs = dll_ptr = pe->thunk->data_offset;
+    pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header);
+    pe->iat_offs = dll_ptr + pe->imp_size;
+    pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD);
+    section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size);
+
+    thk_ptr = pe->iat_offs;
+    ent_ptr = pe->iat_offs + pe->iat_size;
+    for (i = 0; i < pe->imp_count; ++i) {
+	struct pe_import_header *hdr;
+	int k, n, v;
+	struct pe_import_info *p = pe->imp_info[i];
+	const char *name = pe->s1->loaded_dlls[p->dll_index]->name;
+
+	/* put the dll name into the import header */
+	if (0 == strncmp(name, "lib", 3))
+	    name += 3;
+	v = put_elf_str(pe->thunk, name);
+
+	hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr);
+	hdr->first_thunk = thk_ptr + voffset;
+	hdr->first_entry = ent_ptr + voffset;
+	hdr->lib_name_offset = v + voffset;
+
+	for (k = 0, n = p->sym_count; k <= n; ++k) {
+	    if (k < n) {
+		DWORD offset = p->symbols[k]->offset;
+		int sym_index = p->symbols[k]->sym_index;
+		Elf32_Sym *sym =
+		    (Elf32_Sym *) pe->s1->dynsymtab_section->data +
+		    sym_index;
+		const char *name =
+		    pe->s1->dynsymtab_section->link->data + sym->st_name;
+
+		if (offset & 0x80000000) {	/* ref to data */
+		    Elf32_Sym *sym =
+			&((Elf32_Sym *) symtab_section->
+			  data)[offset & 0x7FFFFFFF];
+		    sym->st_value = thk_ptr;
+		    sym->st_shndx = pe->thunk->sh_num;
+		} else {	/* ref to function */
+
+		    char buffer[100];
+		    sprintf(buffer, "IAT.%s", name);
+		    sym_index =
+			put_elf_sym(symtab_section, thk_ptr, sizeof(DWORD),
+				    ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
+				    0, pe->thunk->sh_num, buffer);
+
+		    put_elf_reloc(symtab_section, text_section, offset, R_386_32,	/*R_JMP_SLOT, */
+				  sym_index);
+		}
+		v = pe->thunk->data_offset + voffset;
+		section_ptr_add(pe->thunk, sizeof(WORD));	/* hint, not used */
+		put_elf_str(pe->thunk, name);
+	    } else {
+		v = 0;		// last entry is zero
+	    }
+	    *(DWORD *) (pe->thunk->data + thk_ptr) =
+		*(DWORD *) (pe->thunk->data + ent_ptr) = v;
+	    thk_ptr += sizeof(DWORD);
+	    ent_ptr += sizeof(DWORD);
+	}
+	dll_ptr += sizeof(struct pe_import_header);
+	dynarray_reset((void ***) &p->symbols, &p->sym_count);
+    }
+    dynarray_reset((void ***) &pe->imp_info, &pe->imp_count);
+}
+
+/* ------------------------------------------------------------- */
+ST int sym_cmp(const void *va, const void *vb)
+{
+    Elf32_Sym *sa = (Elf32_Sym *)symtab_section->data + *(int*)va;
+    Elf32_Sym *sb = (Elf32_Sym *)symtab_section->data + *(int*)vb;
+    const char *ca = symtab_section->link->data + sa->st_name;
+    const char *cb = symtab_section->link->data + sb->st_name;
+    return strcmp(ca, cb);
+}
+
+ST void pe_build_exports(struct pe_info *pe)
+{
+    Elf32_Sym *sym;
+    DWORD func_offset, voffset;
+    struct pe_export_header *hdr;
+    int sym_count, n, ord, *sorted;
+
+    voffset = pe->thunk->sh_addr - pe->imagebase;
+    sym_count = 0, n = 1, sorted = NULL;
+
+    // for simplicity only functions are exported
+    for_sym_in_symtab(sym)
+    {
+        if ((sym->st_other & 1)
+            && sym->st_shndx == text_section->sh_num)
+            dynarray_add((void***)&sorted, &sym_count, (void*)n);
+        ++n;
+    }
+
+    if (0 == sym_count)
+	return;
+
+    qsort (sorted, sym_count, sizeof sorted[0], sym_cmp);
+    pe_align_section(pe->thunk, 16);
+
+    pe->exp_offs = pe->thunk->data_offset;
+    hdr = section_ptr_add(pe->thunk,
+			  sizeof(struct pe_export_header) +
+			  sym_count * (2 * sizeof(DWORD) + sizeof(WORD)));
+
+    func_offset = pe->exp_offs + sizeof(struct pe_export_header);
+
+    hdr->Characteristics = 0;
+    hdr->Base = 1;
+    hdr->NumberOfFunctions = sym_count;
+    hdr->NumberOfNames = sym_count;
+    hdr->AddressOfFunctions = func_offset + voffset;
+    hdr->AddressOfNames         = hdr->AddressOfFunctions + sym_count * sizeof(DWORD);
+    hdr->AddressOfNameOrdinals  = hdr->AddressOfNames + sym_count * sizeof(DWORD);
+    hdr->Name = pe->thunk->data_offset + voffset;
+    put_elf_str(pe->thunk, tcc_basename(pe->filename));
+
+    for (ord = 0; ord < sym_count; ++ord)
+    {
+        char *name; DWORD *p, *pfunc, *pname; WORD *pord;
+        sym = (Elf32_Sym *)symtab_section->data + sorted[ord];
+        name = symtab_section->link->data + sym->st_name;
+        p = (DWORD*)(pe->thunk->data + func_offset);
+        pfunc = p + ord;
+        pname = p + sym_count + ord;
+        pord = (WORD *)(p + 2*sym_count) + ord;
+        *pfunc = sym->st_value + pe->s1->sections[sym->st_shndx]->sh_addr - pe->imagebase;
+	*pname = pe->thunk->data_offset + voffset;
+        *pord  = ord;
+	put_elf_str(pe->thunk, name);
+	/* printf("export: %s\n", name); */
+    }
+    pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
+    tcc_free(sorted);
+}
+
+/* ------------------------------------------------------------- */
+ST void pe_build_reloc(struct pe_info *pe, int *section_order,
+		       int section_count)
+{
+    DWORD offset, block_ptr, addr;
+    int count, i;
+    Elf32_Rel *rel, *rel_end;
+    Section *s = NULL, *sr;
+    offset = addr = block_ptr = count = i = 0;
+    rel = rel_end = NULL;
+    for (;;) {
+	if (rel < rel_end) {
+	    int type = ELF32_R_TYPE(rel->r_info);
+	    addr = rel->r_offset + s->sh_addr;
+	    ++rel;
+	    if (type != R_386_32)
+		continue;
+	    if (count == 0) {	/* new block */
+		block_ptr = pe->reloc->data_offset;
+		section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
+		offset = addr & 0xFFFFFFFF << 12;
+	    }
+	    if ((addr -= offset) < (1 << 12)) {	/* one block spans 4k addresses */
+		WORD *wp = section_ptr_add(pe->reloc, sizeof(WORD));
+		*wp = addr | IMAGE_REL_BASED_HIGHLOW << 12;
+		++count;
+		continue;
+	    }
+	    --rel;
+	} else if (i < section_count) {
+	    sr = (s = pe->s1->sections[section_order[i++]])->reloc;
+	    if (sr) {
+		rel = (Elf32_Rel *) sr->data;
+		rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
+	    }
+	    continue;
+	}
+
+	if (count) {		/* store the last block and ready for a new one */
+	    struct pe_reloc_header *hdr;
+	    if (count & 1)
+		section_ptr_add(pe->reloc, 2), ++count;
+	    hdr = (struct pe_reloc_header *) (pe->reloc->data + block_ptr);
+	    hdr->offset = offset - pe->imagebase;
+	    hdr->size =
+		count * sizeof(WORD) + sizeof(struct pe_reloc_header);
+	    count = 0;
+	}
+	if (rel >= rel_end)
+	    break;
+    }
+}
+
+/* ------------------------------------------------------------- */
+ST int pe_assign_addresses(struct pe_info *pe)
+{
+    int i, k, n;
+    DWORD addr;
+    int section_order[pe_sec_number];
+    struct section_info *si_data = NULL;
+
+    pe->imagebase = PE_DLL == pe_type ? 0x10000000 : 0x00400000;
+    addr = pe->imagebase + 1;
+
+    if (PE_DLL == pe_type)
+	pe->reloc = new_section(pe->s1, ".reloc", SHT_DYNAMIC, SHF_ALLOC);
+
+    for (n = k = 0; n < pe_sec_number; ++n) {
+	for (i = 1; i < pe->s1->nb_sections; ++i) {
+	    Section *s = pe->s1->sections[i];
+	    if (0 == strcmp(s->name, pe_sec_names[n])) {
+		struct section_info *si = &pe->sh_info[pe->sec_count];
+#ifdef PE_MERGE_DATA
+		if (n == sec_bss && si_data) {
+		    /* append .bss to .data */
+		    s->sh_addr = addr = ((addr - 1) | 15) + 1;
+		    addr += s->data_offset;
+		    si_data->sh_size = addr - si_data->sh_addr;
+		} else
+#endif
+		{
+		    si->sh_addr = s->sh_addr = addr =
+			pe_virtual_align(addr);
+		    si->id = n;
+
+		    if (n == sec_data) {
+			pe->thunk = s;
+			si_data = si;
+			pe_build_imports(pe);
+			pe_build_exports(pe);
+		    } else if (n == sec_reloc) {
+			pe_build_reloc(pe, section_order, k);
+		    }
+
+		    if (s->data_offset) {
+			if (n != sec_bss) {
+			    si->data = s->data;
+			    si->data_size = s->data_offset;
+			}
+
+			addr += s->data_offset;
+			si->sh_size = s->data_offset;
+			++pe->sec_count;
+		    }
+		    //printf("Section %08X %04X %s\n", si->sh_addr, si->data_size, s->name);
+		}
+		section_order[k] = i, ++k;
+	    }
+	}
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+ST int pe_check_symbols(struct pe_info *pe)
+{
+    Elf32_Sym *sym;
+    int ret = 0;
+
+    pe_align_section(text_section, 8);
+
+    for_sym_in_symtab(sym) {
+	if (sym->st_shndx == SHN_UNDEF) {
+	    const char *symbol = symtab_section->link->data + sym->st_name;
+	    unsigned type = ELF32_ST_TYPE(sym->st_info);
+	    int sym_index = pe_find_import(pe->s1, symbol, NULL);
+	    if (sym_index) {
+		if (type == STT_FUNC) {
+		    unsigned long offset = text_section->data_offset;
+		    if (pe_add_import(pe, sym_index, offset + 2)) {
+			/* add the 'jmp IAT[x]' instruction */
+			*(WORD *) section_ptr_add(text_section, 8) =
+			    0x25FF;
+			/* patch the symbol */
+			sym->st_shndx = text_section->sh_num;
+			sym->st_value = offset;
+			continue;
+		    }
+		} else if (type == STT_OBJECT) {	/* data, ptr to that should be */
+		    if (pe_add_import(pe, sym_index,
+				      (sym -
+				      (Elf32_Sym *) symtab_section->data) | 
+                                      0x80000000))
+			continue;
+		}
+	    }
+	    error_noabort("undefined symbol '%s'", symbol);
+	    ret = 1;
+	} else
+	    if (pe->s1->rdynamic
+		&& ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
+	    /* if -rdynamic option, then export all non local symbols */
+	    sym->st_other |= 1;
+	}
+    }
+    return ret;
+}
+
+/*----------------------------------------------------------------------------*/
+#ifdef PE_PRINT_SECTIONS
+ST void pe_print_section(FILE * f, Section * s)
+{				/* just if you'r curious */
+    BYTE *p, *e, b;
+    int i, n, l, m;
+    p = s->data;
+    e = s->data + s->data_offset;
+    l = e - p;
+
+    fprintf(f, "section  \"%s\"", s->name);
+    if (s->link)
+	fprintf(f, "\nlink     \"%s\"", s->link->name);
+    if (s->reloc)
+	fprintf(f, "\nreloc    \"%s\"", s->reloc->name);
+    fprintf(f, "\nv_addr   %08X", s->sh_addr);
+    fprintf(f, "\ncontents %08X", l);
+    fprintf(f, "\n\n");
+
+    if (s->sh_type == SHT_NOBITS)
+	return;
+
+    if (s->sh_type == SHT_SYMTAB)
+	m = sizeof(Elf32_Sym);
+    if (s->sh_type == SHT_REL)
+	m = sizeof(Elf32_Rel);
+    else
+	m = 16;
+
+    for (i = 0; i < l;) {
+	fprintf(f, "%08X", i);
+	for (n = 0; n < m; ++n) {
+	    if (n + i < l)
+		fprintf(f, " %02X", p[i + n]);
+	    else
+		fprintf(f, "   ");
+	}
+
+	if (s->sh_type == SHT_SYMTAB) {
+	    Elf32_Sym *sym = (Elf32_Sym *) (p + i);
+	    const char *name = s->link->data + sym->st_name;
+	    fprintf(f,
+		    "  name:%04X"
+		    "  value:%04X"
+		    "  size:%04X"
+		    "  bind:%02X"
+		    "  type:%02X"
+		    "  other:%02X"
+		    "  shndx:%04X"
+		    "  \"%s\"",
+		    sym->st_name,
+		    sym->st_value,
+		    sym->st_size,
+		    ELF32_ST_BIND(sym->st_info),
+		    ELF32_ST_TYPE(sym->st_info),
+		    sym->st_other, sym->st_shndx, name);
+	} else if (s->sh_type == SHT_REL) {
+	    Elf32_Rel *rel = (Elf32_Rel *) (p + i);
+	    Elf32_Sym *sym =
+		(Elf32_Sym *) s->link->data + ELF32_R_SYM(rel->r_info);
+	    const char *name = s->link->link->data + sym->st_name;
+	    fprintf(f,
+		    "  offset:%04X"
+		    "  type:%02X"
+		    "  symbol:%04X"
+		    "  \"%s\"",
+		    rel->r_offset,
+		    ELF32_R_TYPE(rel->r_info),
+		    ELF32_R_SYM(rel->r_info), name);
+	} else {
+	    fprintf(f, "   ");
+	    for (n = 0; n < m; ++n) {
+		if (n + i < l) {
+		    b = p[i + n];
+		    if (b < 32 || b >= 127)
+			b = '.';
+		    fprintf(f, "%c", b);
+		}
+	    }
+	}
+	i += m;
+	fprintf(f, "\n");
+    }
+    fprintf(f, "\n\n");
+}
+#endif
+
+static int pe_test_cmd(const char **pp, const char *cmd)
+{
+    const char *p;
+    char *q, buf[16];
+    int ret;
+
+    p = *pp;
+    q = buf;
+    while (*p != '\0' && !is_space(*p)) {
+        if ((q - buf) < sizeof(buf) - 1)
+            *q++ = toup(*p);
+        p++;
+    }
+    *q = '\0';
+    ret = !strcmp(buf, cmd);
+    *pp = p;
+    return ret;
+}
+
+/* ------------------------------------------------------------- */
+int pe_load_def_file(TCCState * s1, FILE * fp)
+{
+    DLLReference *dllref;
+    int f = 0, sym_index;
+    char *p, line[120], dllname[40];
+    while (fgets(line, sizeof line, fp)) {
+	p = strchr(line, 0);
+	while (p > line && p[-1] <= ' ')
+	    --p;
+	*p = 0;
+	p = line;
+	while (*p && *p <= ' ')
+	    ++p;
+
+	if (*p && ';' != *p)
+	    switch (f) {
+	    case 0:
+                if (!pe_test_cmd((const char **)&p, "LIBRARY"))
+		    return -1;
+                while (is_space(*p))
+                    p++;
+		pstrcpy(dllname, sizeof(dllname), p);
+		++f;
+		continue;
+
+	    case 1:
+                if (!pe_test_cmd((const char **)&p, "EXPORTS"))
+		    return -1;
+		++f;
+		continue;
+
+	    case 2:
+		dllref =
+		    tcc_malloc(sizeof(DLLReference) + strlen(dllname));
+		strcpy(dllref->name, dllname);
+		dllref->level = 0;
+		dynarray_add((void ***) &s1->loaded_dlls,
+			     &s1->nb_loaded_dlls, dllref);
+		++f;
+
+	    default:
+		/* tccpe needs to know from what dll it should import
+                   the sym */
+		sym_index = add_elf_sym(s1->dynsymtab_section,
+					0, 0, ELF32_ST_INFO(STB_GLOBAL,
+							    STT_FUNC),
+                                        s1->nb_loaded_dlls - 1,
+					text_section->sh_num, p);
+		continue;
+	    }
+    }
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+void pe_guess_outfile(char *objfilename, int output_type)
+{
+    char *ext = strrchr(objfilename, '.');
+    if (NULL == ext)
+        ext = strchr(objfilename, 0);
+    if (output_type == TCC_OUTPUT_DLL)
+        strcpy(ext, ".dll");
+    else
+    if (output_type == TCC_OUTPUT_EXE)
+        strcpy(ext, ".exe");
+    else
+    if (output_type == TCC_OUTPUT_OBJ && strcmp(ext, ".o"))
+        strcpy(ext, ".o");
+    else
+        error("no outputfile given");
+}
+
+/* ------------------------------------------------------------- */
+unsigned long pe_add_runtime(TCCState * s1)
+{
+    const char *start_symbol;
+    unsigned long addr;
+
+    if (find_elf_sym(symtab_section, "WinMain"))
+	pe_type = PE_GUI;
+    else
+    if (TCC_OUTPUT_DLL == s1->output_type)
+    {
+        pe_type = PE_DLL;
+        // need this for 'tccelf.c:relocate_section()'
+        s1->output_type = TCC_OUTPUT_EXE;
+    }
+
+    start_symbol =
+	TCC_OUTPUT_MEMORY == s1->output_type
+	? PE_GUI == pe_type ? "_runwinmain" : NULL
+	: PE_DLL == pe_type ? "_dllstart"
+	: PE_GUI == pe_type ? "_winstart" : "_start";
+
+    /* grab the startup code from libtcc1 */
+    if (start_symbol)
+	add_elf_sym(symtab_section,
+		    0, 0,
+		    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
+		    SHN_UNDEF, start_symbol);
+
+    if (0 == s1->nostdlib) {
+	tcc_add_library(s1, "tcc1");
+	tcc_add_library(s1, "msvcrt");
+	if (PE_DLL == pe_type || PE_GUI == pe_type) {
+	    tcc_add_library(s1, "kernel32");
+	    tcc_add_library(s1, "user32");
+	    tcc_add_library(s1, "gdi32");
+	}
+    }
+
+    addr = start_symbol ?
+	(unsigned long) tcc_get_symbol_err(s1, start_symbol) : 0;
+
+    if (s1->output_type == TCC_OUTPUT_MEMORY && addr) {
+	/* for -run GUI's, put '_runwinmain' instead of 'main' */
+	add_elf_sym(symtab_section,
+		    addr, 0,
+		    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
+		    text_section->sh_num, "main");
+
+	/* FreeConsole(); */
+    }
+    return addr;
+}
+
+int tcc_output_pe(TCCState * s1, const char *filename)
+{
+    int ret;
+    struct pe_info pe;
+    int i;
+    memset(&pe, 0, sizeof pe);
+    pe.filename = filename;
+    pe.s1 = s1;
+    pe.start_addr = pe_add_runtime(s1);
+
+    relocate_common_syms();	/* assign bss adresses */
+    ret = pe_check_symbols(&pe);
+    if (0 == ret) {
+	pe_assign_addresses(&pe);
+	relocate_syms(s1, 0);
+	for (i = 1; i < s1->nb_sections; ++i) {
+	    Section *s = s1->sections[i];
+	    if (s->reloc)
+		relocate_section(s1, s);
+	}
+	ret = pe_write_pe(&pe);
+    }
+#ifdef PE_PRINT_SECTIONS
+    {
+	Section *s;
+	FILE *f;
+        f = fopen("tccpe.log", "wt");
+	for (i = 1; i < s1->nb_sections; ++i) {
+	    s = s1->sections[i];
+	    pe_print_section(f, s);
+	}
+	pe_print_section(f, s1->dynsymtab_section);
+	fclose(f);
+    }
+#endif
+    return ret;
+}
+
+/*----------------------------------------------------------------------------*/