Commit 80f10965 authored by Clément Chigot's avatar Clément Chigot Committed by Ian Lance Taylor

cmd/link, runtime: allow external linking for aix/ppc64

This commit adds external linking in cmd/link for aix/ppc64.
As relocations on .text data aren't possible on AIX, Segrelrodata is
used to move all these datas to .data section.

Change-Id: I4d1361c1fc9290e11e6f5560864460c76551dbeb
Reviewed-on: https://go-review.googlesource.com/c/go/+/164003
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 0ff0df8b
......@@ -247,7 +247,7 @@ func determineLinkMode(ctxt *Link) {
}
ctxt.LinkMode = LinkInternal
case "1":
if objabi.GOARCH == "ppc64" {
if objabi.GOARCH == "ppc64" && objabi.GOOS != "aix" {
Exitf("external linking requested via GO_EXTLINK_ENABLED but not supported for %s/ppc64", objabi.GOOS)
}
ctxt.LinkMode = LinkExternal
......@@ -261,7 +261,7 @@ func determineLinkMode(ctxt *Link) {
} else {
ctxt.LinkMode = LinkInternal
}
if objabi.GOARCH == "ppc64" && ctxt.LinkMode == LinkExternal {
if objabi.GOARCH == "ppc64" && objabi.GOOS != "aix" && ctxt.LinkMode == LinkExternal {
Exitf("external linking is not supported for %s/ppc64", objabi.GOOS)
}
}
......@@ -270,7 +270,7 @@ func determineLinkMode(ctxt *Link) {
Exitf("internal linking requested but external linking required: %s", reason)
}
case LinkExternal:
if objabi.GOARCH == "ppc64" {
if objabi.GOARCH == "ppc64" && objabi.GOOS != "aix" {
Exitf("external linking not supported for %s/ppc64", objabi.GOOS)
}
}
......
......@@ -308,6 +308,8 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
}
} else if ctxt.HeadType == objabi.Hwindows {
// nothing to do
} else if ctxt.HeadType == objabi.Haix {
o = Symaddr(r.Sym) + r.Add
} else {
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.HeadType)
}
......@@ -1400,7 +1402,7 @@ func (ctxt *Link) dodata() {
if len(data[sym.STLSBSS]) > 0 {
var sect *sym.Section
if ctxt.IsELF && (ctxt.LinkMode == LinkExternal || !*FlagD) {
if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
sect = addsection(ctxt.Arch, &Segdata, ".tbss", 06)
sect.Align = int32(ctxt.Arch.PtrSize)
sect.Vaddr = 0
......@@ -1538,7 +1540,7 @@ func (ctxt *Link) dodata() {
if ctxt.UseRelro() {
addrelrosection = func(suffix string) *sym.Section {
seg := &Segrelrodata
if ctxt.LinkMode == LinkExternal {
if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
// Using a separate segment with an external
// linker results in some programs moving
// their data sections unexpectedly, which
......@@ -2046,6 +2048,10 @@ func (ctxt *Link) address() []*sym.Segment {
// align to page boundary so as not to mix
// rodata, rel-ro data, and executable text.
va = uint64(Rnd(int64(va), int64(*FlagRound)))
if ctxt.HeadType == objabi.Haix {
// Relro data are inside data segment on AIX.
va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
}
order = append(order, &Segrelrodata)
Segrelrodata.Rwx = 06
......@@ -2060,9 +2066,10 @@ func (ctxt *Link) address() []*sym.Segment {
}
va = uint64(Rnd(int64(va), int64(*FlagRound)))
if ctxt.HeadType == objabi.Haix {
if ctxt.HeadType == objabi.Haix && len(Segrelrodata.Sections) == 0 {
// Data sections are moved to an unreachable segment
// to ensure that they are position-independent.
// Already done if relro sections exist.
va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
}
order = append(order, &Segdata)
......@@ -2073,11 +2080,11 @@ func (ctxt *Link) address() []*sym.Segment {
var bss *sym.Section
var noptrbss *sym.Section
for i, s := range Segdata.Sections {
if ctxt.IsELF && s.Name == ".tbss" {
if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
continue
}
vlen := int64(s.Length)
if i+1 < len(Segdata.Sections) && !(ctxt.IsELF && Segdata.Sections[i+1].Name == ".tbss") {
if i+1 < len(Segdata.Sections) && !((ctxt.IsELF || ctxt.HeadType == objabi.Haix) && Segdata.Sections[i+1].Name == ".tbss") {
vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
}
s.Vaddr = va
......
......@@ -1683,6 +1683,7 @@ func dwarfEnabled(ctxt *Link) bool {
}
if ctxt.LinkMode == LinkExternal {
// TODO(aix): enable DWARF
switch {
case ctxt.IsELF:
case ctxt.HeadType == objabi.Hdarwin:
......
......@@ -133,6 +133,7 @@ type Arch struct {
Gentext func(*Link)
Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
PEreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
Xcoffreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
// TLSIEtoLE converts a TLS Initial Executable relocation to
// a TLS Local Executable relocation.
......@@ -179,7 +180,7 @@ func (ctxt *Link) UseRelro() bool {
case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin:
return ctxt.IsELF
default:
return ctxt.linkShared
return ctxt.linkShared || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal)
}
}
......@@ -405,7 +406,7 @@ func (ctxt *Link) loadlib() {
*FlagTextAddr = 0
}
if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 {
if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && objabi.GOOS != "aix" {
toc := ctxt.Syms.Lookup(".TOC.", 0)
toc.Type = sym.SDYNIMPORT
}
......@@ -1145,6 +1146,11 @@ func (ctxt *Link) hostlink() {
} else {
argv = append(argv, "-mconsole")
}
case objabi.Haix:
argv = append(argv, "-pthread")
// prevent ld to reorder .text functions to keep the same
// first/last functions for moduledata.
argv = append(argv, "-Wl,-bnoobjreorder")
}
switch ctxt.BuildMode {
......@@ -1493,7 +1499,7 @@ func hostlinkArchArgs(arch *sys.Arch) []string {
switch arch.Family {
case sys.I386:
return []string{"-m32"}
case sys.AMD64, sys.PPC64, sys.S390X:
case sys.AMD64, sys.S390X:
return []string{"-m64"}
case sys.ARM:
return []string{"-marm"}
......@@ -1503,6 +1509,13 @@ func hostlinkArchArgs(arch *sys.Arch) []string {
return []string{"-mabi=64"}
case sys.MIPS:
return []string{"-mabi=32"}
case sys.PPC64:
if objabi.GOOS == "aix" {
return []string{"-maix64"}
} else {
return []string{"-m64"}
}
}
return nil
}
......
This diff is collapsed.
......@@ -382,6 +382,43 @@ func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
return false
}
func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
rs := r.Xsym
emitReloc := func(v uint16, off uint64) {
out.Write64(uint64(sectoff) + off)
out.Write32(uint32(rs.Dynid))
out.Write16(v)
}
var v uint16
switch r.Type {
default:
return false
case objabi.R_ADDR:
v = ld.XCOFF_R_POS
if r.Siz == 4 {
v |= 0x1F << 8
} else {
v |= 0x3F << 8
}
emitReloc(v, 0)
case objabi.R_ADDRPOWER_TOCREL:
case objabi.R_ADDRPOWER_TOCREL_DS:
emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
case objabi.R_POWER_TLS_LE:
emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
case objabi.R_CALLPOWER:
if r.Siz != 4 {
return false
}
emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
}
return true
}
func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
// Beware that bit0~bit15 start from the third byte of a instruction in Big-Endian machines.
if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
......@@ -514,7 +551,7 @@ func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
}
if tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
if ctxt.LinkMode == ld.LinkInternal && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
// change ld to addi in the second instruction
o2 = (o2 & 0x03FF0000) | 0xE<<26
......@@ -704,9 +741,13 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, o
func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if ctxt.LinkMode == ld.LinkExternal {
// On AIX, relocations (except TLS ones) must be also done to the
// value with the current addresses.
switch r.Type {
default:
return val, false
if ctxt.HeadType != objabi.Haix {
return val, false
}
case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
r.Done = false
// check Outer is nil, Type is TLSBSS?
......@@ -734,12 +775,16 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
}
r.Xsym = rs
return val, true
if ctxt.HeadType != objabi.Haix {
return val, true
}
case objabi.R_CALLPOWER:
r.Done = false
r.Xsym = r.Sym
r.Xadd = r.Add
return val, true
if ctxt.HeadType != objabi.Haix {
return val, true
}
}
}
......
......@@ -59,6 +59,7 @@ func Init() (*sys.Arch, ld.Arch) {
Gentext: gentext,
Trampoline: trampoline,
Machoreloc1: machoreloc1,
Xcoffreloc1: xcoffreloc1,
// TODO(austin): ABI v1 uses /usr/lib/ld.so.1,
Linuxdynld: "/lib64/ld64.so.1",
......
......@@ -784,11 +784,18 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8
RET
#ifdef GOARCH_ppc64
#ifdef GOOS_aix
DATA setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB)
DATA setg_gcc<>+8(SB)/8, $TOC(SB)
DATA setg_gcc<>+16(SB)/8, $0
GLOBL setg_gcc<>(SB), NOPTR, $24
#else
TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
DWORD $_setg_gcc<>(SB)
DWORD $0
DWORD $0
#endif
#endif
// void setg_gcc(G*); set g in C TLS.
// Must obey the gcc calling convention.
......
......@@ -34,6 +34,15 @@ TEXT __start<>(SB),NOSPLIT,$-8
MOVD 40(R1), R2
MOVD R14, R3 // argc
MOVD R15, R4 // argv
BL _main(SB)
DATA main+0(SB)/8, $_main(SB)
DATA main+8(SB)/8, $TOC(SB)
DATA main+16(SB)/8, $0
GLOBL main(SB), NOPTR, $24
TEXT _main(SB),NOSPLIT,$-8
MOVD $runtime·rt0_go(SB), R12
MOVD R12, CTR
BR (CTR)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment