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) { ...@@ -247,7 +247,7 @@ func determineLinkMode(ctxt *Link) {
} }
ctxt.LinkMode = LinkInternal ctxt.LinkMode = LinkInternal
case "1": 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) Exitf("external linking requested via GO_EXTLINK_ENABLED but not supported for %s/ppc64", objabi.GOOS)
} }
ctxt.LinkMode = LinkExternal ctxt.LinkMode = LinkExternal
...@@ -261,7 +261,7 @@ func determineLinkMode(ctxt *Link) { ...@@ -261,7 +261,7 @@ func determineLinkMode(ctxt *Link) {
} else { } else {
ctxt.LinkMode = LinkInternal 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) Exitf("external linking is not supported for %s/ppc64", objabi.GOOS)
} }
} }
...@@ -270,7 +270,7 @@ func determineLinkMode(ctxt *Link) { ...@@ -270,7 +270,7 @@ func determineLinkMode(ctxt *Link) {
Exitf("internal linking requested but external linking required: %s", reason) Exitf("internal linking requested but external linking required: %s", reason)
} }
case LinkExternal: case LinkExternal:
if objabi.GOARCH == "ppc64" { if objabi.GOARCH == "ppc64" && objabi.GOOS != "aix" {
Exitf("external linking not supported for %s/ppc64", objabi.GOOS) Exitf("external linking not supported for %s/ppc64", objabi.GOOS)
} }
} }
......
...@@ -308,6 +308,8 @@ func relocsym(ctxt *Link, s *sym.Symbol) { ...@@ -308,6 +308,8 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
} }
} else if ctxt.HeadType == objabi.Hwindows { } else if ctxt.HeadType == objabi.Hwindows {
// nothing to do // nothing to do
} else if ctxt.HeadType == objabi.Haix {
o = Symaddr(r.Sym) + r.Add
} else { } else {
Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.HeadType) Errorf(s, "unhandled pcrel relocation to %s on %v", rs.Name, ctxt.HeadType)
} }
...@@ -1400,7 +1402,7 @@ func (ctxt *Link) dodata() { ...@@ -1400,7 +1402,7 @@ func (ctxt *Link) dodata() {
if len(data[sym.STLSBSS]) > 0 { if len(data[sym.STLSBSS]) > 0 {
var sect *sym.Section 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 = addsection(ctxt.Arch, &Segdata, ".tbss", 06)
sect.Align = int32(ctxt.Arch.PtrSize) sect.Align = int32(ctxt.Arch.PtrSize)
sect.Vaddr = 0 sect.Vaddr = 0
...@@ -1538,7 +1540,7 @@ func (ctxt *Link) dodata() { ...@@ -1538,7 +1540,7 @@ func (ctxt *Link) dodata() {
if ctxt.UseRelro() { if ctxt.UseRelro() {
addrelrosection = func(suffix string) *sym.Section { addrelrosection = func(suffix string) *sym.Section {
seg := &Segrelrodata seg := &Segrelrodata
if ctxt.LinkMode == LinkExternal { if ctxt.LinkMode == LinkExternal && ctxt.HeadType != objabi.Haix {
// Using a separate segment with an external // Using a separate segment with an external
// linker results in some programs moving // linker results in some programs moving
// their data sections unexpectedly, which // their data sections unexpectedly, which
...@@ -2046,6 +2048,10 @@ func (ctxt *Link) address() []*sym.Segment { ...@@ -2046,6 +2048,10 @@ func (ctxt *Link) address() []*sym.Segment {
// align to page boundary so as not to mix // align to page boundary so as not to mix
// rodata, rel-ro data, and executable text. // rodata, rel-ro data, and executable text.
va = uint64(Rnd(int64(va), int64(*FlagRound))) 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) order = append(order, &Segrelrodata)
Segrelrodata.Rwx = 06 Segrelrodata.Rwx = 06
...@@ -2060,9 +2066,10 @@ func (ctxt *Link) address() []*sym.Segment { ...@@ -2060,9 +2066,10 @@ func (ctxt *Link) address() []*sym.Segment {
} }
va = uint64(Rnd(int64(va), int64(*FlagRound))) 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 // Data sections are moved to an unreachable segment
// to ensure that they are position-independent. // to ensure that they are position-independent.
// Already done if relro sections exist.
va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE) va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
} }
order = append(order, &Segdata) order = append(order, &Segdata)
...@@ -2073,11 +2080,11 @@ func (ctxt *Link) address() []*sym.Segment { ...@@ -2073,11 +2080,11 @@ func (ctxt *Link) address() []*sym.Segment {
var bss *sym.Section var bss *sym.Section
var noptrbss *sym.Section var noptrbss *sym.Section
for i, s := range Segdata.Sections { for i, s := range Segdata.Sections {
if ctxt.IsELF && s.Name == ".tbss" { if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
continue continue
} }
vlen := int64(s.Length) 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) vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
} }
s.Vaddr = va s.Vaddr = va
......
...@@ -1683,6 +1683,7 @@ func dwarfEnabled(ctxt *Link) bool { ...@@ -1683,6 +1683,7 @@ func dwarfEnabled(ctxt *Link) bool {
} }
if ctxt.LinkMode == LinkExternal { if ctxt.LinkMode == LinkExternal {
// TODO(aix): enable DWARF
switch { switch {
case ctxt.IsELF: case ctxt.IsELF:
case ctxt.HeadType == objabi.Hdarwin: case ctxt.HeadType == objabi.Hdarwin:
......
...@@ -133,6 +133,7 @@ type Arch struct { ...@@ -133,6 +133,7 @@ type Arch struct {
Gentext func(*Link) Gentext func(*Link)
Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool Machoreloc1 func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
PEreloc1 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 // TLSIEtoLE converts a TLS Initial Executable relocation to
// a TLS Local Executable relocation. // a TLS Local Executable relocation.
...@@ -179,7 +180,7 @@ func (ctxt *Link) UseRelro() bool { ...@@ -179,7 +180,7 @@ func (ctxt *Link) UseRelro() bool {
case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin: case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin:
return ctxt.IsELF return ctxt.IsELF
default: default:
return ctxt.linkShared return ctxt.linkShared || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal)
} }
} }
...@@ -405,7 +406,7 @@ func (ctxt *Link) loadlib() { ...@@ -405,7 +406,7 @@ func (ctxt *Link) loadlib() {
*FlagTextAddr = 0 *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 := ctxt.Syms.Lookup(".TOC.", 0)
toc.Type = sym.SDYNIMPORT toc.Type = sym.SDYNIMPORT
} }
...@@ -1145,6 +1146,11 @@ func (ctxt *Link) hostlink() { ...@@ -1145,6 +1146,11 @@ func (ctxt *Link) hostlink() {
} else { } else {
argv = append(argv, "-mconsole") 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 { switch ctxt.BuildMode {
...@@ -1493,7 +1499,7 @@ func hostlinkArchArgs(arch *sys.Arch) []string { ...@@ -1493,7 +1499,7 @@ func hostlinkArchArgs(arch *sys.Arch) []string {
switch arch.Family { switch arch.Family {
case sys.I386: case sys.I386:
return []string{"-m32"} return []string{"-m32"}
case sys.AMD64, sys.PPC64, sys.S390X: case sys.AMD64, sys.S390X:
return []string{"-m64"} return []string{"-m64"}
case sys.ARM: case sys.ARM:
return []string{"-marm"} return []string{"-marm"}
...@@ -1503,6 +1509,13 @@ func hostlinkArchArgs(arch *sys.Arch) []string { ...@@ -1503,6 +1509,13 @@ func hostlinkArchArgs(arch *sys.Arch) []string {
return []string{"-mabi=64"} return []string{"-mabi=64"}
case sys.MIPS: case sys.MIPS:
return []string{"-mabi=32"} return []string{"-mabi=32"}
case sys.PPC64:
if objabi.GOOS == "aix" {
return []string{"-maix64"}
} else {
return []string{"-m64"}
}
} }
return nil return nil
} }
......
This diff is collapsed.
...@@ -382,6 +382,43 @@ func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { ...@@ -382,6 +382,43 @@ func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
return false 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 { 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. // 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 { 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 { ...@@ -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") 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 t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
// change ld to addi in the second instruction // change ld to addi in the second instruction
o2 = (o2 & 0x03FF0000) | 0xE<<26 o2 = (o2 & 0x03FF0000) | 0xE<<26
...@@ -704,9 +741,13 @@ func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, o ...@@ -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) { func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
if ctxt.LinkMode == ld.LinkExternal { 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 { switch r.Type {
default: 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: case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
r.Done = false r.Done = false
// check Outer is nil, Type is TLSBSS? // 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 ...@@ -734,12 +775,16 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
} }
r.Xsym = rs r.Xsym = rs
return val, true if ctxt.HeadType != objabi.Haix {
return val, true
}
case objabi.R_CALLPOWER: case objabi.R_CALLPOWER:
r.Done = false r.Done = false
r.Xsym = r.Sym r.Xsym = r.Sym
r.Xadd = r.Add 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) { ...@@ -59,6 +59,7 @@ func Init() (*sys.Arch, ld.Arch) {
Gentext: gentext, Gentext: gentext,
Trampoline: trampoline, Trampoline: trampoline,
Machoreloc1: machoreloc1, Machoreloc1: machoreloc1,
Xcoffreloc1: xcoffreloc1,
// TODO(austin): ABI v1 uses /usr/lib/ld.so.1, // TODO(austin): ABI v1 uses /usr/lib/ld.so.1,
Linuxdynld: "/lib64/ld64.so.1", Linuxdynld: "/lib64/ld64.so.1",
......
...@@ -784,11 +784,18 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8 ...@@ -784,11 +784,18 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8
RET RET
#ifdef GOARCH_ppc64 #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 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
DWORD $_setg_gcc<>(SB) DWORD $_setg_gcc<>(SB)
DWORD $0 DWORD $0
DWORD $0 DWORD $0
#endif #endif
#endif
// void setg_gcc(G*); set g in C TLS. // void setg_gcc(G*); set g in C TLS.
// Must obey the gcc calling convention. // Must obey the gcc calling convention.
......
...@@ -34,6 +34,15 @@ TEXT __start<>(SB),NOSPLIT,$-8 ...@@ -34,6 +34,15 @@ TEXT __start<>(SB),NOSPLIT,$-8
MOVD 40(R1), R2 MOVD 40(R1), R2
MOVD R14, R3 // argc MOVD R14, R3 // argc
MOVD R15, R4 // argv 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 $runtime·rt0_go(SB), R12
MOVD R12, CTR MOVD R12, CTR
BR (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