From: Jordan Rhee Date: Tue, 24 Jul 2018 22:13:41 +0000 (-0700) Subject: cmd/link: support windows/arm X-Git-Tag: go1.12beta1~1359 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=aa311fecda008d26f97af0a8e7f57dcd04cae6ae;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index 80db6f0f18..259b59a4f4 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -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 "" } diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 5e4ddea88e..b1d44b5896 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -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() diff --git a/src/cmd/link/internal/arm/obj.go b/src/cmd/link/internal/arm/obj.go index 788be68522..77716bb954 100644 --- a/src/cmd/link/internal/arm/obj.go +++ b/src/cmd/link/internal/arm/obj.go @@ -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 { diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 18fbea62ee..77b03b67f9 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -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() } diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 5dd4aac03e..730e9a0bf7 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index c81e3d6af5..0e60ef76d2 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -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) diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go index c8fae37898..f78252c283 100644 --- a/src/cmd/link/internal/loadpe/ldpe.go +++ b/src/cmd/link/internal/loadpe/ldpe.go @@ -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