aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/goobj/objfile_test.go
blob: ed942aa93448bd1e36c57309039beadf5efaf090 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package goobj

import (
	"bufio"
	"bytes"
	"cmd/internal/bio"
	"cmd/internal/objabi"
	"fmt"
	"internal/buildcfg"
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
)

func dummyWriter(buf *bytes.Buffer) *Writer {
	wr := &bio.Writer{Writer: bufio.NewWriter(buf)} // hacky: no file, so cannot seek
	return NewWriter(wr)
}

func TestReadWrite(t *testing.T) {
	// Test that we get the same data in a write-read roundtrip.

	// Write a symbol, a relocation, and an aux info.
	var buf bytes.Buffer
	w := dummyWriter(&buf)

	var s Sym
	s.SetABI(1)
	s.SetType(uint8(objabi.STEXT))
	s.SetFlag(0x12)
	s.SetSiz(12345)
	s.SetAlign(8)
	s.Write(w)

	var r Reloc
	r.SetOff(12)
	r.SetSiz(4)
	r.SetType(uint16(objabi.R_ADDR))
	r.SetAdd(54321)
	r.SetSym(SymRef{11, 22})
	r.Write(w)

	var a Aux
	a.SetType(AuxFuncInfo)
	a.SetSym(SymRef{33, 44})
	a.Write(w)

	w.wr.Flush()

	// Read them back and check.
	b := buf.Bytes()
	var s2 Sym
	s2.fromBytes(b)
	if s2.ABI() != 1 || s2.Type() != uint8(objabi.STEXT) || s2.Flag() != 0x12 || s2.Siz() != 12345 || s2.Align() != 8 {
		t.Errorf("read Sym2 mismatch: got %v %v %v %v %v", s2.ABI(), s2.Type(), s2.Flag(), s2.Siz(), s2.Align())
	}

	b = b[SymSize:]
	var r2 Reloc
	r2.fromBytes(b)
	if r2.Off() != 12 || r2.Siz() != 4 || r2.Type() != uint16(objabi.R_ADDR) || r2.Add() != 54321 || r2.Sym() != (SymRef{11, 22}) {
		t.Errorf("read Reloc2 mismatch: got %v %v %v %v %v", r2.Off(), r2.Siz(), r2.Type(), r2.Add(), r2.Sym())
	}

	b = b[RelocSize:]
	var a2 Aux
	a2.fromBytes(b)
	if a2.Type() != AuxFuncInfo || a2.Sym() != (SymRef{33, 44}) {
		t.Errorf("read Aux2 mismatch: got %v %v", a2.Type(), a2.Sym())
	}
}

var issue41621prolog = `
package main
var lines = []string{
`

var issue41621epilog = `
}
func getLines() []string {
	return lines
}
func main() {
	println(getLines())
}
`

func TestIssue41621LargeNumberOfRelocations(t *testing.T) {
	if testing.Short() || (buildcfg.GOARCH != "amd64") {
		t.Skipf("Skipping large number of relocations test in short mode or on %s", buildcfg.GOARCH)
	}
	testenv.MustHaveGoBuild(t)

	tmpdir, err := ioutil.TempDir("", "lotsofrelocs")
	if err != nil {
		t.Fatalf("can't create temp directory: %v\n", err)
	}
	defer os.RemoveAll(tmpdir)

	// Emit testcase.
	var w bytes.Buffer
	fmt.Fprintf(&w, issue41621prolog)
	for i := 0; i < 1048576+13; i++ {
		fmt.Fprintf(&w, "\t\"%d\",\n", i)
	}
	fmt.Fprintf(&w, issue41621epilog)
	err = ioutil.WriteFile(tmpdir+"/large.go", w.Bytes(), 0666)
	if err != nil {
		t.Fatalf("can't write output: %v\n", err)
	}

	// Emit go.mod
	w.Reset()
	fmt.Fprintf(&w, "module issue41621\n\ngo 1.12\n")
	err = ioutil.WriteFile(tmpdir+"/go.mod", w.Bytes(), 0666)
	if err != nil {
		t.Fatalf("can't write output: %v\n", err)
	}
	w.Reset()

	// Build.
	cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "large")
	cmd.Dir = tmpdir
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("Build failed: %v, output: %s", err, out)
	}
}