mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: handle large relocation addend on darwin/arm64
Mach-O relocation addend is signed 24-bit. When external linking, if the addend is larger, we cannot put it directly into a Mach-O relocation. This CL handles large addend by creating "label" symbols at sym+0x800000, sym+(0x800000*2), etc., and emitting Mach-O relocations that target the label symbols with a smaller addend. The label symbols are generated late (similar to what we do for RISC-V64). One complexity comes from handling of carrier symbols, which does not track its size or its inner symbols. But relocations can target them. We track them in a side table (similar to what we do for XCOFF, xcoffUpdateOuterSize). Fixes #42738. Change-Id: I8c53ab2397f8b88870d26f00e9026285e5ff5584 Reviewed-on: https://go-review.googlesource.com/c/go/+/278332 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
a318d56c1e
commit
5abda2618b
8 changed files with 176 additions and 10 deletions
|
|
@ -925,3 +925,57 @@ func TestIssue42396(t *testing.T) {
|
|||
t.Fatalf("error message incorrect: expected it to contain %q but instead got:\n%s\n", want, out)
|
||||
}
|
||||
}
|
||||
|
||||
const testLargeRelocSrc = `
|
||||
package main
|
||||
|
||||
var x = [1<<25]byte{1<<23: 23, 1<<24: 24}
|
||||
|
||||
func main() {
|
||||
check(x[1<<23-1], 0)
|
||||
check(x[1<<23], 23)
|
||||
check(x[1<<23+1], 0)
|
||||
check(x[1<<24-1], 0)
|
||||
check(x[1<<24], 24)
|
||||
check(x[1<<24+1], 0)
|
||||
}
|
||||
|
||||
func check(x, y byte) {
|
||||
if x != y {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
func TestLargeReloc(t *testing.T) {
|
||||
// Test that large relocation addend is handled correctly.
|
||||
// In particular, on darwin/arm64 when external linking,
|
||||
// Mach-O relocation has only 24-bit addend. See issue #42738.
|
||||
testenv.MustHaveGoBuild(t)
|
||||
t.Parallel()
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "TestIssue42396")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
src := filepath.Join(tmpdir, "x.go")
|
||||
err = ioutil.WriteFile(src, []byte(testLargeRelocSrc), 0666)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write source file: %v", err)
|
||||
}
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "run", src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("build failed: %v. output:\n%s", err, out)
|
||||
}
|
||||
|
||||
if testenv.HasCGO() { // currently all targets that support cgo can external link
|
||||
cmd = exec.Command(testenv.GoToolPath(t), "run", "-ldflags=-linkmode=external", src)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed: %v. output:\n%s", err, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue