obj.$O\
optab.$O\
pass.$O\
+ pe.$O\
span.$O\
go.$O\
../8l/8.out.h\
../ld/elf.h\
../ld/macho.h\
+ ../ld/pe.h\
$(TARG): $(OFILES)
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/macho.h"
+#include "../ld/pe.h"
#define Dbufslop 100
case 7:
case 8:
case 9:
+ case 10:
v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0);
break;
case 7:
case 8:
case 9:
+ case 10:
symo = rnd(HEADR+textsize, INITRND)+datsize;
symo = rnd(symo, INITRND);
break;
asmlc();
if(dlm)
asmdyn();
+ if(HEADTYPE == 10)
+ strnput("", INITRND-(8+symsize+lcsize)%INITRND);
cflush();
seek(cout, symo, 0);
lputl(symsize);
if(a+elfwriteinterp() > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
+
+ case 10:
+ asmbpe();
+ break;
}
cflush();
}
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/macho.h"
+#include "../ld/pe.h"
#include <ar.h>
#ifndef DEFAULT
listinit();
memset(debug, 0, sizeof(debug));
nerrors = 0;
- outfile = "8.out";
+ outfile = nil;
HEADTYPE = -1;
INITTEXT = -1;
INITDAT = -1;
if(*argv == 0)
usage();
- libinit();
+ mywhatsys(); // get goos
if(HEADTYPE == -1) {
HEADTYPE = 2;
if(strcmp(goos, "freebsd") == 0)
HEADTYPE = 9;
else
- print("goos is not known: %sn", goos);
+ if(strcmp(goos, "mingw") == 0)
+ HEADTYPE = 10;
+ else
+ print("goos is not known: %s\n", goos);
+ }
+
+ if(outfile == nil) {
+ if(HEADTYPE == 10)
+ outfile = "8.out.exe";
+ else
+ outfile = "8.out";
}
+ libinit();
+
switch(HEADTYPE) {
default:
diag("unknown -H option");
if(INITRND == -1)
INITRND = 4096;
break;
+ case 10: /* PE executable */
+ peinit();
+ HEADR = PERESERVE;
+ if(INITTEXT == -1)
+ INITTEXT = PEBASE+0x1000;
+ if(INITDAT == -1)
+ INITDAT = 0;
+ if(INITRND == -1)
+ INITRND = PEALIGN;
+ break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%lux is ignored because of -R0x%lux\n",
doprof2();
span();
doinit();
+ if(HEADTYPE == 10)
+ dope();
asmb();
undef();
if(debug['v']) {
s = lookup("exit", 0);
vexit = s->value;
for(p = firstp; p != P; p = p->link) {
+ if(HEADTYPE == 10) {
+ // Convert
+ // op n(GS), reg
+ // to
+ // MOVL 0x2C(FS), reg
+ // op n(reg), reg
+ // The purpose of this patch is to fix some accesses
+ // to extern register variables (TLS) on Windows, as
+ // a different method is used to access them.
+ if(p->from.type == D_INDIR+D_GS
+ && p->to.type >= D_AX && p->to.type <= D_DI) {
+ q = appendp(p);
+ q->from = p->from;
+ q->from.type += p->to.type-D_GS;
+ q->to = p->to;
+ q->as = p->as;
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_FS;
+ p->from.offset = 0x2C;
+ }
+ }
if(p->as == ATEXT)
curtext = p;
if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
if(pmorestack != P)
if(!(p->from.scale & NOSPLIT)) {
p = appendp(p); // load g into CX
- p->as = AMOVL;
- p->from.type = D_INDIR+D_GS;
- p->from.offset = tlsoffset + 0;
- p->to.type = D_CX;
+ if(HEADTYPE == 10) {
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_FS;
+ p->from.offset = 0x2c;
+ p->to.type = D_CX;
+
+ p = appendp(p);
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_CX;
+ p->from.offset = 0;
+ p->to.type = D_CX;
+ } else {
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_GS;
+ p->from.offset = tlsoffset + 0;
+ p->to.type = D_CX;
+ }
if(debug['K']) {
// 8l -K means check not only for stack
int
systemtype(int sys)
{
-
+#ifdef __MINGW32__
+ return sys&Windows;
+#else
return sys&Plan9;
+#endif
}
int
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// PE (Portable Executable) file writing
+// http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
+
+#include <time.h>
+
+#include "l.h"
+#include "../ld/lib.h"
+#include "../ld/pe.h"
+
+static int pe64;
+static int nsect;
+static int sect_virt_begin;
+static int sect_raw_begin = PERESERVE;
+
+static IMAGE_FILE_HEADER fh;
+static IMAGE_OPTIONAL_HEADER oh;
+static IMAGE_SECTION_HEADER sh[16];
+static IMAGE_SECTION_HEADER *textsect, *datsect, *bsssect;
+
+static IMAGE_SECTION_HEADER*
+new_section(char *name, int size, int noraw)
+{
+ IMAGE_SECTION_HEADER *h;
+
+ if(nsect == 16) {
+ diag("too many sections");
+ errorexit();
+ }
+ h = &sh[nsect++];
+ strncpy(h->Name, name, sizeof(h->Name));
+ h->VirtualSize = size;
+ if(!sect_virt_begin)
+ sect_virt_begin = 0x1000;
+ h->VirtualAddress = sect_virt_begin;
+ sect_virt_begin = rnd(sect_virt_begin+size, 0x1000);
+ if(!noraw) {
+ h->SizeOfRawData = rnd(size, PEALIGN);
+ h->PointerToRawData = sect_raw_begin;
+ sect_raw_begin += h->SizeOfRawData;
+ }
+ return h;
+}
+
+void
+peinit(void)
+{
+ switch(thechar) {
+ // 64-bit architectures
+ case '6':
+ pe64 = 1;
+ break;
+ // 32-bit architectures
+ default:
+ break;
+ }
+}
+
+static void
+pewrite(void)
+{
+ int i, j;
+
+ strnput("MZ", 0x3c);
+ LPUT(0x40); // file offset to PE header
+ strnput("PE", 4);
+
+ for (i=0; i<sizeof(fh); i++)
+ cput(((char*)&fh)[i]);
+ for (i=0; i<sizeof(oh); i++)
+ cput(((char*)&oh)[i]);
+ for (i=0; i<nsect; i++)
+ for (j=0; j<sizeof(sh[i]); j++)
+ cput(((char*)&sh[i])[j]);
+}
+
+void
+dope(void)
+{
+ textsect = new_section(".text", textsize, 0);
+ textsect->Characteristics = IMAGE_SCN_CNT_CODE|
+ IMAGE_SCN_CNT_INITIALIZED_DATA|
+ IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
+
+ datsect = new_section(".data", datsize, 0);
+ datsect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
+ IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
+ INITDAT = PEBASE+datsect->VirtualAddress;
+
+ bsssect = new_section(".bss", bsssize, 1);
+ bsssect->Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA|
+ IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
+}
+
+void
+asmbpe(void)
+{
+ switch(thechar) {
+ default:
+ diag("unknown PE architecture");
+ errorexit();
+ case '6':
+ fh.Machine = IMAGE_FILE_MACHINE_AMD64;
+ break;
+ case '8':
+ fh.Machine = IMAGE_FILE_MACHINE_I386;
+ break;
+ }
+
+ if(!debug['s']) {
+ IMAGE_SECTION_HEADER *symsect;
+ symsect = new_section(".symdat", 8+symsize+lcsize, 0);
+ symsect->Characteristics = IMAGE_SCN_MEM_READ|
+ IMAGE_SCN_CNT_INITIALIZED_DATA;
+ }
+
+ fh.NumberOfSections = nsect;
+ fh.TimeDateStamp = time(0);
+ fh.SizeOfOptionalHeader = sizeof(oh);
+ fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
+ IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED;
+ if(thechar == '8')
+ fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE;
+
+ oh.Magic = 0x10b; // PE32
+ oh.MajorLinkerVersion = 1;
+ oh.MinorLinkerVersion = 0;
+ oh.SizeOfCode = textsect->SizeOfRawData;
+ oh.SizeOfInitializedData = datsect->SizeOfRawData;
+ oh.SizeOfUninitializedData = bsssect->SizeOfRawData;
+ oh.AddressOfEntryPoint = entryvalue()-PEBASE;
+ oh.BaseOfCode = textsect->VirtualAddress;
+ oh.BaseOfData = datsect->VirtualAddress;
+
+ oh.ImageBase = PEBASE;
+ oh.SectionAlignment = 0x00001000;
+ oh.FileAlignment = PEALIGN;
+ oh.MajorOperatingSystemVersion = 4;
+ oh.MinorOperatingSystemVersion = 0;
+ oh.MajorImageVersion = 1;
+ oh.MinorImageVersion = 0;
+ oh.MajorSubsystemVersion = 4;
+ oh.MinorSubsystemVersion = 0;
+ oh.SizeOfImage = sect_virt_begin;
+ oh.SizeOfHeaders = PERESERVE;
+ oh.Subsystem = 3; // WINDOWS_CUI
+ oh.SizeOfStackReserve = 0x00200000;
+ oh.SizeOfStackCommit = 0x00001000;
+ oh.SizeOfHeapReserve = 0x00100000;
+ oh.SizeOfHeapCommit = 0x00001000;
+ oh.NumberOfRvaAndSizes = 16;
+
+ pewrite();
+}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+typedef struct {
+ uint16 Machine;
+ uint16 NumberOfSections;
+ uint32 TimeDateStamp;
+ uint32 PointerToSymbolTable;
+ uint32 NumberOfSymbols;
+ uint16 SizeOfOptionalHeader;
+ uint16 Characteristics;
+} IMAGE_FILE_HEADER;
+
+typedef struct {
+ uint32 VirtualAddress;
+ uint32 Size;
+} IMAGE_DATA_DIRECTORY;
+
+typedef struct {
+ uint16 Magic;
+ uint8 MajorLinkerVersion;
+ uint8 MinorLinkerVersion;
+ uint32 SizeOfCode;
+ uint32 SizeOfInitializedData;
+ uint32 SizeOfUninitializedData;
+ uint32 AddressOfEntryPoint;
+ uint32 BaseOfCode;
+ uint32 BaseOfData;
+ uint32 ImageBase;
+ uint32 SectionAlignment;
+ uint32 FileAlignment;
+ uint16 MajorOperatingSystemVersion;
+ uint16 MinorOperatingSystemVersion;
+ uint16 MajorImageVersion;
+ uint16 MinorImageVersion;
+ uint16 MajorSubsystemVersion;
+ uint16 MinorSubsystemVersion;
+ uint32 Win32VersionValue;
+ uint32 SizeOfImage;
+ uint32 SizeOfHeaders;
+ uint32 CheckSum;
+ uint16 Subsystem;
+ uint16 DllCharacteristics;
+ uint32 SizeOfStackReserve;
+ uint32 SizeOfStackCommit;
+ uint32 SizeOfHeapReserve;
+ uint32 SizeOfHeapCommit;
+ uint32 LoaderFlags;
+ uint32 NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[16];
+} IMAGE_OPTIONAL_HEADER;
+
+typedef struct {
+ uint8 Name[8];
+ uint32 VirtualSize;
+ uint32 VirtualAddress;
+ uint32 SizeOfRawData;
+ uint32 PointerToRawData;
+ uint32 PointerToRelocations;
+ uint32 PointerToLineNumbers;
+ uint16 NumberOfRelocations;
+ uint16 NumberOfLineNumbers;
+ uint32 Characteristics;
+} IMAGE_SECTION_HEADER;
+
+#define PERESERVE 0x400
+#define PEALIGN 0x200
+#define PEBASE 0x00400000
+
+enum {
+ IMAGE_FILE_MACHINE_I386 = 0x14c,
+ IMAGE_FILE_MACHINE_AMD64 = 0x8664,
+
+ IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
+ IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
+ IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
+ IMAGE_FILE_32BIT_MACHINE = 0x0100,
+ IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
+
+ IMAGE_SCN_CNT_CODE = 0x00000020,
+ IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
+ IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
+ IMAGE_SCN_MEM_EXECUTE = 0x20000000,
+ IMAGE_SCN_MEM_READ = 0x40000000,
+ IMAGE_SCN_MEM_WRITE = 0x80000000,
+};
+
+void peinit(void);
+void dope(void);
+void asmbpe(void);