Skip to content

Commit

Permalink
cmd/link,cmd/internal/objabi: support ADDR32NB relocations on windows
Browse files Browse the repository at this point in the history
This CL updates the linker to support
IMAGE_REL_[I386|AMD64|ARM|ARM64]_ADDR32NB relocations via the new
R_PEIMAGEOFF relocation type. This relocation type references symbols
using RVAs instead of VA, so it can use 4-byte offsets to reference
symbols that would normally require 8-byte offsets.

This new relocation is still not used, but will be useful when
generating Structured Exception Handling (SEH) metadata, which
needs to reference functions only using 4-byte addresses, thus
using RVAs instead of VA is of great help.

Updates #57302

Change-Id: I28d73e97d5cb78a3bc7194dc7d2fcb4a03f9f4d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/461737
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Davis Goodin <dagood@microsoft.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
qmuntal committed Mar 29, 2023
1 parent 541ef42 commit f57f02f
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 12 deletions.
4 changes: 4 additions & 0 deletions src/cmd/internal/objabi/reloctype.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,10 @@ const (
// in a symbol and target any symbols.
R_XCOFFREF

// R_PEIMAGEOFF resolves to a 32-bit offset from the start address of where
// the executable file is mapped in memory.
R_PEIMAGEOFF

// R_WEAK marks the relocation as a weak reference.
// A weak relocation does not make the symbol it refers to reachable,
// and is only honored by the linker if the symbol is in some other way
Expand Down
5 changes: 3 additions & 2 deletions src/cmd/internal/objabi/reloctype_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/cmd/link/internal/amd64/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,9 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
v = ld.IMAGE_REL_AMD64_ADDR32
}

case objabi.R_PEIMAGEOFF:
v = ld.IMAGE_REL_AMD64_ADDR32NB

case objabi.R_CALL,
objabi.R_PCREL:
v = ld.IMAGE_REL_AMD64_REL32
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/link/internal/arm/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,

case objabi.R_ADDR:
v = ld.IMAGE_REL_ARM_ADDR32

case objabi.R_PEIMAGEOFF:
v = ld.IMAGE_REL_ARM_ADDR32NB
}

out.Write16(uint16(v))
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/link/internal/arm64/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,9 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
out.Write16(ld.IMAGE_REL_ARM64_ADDR32)
}

case objabi.R_PEIMAGEOFF:
out.Write16(ld.IMAGE_REL_ARM64_ADDR32NB)

case objabi.R_ADDRARM64:
// Note: r.Xadd has been taken care of below, in archreloc.
out.Write32(uint32(sectoff))
Expand Down
9 changes: 7 additions & 2 deletions src/cmd/link/internal/ld/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
} else {
log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
}
case objabi.R_ADDR:
case objabi.R_ADDR, objabi.R_PEIMAGEOFF:
if weak && !ldr.AttrReachable(rs) {
// Redirect it to runtime.unreachableMethod, which will throw if called.
rs = syms.unreachableMethod
Expand Down Expand Up @@ -398,6 +398,11 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
}

o = ldr.SymValue(rs) + r.Add()
if rt == objabi.R_PEIMAGEOFF {
// The R_PEIMAGEOFF offset is a RVA, so subtract
// the base address for the executable.
o -= PEBASE
}

// On amd64, 4-byte offsets will be sign-extended, so it is impossible to
// access more than 2GB of static data; fail at link time is better than
Expand Down Expand Up @@ -639,7 +644,7 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa
}
return rr, false

case objabi.R_ADDR:
case objabi.R_ADDR, objabi.R_PEIMAGEOFF:
// set up addend for eventual relocation via outer symbol.
rs := r.Sym()
if r.Weak() && !ldr.AttrReachable(rs) {
Expand Down
18 changes: 10 additions & 8 deletions src/cmd/link/internal/ld/pe.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,16 @@ const (
IMAGE_SYM_CLASS_EXTERNAL = 2
IMAGE_SYM_CLASS_STATIC = 3

IMAGE_REL_I386_DIR32 = 0x0006
IMAGE_REL_I386_SECREL = 0x000B
IMAGE_REL_I386_REL32 = 0x0014

IMAGE_REL_AMD64_ADDR64 = 0x0001
IMAGE_REL_AMD64_ADDR32 = 0x0002
IMAGE_REL_AMD64_REL32 = 0x0004
IMAGE_REL_AMD64_SECREL = 0x000B
IMAGE_REL_I386_DIR32 = 0x0006
IMAGE_REL_I386_DIR32NB = 0x0007
IMAGE_REL_I386_SECREL = 0x000B
IMAGE_REL_I386_REL32 = 0x0014

IMAGE_REL_AMD64_ADDR64 = 0x0001
IMAGE_REL_AMD64_ADDR32 = 0x0002
IMAGE_REL_AMD64_ADDR32NB = 0x0003
IMAGE_REL_AMD64_REL32 = 0x0004
IMAGE_REL_AMD64_SECREL = 0x000B

IMAGE_REL_ARM_ABSOLUTE = 0x0000
IMAGE_REL_ARM_ADDR32 = 0x0001
Expand Down
11 changes: 11 additions & 0 deletions src/cmd/link/internal/loader/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,17 @@ func TestAddDataMethods(t *testing.T) {
expKind: sym.SDATA,
expRel: []Reloc{mkReloc(ldr, objabi.R_ADDRCUOFF, 0, 8, 7, 8)},
},
{
which: "AddPEImageRelativeAddrPlus",
addDataFunc: func(l *Loader, s Sym, s2 Sym) Sym {
sb := l.MakeSymbolUpdater(s)
sb.AddPEImageRelativeAddrPlus(arch, s2, 3)
return s
},
expData: []byte{0, 0, 0, 0},
expKind: sym.SDATA,
expRel: []Reloc{mkReloc(ldr, objabi.R_PEIMAGEOFF, 0, 4, 3, 9)},
},
}

var pmi Sym
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/link/internal/loader/symbolbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ func (sb *SymbolBuilder) AddAddr(arch *sys.Arch, tgt Sym) int64 {
return sb.AddAddrPlus(arch, tgt, 0)
}

func (sb *SymbolBuilder) AddPEImageRelativeAddrPlus(arch *sys.Arch, tgt Sym, add int64) int64 {
return sb.addSymRef(tgt, add, objabi.R_PEIMAGEOFF, 4)
}

func (sb *SymbolBuilder) AddPCRelPlus(arch *sys.Arch, tgt Sym, add int64) int64 {
return sb.addSymRef(tgt, add, objabi.R_PCREL, 4)
}
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/link/internal/x86/asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
case objabi.R_ADDR:
v = ld.IMAGE_REL_I386_DIR32

case objabi.R_PEIMAGEOFF:
v = ld.IMAGE_REL_I386_DIR32NB

case objabi.R_CALL,
objabi.R_PCREL:
v = ld.IMAGE_REL_I386_REL32
Expand Down

0 comments on commit f57f02f

Please sign in to comment.