mirror of
https://github.com/golang/go
synced 2024-11-12 10:20:27 -07:00
cmd/link: support windows/arm
Enable the Go linker to generate executables for windows/arm. Generates PE relocation tables, which are used by Windows to dynamically relocate the Go binary in memory. Windows on ARM requires all modules to be relocatable, unlike x86/amd64 which are permitted to have fixed base addresses. Updates #26148 Change-Id: Ie63964ff52c2377e121b2885e9d05ec3ed8dc1cd Reviewed-on: https://go-review.googlesource.com/125648 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
39e59da76d
commit
aa311fecda
@ -190,6 +190,9 @@ func (f *peFile) goarch() string {
|
||||
if _, err := findPESymbol(f.pe, "_rt0_amd64_windows"); err == nil {
|
||||
return "amd64"
|
||||
}
|
||||
if _, err := findPESymbol(f.pe, "_rt0_arm_windows"); err == nil {
|
||||
return "arm"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -411,6 +411,35 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se
|
||||
return true
|
||||
}
|
||||
|
||||
func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
|
||||
rs := r.Xsym
|
||||
|
||||
if rs.Dynid < 0 {
|
||||
ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
|
||||
return false
|
||||
}
|
||||
|
||||
out.Write32(uint32(sectoff))
|
||||
out.Write32(uint32(rs.Dynid))
|
||||
|
||||
var v uint32
|
||||
switch r.Type {
|
||||
default:
|
||||
// unsupported relocation type
|
||||
return false
|
||||
|
||||
case objabi.R_DWARFSECREF:
|
||||
v = ld.IMAGE_REL_ARM_SECREL
|
||||
|
||||
case objabi.R_ADDR:
|
||||
v = ld.IMAGE_REL_ARM_ADDR32
|
||||
}
|
||||
|
||||
out.Write16(uint16(v))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// sign extend a 24-bit integer
|
||||
func signext24(x int64) int32 {
|
||||
return (int32(x) << 8) >> 8
|
||||
@ -799,6 +828,10 @@ func asmb(ctxt *ld.Link) {
|
||||
|
||||
case objabi.Hdarwin:
|
||||
symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
|
||||
|
||||
case objabi.Hwindows:
|
||||
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
|
||||
symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
|
||||
}
|
||||
|
||||
ctxt.Out.SeekSet(int64(symo))
|
||||
@ -828,6 +861,11 @@ func asmb(ctxt *ld.Link) {
|
||||
ctxt.Out.Flush()
|
||||
}
|
||||
|
||||
case objabi.Hwindows:
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
|
||||
}
|
||||
|
||||
case objabi.Hdarwin:
|
||||
if ctxt.LinkMode == ld.LinkExternal {
|
||||
ld.Machoemitreloc(ctxt)
|
||||
@ -860,6 +898,9 @@ func asmb(ctxt *ld.Link) {
|
||||
|
||||
case objabi.Hdarwin:
|
||||
ld.Asmbmacho(ctxt)
|
||||
|
||||
case objabi.Hwindows:
|
||||
ld.Asmbpe(ctxt)
|
||||
}
|
||||
|
||||
ctxt.Out.Flush()
|
||||
|
@ -57,6 +57,7 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Elfsetupplt: elfsetupplt,
|
||||
Gentext: gentext,
|
||||
Machoreloc1: machoreloc1,
|
||||
PEreloc1: pereloc1,
|
||||
|
||||
Linuxdynld: "/lib/ld-linux.so.3", // 2 for OABI, 3 for EABI
|
||||
Freebsddynld: "/usr/libexec/ld-elf.so.1",
|
||||
@ -130,6 +131,10 @@ func archinit(ctxt *ld.Link) {
|
||||
if *ld.FlagRound == -1 {
|
||||
*ld.FlagRound = 4096
|
||||
}
|
||||
|
||||
case objabi.Hwindows: /* PE executable */
|
||||
// ld.HEADR, ld.FlagTextAddr, ld.FlagDataAddr and ld.FlagRound are set in ld.Peinit
|
||||
return
|
||||
}
|
||||
|
||||
if *ld.FlagDataAddr != 0 && *ld.FlagRound != 0 {
|
||||
|
@ -60,7 +60,7 @@ func (mode *BuildMode) Set(s string) error {
|
||||
}
|
||||
case "windows":
|
||||
switch objabi.GOARCH {
|
||||
case "amd64", "386":
|
||||
case "amd64", "386", "arm":
|
||||
default:
|
||||
return badmode()
|
||||
}
|
||||
|
@ -539,13 +539,17 @@ func windynrelocsym(ctxt *Link, s *sym.Symbol) {
|
||||
r.Add = int64(targ.Plt)
|
||||
|
||||
// jmp *addr
|
||||
if ctxt.Arch.Family == sys.I386 {
|
||||
switch ctxt.Arch.Family {
|
||||
default:
|
||||
Errorf(s, "unsupported arch %v", ctxt.Arch.Family)
|
||||
return
|
||||
case sys.I386:
|
||||
rel.AddUint8(0xff)
|
||||
rel.AddUint8(0x25)
|
||||
rel.AddAddr(ctxt.Arch, targ)
|
||||
rel.AddUint8(0x90)
|
||||
rel.AddUint8(0x90)
|
||||
} else {
|
||||
case sys.AMD64:
|
||||
rel.AddUint8(0xff)
|
||||
rel.AddUint8(0x24)
|
||||
rel.AddUint8(0x25)
|
||||
|
@ -54,41 +54,45 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
IMAGE_FILE_MACHINE_I386 = 0x14c
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||
IMAGE_FILE_RELOCS_STRIPPED = 0x0001
|
||||
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002
|
||||
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004
|
||||
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
|
||||
IMAGE_SCN_MEM_DISCARDABLE = 0x2000000
|
||||
IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000
|
||||
IMAGE_SCN_ALIGN_32BYTES = 0x600000
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT = 0
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT = 1
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2
|
||||
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3
|
||||
IMAGE_DIRECTORY_ENTRY_SECURITY = 4
|
||||
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5
|
||||
IMAGE_DIRECTORY_ENTRY_DEBUG = 6
|
||||
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7
|
||||
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7
|
||||
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8
|
||||
IMAGE_DIRECTORY_ENTRY_TLS = 9
|
||||
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
|
||||
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11
|
||||
IMAGE_DIRECTORY_ENTRY_IAT = 12
|
||||
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
|
||||
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
|
||||
IMAGE_FILE_MACHINE_I386 = 0x14c
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||
IMAGE_FILE_MACHINE_ARM = 0x1c0
|
||||
IMAGE_FILE_MACHINE_ARMNT = 0x1c4
|
||||
IMAGE_FILE_RELOCS_STRIPPED = 0x0001
|
||||
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002
|
||||
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004
|
||||
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
|
||||
IMAGE_SCN_MEM_DISCARDABLE = 0x2000000
|
||||
IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000
|
||||
IMAGE_SCN_ALIGN_32BYTES = 0x600000
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT = 0
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT = 1
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2
|
||||
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3
|
||||
IMAGE_DIRECTORY_ENTRY_SECURITY = 4
|
||||
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5
|
||||
IMAGE_DIRECTORY_ENTRY_DEBUG = 6
|
||||
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7
|
||||
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7
|
||||
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8
|
||||
IMAGE_DIRECTORY_ENTRY_TLS = 9
|
||||
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
|
||||
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11
|
||||
IMAGE_DIRECTORY_ENTRY_IAT = 12
|
||||
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
|
||||
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
|
||||
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040
|
||||
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100
|
||||
)
|
||||
|
||||
// TODO(crawshaw): add these constants to debug/pe.
|
||||
@ -109,6 +113,15 @@ const (
|
||||
IMAGE_REL_AMD64_ADDR32 = 0x0002
|
||||
IMAGE_REL_AMD64_REL32 = 0x0004
|
||||
IMAGE_REL_AMD64_SECREL = 0x000B
|
||||
|
||||
IMAGE_REL_ARM_ABSOLUTE = 0x0000
|
||||
IMAGE_REL_ARM_ADDR32 = 0x0001
|
||||
IMAGE_REL_ARM_ADDR32NB = 0x0002
|
||||
IMAGE_REL_ARM_BRANCH24 = 0x0003
|
||||
IMAGE_REL_ARM_BRANCH11 = 0x0004
|
||||
IMAGE_REL_ARM_SECREL = 0x000F
|
||||
|
||||
IMAGE_REL_BASED_HIGHLOW = 3
|
||||
)
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
@ -477,6 +490,8 @@ func (f *peFile) addInitArray(ctxt *Link) *peSection {
|
||||
size = 4
|
||||
case "amd64":
|
||||
size = 8
|
||||
case "arm":
|
||||
size = 4
|
||||
}
|
||||
sect := f.addSection(".ctors", size, size)
|
||||
sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
|
||||
@ -487,7 +502,7 @@ func (f *peFile) addInitArray(ctxt *Link) *peSection {
|
||||
init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0)
|
||||
addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr
|
||||
switch objabi.GOARCH {
|
||||
case "386":
|
||||
case "386", "arm":
|
||||
ctxt.Out.Write32(uint32(addr))
|
||||
case "amd64":
|
||||
ctxt.Out.Write64(addr)
|
||||
@ -592,6 +607,8 @@ dwarfLoop:
|
||||
ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
|
||||
case "amd64":
|
||||
ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64)
|
||||
case "arm":
|
||||
ctxt.Out.Write16(IMAGE_REL_ARM_ADDR32)
|
||||
}
|
||||
return 1
|
||||
})
|
||||
@ -743,6 +760,8 @@ func (f *peFile) writeFileHeader(arch *sys.Arch, out *OutBuf, linkmode LinkMode)
|
||||
fh.Machine = IMAGE_FILE_MACHINE_AMD64
|
||||
case sys.I386:
|
||||
fh.Machine = IMAGE_FILE_MACHINE_I386
|
||||
case sys.ARM:
|
||||
fh.Machine = IMAGE_FILE_MACHINE_ARMNT
|
||||
}
|
||||
|
||||
fh.NumberOfSections = uint16(len(f.sections))
|
||||
@ -754,7 +773,14 @@ func (f *peFile) writeFileHeader(arch *sys.Arch, out *OutBuf, linkmode LinkMode)
|
||||
if linkmode == LinkExternal {
|
||||
fh.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||
} else {
|
||||
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED
|
||||
switch arch.Family {
|
||||
default:
|
||||
Exitf("write COFF(ext): unknown PE architecture: %v", arch.Family)
|
||||
case sys.AMD64, sys.I386:
|
||||
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED
|
||||
case sys.ARM:
|
||||
fh.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED
|
||||
}
|
||||
}
|
||||
if pe64 != 0 {
|
||||
var oh64 pe.OptionalHeader64
|
||||
@ -831,6 +857,12 @@ func (f *peFile) writeOptionalHeader(ctxt *Link) {
|
||||
oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
}
|
||||
|
||||
switch ctxt.Arch.Family {
|
||||
case sys.ARM:
|
||||
oh64.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
oh.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
}
|
||||
|
||||
// Disable stack growth as we don't want Windows to
|
||||
// fiddle with the thread stack limits, which we set
|
||||
// ourselves to circumvent the stack checks in the
|
||||
@ -1271,6 +1303,162 @@ func addexports(ctxt *Link) {
|
||||
sect.pad(out, uint32(size))
|
||||
}
|
||||
|
||||
// peBaseRelocEntry represents a single relocation entry.
|
||||
type peBaseRelocEntry struct {
|
||||
typeOff uint16
|
||||
rel *sym.Reloc
|
||||
sym *sym.Symbol // For debug
|
||||
}
|
||||
|
||||
// peBaseRelocBlock represents a Base Relocation Block. A block
|
||||
// is a collection of relocation entries in a page, where each
|
||||
// entry describes a single relocation.
|
||||
// The block page RVA (Relative Virtual Address) is the index
|
||||
// into peBaseRelocTable.blocks.
|
||||
type peBaseRelocBlock struct {
|
||||
entries []peBaseRelocEntry
|
||||
}
|
||||
|
||||
// pePages is a type used to store the list of pages for which there
|
||||
// are base relocation blocks. This is defined as a type so that
|
||||
// it can be sorted.
|
||||
type pePages []uint32
|
||||
|
||||
func (p pePages) Len() int { return len(p) }
|
||||
func (p pePages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
func (p pePages) Less(i, j int) bool { return p[i] < p[j] }
|
||||
|
||||
// A PE base relocation table is a list of blocks, where each block
|
||||
// contains relocation information for a single page. The blocks
|
||||
// must be emitted in order of page virtual address.
|
||||
// See https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-reloc-section-image-only
|
||||
type peBaseRelocTable struct {
|
||||
blocks map[uint32]peBaseRelocBlock
|
||||
|
||||
// pePages is a list of keys into blocks map.
|
||||
// It is stored separately for ease of sorting.
|
||||
pages pePages
|
||||
}
|
||||
|
||||
func (rt *peBaseRelocTable) init(ctxt *Link) {
|
||||
rt.blocks = make(map[uint32]peBaseRelocBlock)
|
||||
}
|
||||
|
||||
func (rt *peBaseRelocTable) addentry(ctxt *Link, s *sym.Symbol, r *sym.Reloc) {
|
||||
// pageSize is the size in bytes of a page
|
||||
// described by a base relocation block.
|
||||
const pageSize = 0x1000
|
||||
const pageMask = pageSize - 1
|
||||
|
||||
addr := s.Value + int64(r.Off) - int64(PEBASE)
|
||||
page := uint32(addr &^ pageMask)
|
||||
off := uint32(addr & pageMask)
|
||||
|
||||
b, ok := rt.blocks[page]
|
||||
if !ok {
|
||||
rt.pages = append(rt.pages, page)
|
||||
}
|
||||
|
||||
e := peBaseRelocEntry{
|
||||
typeOff: uint16(off & 0xFFF),
|
||||
rel: r,
|
||||
sym: s,
|
||||
}
|
||||
|
||||
// Set entry type
|
||||
switch r.Siz {
|
||||
default:
|
||||
Exitf("unsupported relocation size %d\n", r.Siz)
|
||||
case 4:
|
||||
e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
|
||||
}
|
||||
|
||||
b.entries = append(b.entries, e)
|
||||
rt.blocks[page] = b
|
||||
}
|
||||
|
||||
func (rt *peBaseRelocTable) write(ctxt *Link) {
|
||||
out := ctxt.Out
|
||||
|
||||
// sort the pages array
|
||||
sort.Sort(rt.pages)
|
||||
|
||||
for _, p := range rt.pages {
|
||||
b := rt.blocks[p]
|
||||
const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
|
||||
blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
|
||||
out.Write32(p)
|
||||
out.Write32(blockSize)
|
||||
|
||||
for _, e := range b.entries {
|
||||
out.Write16(e.typeOff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addPEBaseRelocSym(ctxt *Link, s *sym.Symbol, rt *peBaseRelocTable) {
|
||||
for ri := 0; ri < len(s.R); ri++ {
|
||||
r := &s.R[ri]
|
||||
|
||||
if r.Sym == nil {
|
||||
continue
|
||||
}
|
||||
if !r.Sym.Attr.Reachable() {
|
||||
continue
|
||||
}
|
||||
if r.Type >= 256 {
|
||||
continue
|
||||
}
|
||||
if r.Siz == 0 { // informational relocation
|
||||
continue
|
||||
}
|
||||
if r.Type == objabi.R_DWARFFILEREF {
|
||||
continue
|
||||
}
|
||||
|
||||
switch r.Type {
|
||||
default:
|
||||
case objabi.R_ADDR:
|
||||
rt.addentry(ctxt, s, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addPEBaseReloc(ctxt *Link) {
|
||||
// We only generate base relocation table for ARM (and ... ARM64), x86, and AMD64 are marked as legacy
|
||||
// archs and can use fixed base with no base relocation information
|
||||
switch ctxt.Arch.Family {
|
||||
default:
|
||||
return
|
||||
case sys.ARM:
|
||||
}
|
||||
|
||||
var rt peBaseRelocTable
|
||||
rt.init(ctxt)
|
||||
|
||||
// Get relocation information
|
||||
for _, s := range ctxt.Textp {
|
||||
addPEBaseRelocSym(ctxt, s, &rt)
|
||||
}
|
||||
for _, s := range datap {
|
||||
addPEBaseRelocSym(ctxt, s, &rt)
|
||||
}
|
||||
|
||||
// Write relocation information
|
||||
startoff := ctxt.Out.Offset()
|
||||
rt.write(ctxt)
|
||||
size := ctxt.Out.Offset() - startoff
|
||||
|
||||
// Add a PE section and pad it at the end
|
||||
rsect := pefile.addSection(".reloc", int(size), int(size))
|
||||
rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
|
||||
rsect.checkOffset(startoff)
|
||||
rsect.pad(ctxt.Out, uint32(size))
|
||||
|
||||
pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
|
||||
pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
|
||||
}
|
||||
|
||||
func (ctxt *Link) dope() {
|
||||
/* relocation table */
|
||||
rel := ctxt.Syms.Lookup(".rel", 0)
|
||||
@ -1326,7 +1514,7 @@ func Asmbpe(ctxt *Link) {
|
||||
switch ctxt.Arch.Family {
|
||||
default:
|
||||
Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
|
||||
case sys.AMD64, sys.I386:
|
||||
case sys.AMD64, sys.I386, sys.ARM:
|
||||
}
|
||||
|
||||
t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
|
||||
@ -1380,6 +1568,7 @@ func Asmbpe(ctxt *Link) {
|
||||
if ctxt.LinkMode != LinkExternal {
|
||||
addimports(ctxt, d)
|
||||
addexports(ctxt)
|
||||
addPEBaseReloc(ctxt)
|
||||
}
|
||||
pefile.writeSymbolTableAndStringTable(ctxt)
|
||||
addpersrc(ctxt)
|
||||
|
@ -101,6 +101,19 @@ const (
|
||||
IMAGE_REL_AMD64_SREL32 = 0x000E
|
||||
IMAGE_REL_AMD64_PAIR = 0x000F
|
||||
IMAGE_REL_AMD64_SSPAN32 = 0x0010
|
||||
IMAGE_REL_ARM_ABSOLUTE = 0x0000
|
||||
IMAGE_REL_ARM_ADDR32 = 0x0001
|
||||
IMAGE_REL_ARM_ADDR32NB = 0x0002
|
||||
IMAGE_REL_ARM_BRANCH24 = 0x0003
|
||||
IMAGE_REL_ARM_BRANCH11 = 0x0004
|
||||
IMAGE_REL_ARM_SECTION = 0x000E
|
||||
IMAGE_REL_ARM_SECREL = 0x000F
|
||||
IMAGE_REL_ARM_MOV32 = 0x0010
|
||||
IMAGE_REL_THUMB_MOV32 = 0x0011
|
||||
IMAGE_REL_THUMB_BRANCH20 = 0x0012
|
||||
IMAGE_REL_THUMB_BRANCH24 = 0x0014
|
||||
IMAGE_REL_THUMB_BLX23 = 0x0015
|
||||
IMAGE_REL_ARM_PAIR = 0x0016
|
||||
)
|
||||
|
||||
// TODO(crawshaw): de-duplicate these symbols with cmd/internal/ld, ideally in debug/pe.
|
||||
@ -241,30 +254,56 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
|
||||
rp.Sym = gosym
|
||||
rp.Siz = 4
|
||||
rp.Off = int32(r.VirtualAddress)
|
||||
switch r.Type {
|
||||
switch arch.Family {
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type)
|
||||
return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
|
||||
case sys.I386, sys.AMD64:
|
||||
switch r.Type {
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type)
|
||||
|
||||
case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32,
|
||||
IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32
|
||||
IMAGE_REL_AMD64_ADDR32NB:
|
||||
rp.Type = objabi.R_PCREL
|
||||
case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32,
|
||||
IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32
|
||||
IMAGE_REL_AMD64_ADDR32NB:
|
||||
rp.Type = objabi.R_PCREL
|
||||
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
|
||||
case IMAGE_REL_I386_DIR32NB, IMAGE_REL_I386_DIR32:
|
||||
rp.Type = objabi.R_ADDR
|
||||
case IMAGE_REL_I386_DIR32NB, IMAGE_REL_I386_DIR32:
|
||||
rp.Type = objabi.R_ADDR
|
||||
|
||||
// load addend from image
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
// load addend from image
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
|
||||
case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
|
||||
rp.Siz = 8
|
||||
case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
|
||||
rp.Siz = 8
|
||||
|
||||
rp.Type = objabi.R_ADDR
|
||||
rp.Type = objabi.R_ADDR
|
||||
|
||||
// load addend from image
|
||||
rp.Add = int64(binary.LittleEndian.Uint64(sectdata[rsect][rp.Off:]))
|
||||
// load addend from image
|
||||
rp.Add = int64(binary.LittleEndian.Uint64(sectdata[rsect][rp.Off:]))
|
||||
}
|
||||
|
||||
case sys.ARM:
|
||||
switch r.Type {
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type)
|
||||
|
||||
case IMAGE_REL_ARM_SECREL:
|
||||
rp.Type = objabi.R_PCREL
|
||||
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
|
||||
case IMAGE_REL_ARM_ADDR32:
|
||||
rp.Type = objabi.R_ADDR
|
||||
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
|
||||
case IMAGE_REL_ARM_BRANCH24:
|
||||
rp.Type = objabi.R_CALLARM
|
||||
|
||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||
}
|
||||
}
|
||||
|
||||
// ld -r could generate multiple section symbols for the
|
||||
|
Loading…
Reference in New Issue
Block a user