1// Copyright 2020 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package goobj 6 7import ( 8 "bufio" 9 "bytes" 10 "fmt" 11 "internal/buildcfg" 12 "internal/testenv" 13 "os" 14 "testing" 15 16 "cmd/internal/bio" 17 "cmd/internal/objabi" 18) 19 20func dummyWriter(buf *bytes.Buffer) *Writer { 21 wr := &bio.Writer{Writer: bufio.NewWriter(buf)} // hacky: no file, so cannot seek 22 return NewWriter(wr) 23} 24 25func TestReadWrite(t *testing.T) { 26 // Test that we get the same data in a write-read roundtrip. 27 28 // Write a symbol, a relocation, and an aux info. 29 var buf bytes.Buffer 30 w := dummyWriter(&buf) 31 32 var s Sym 33 s.SetABI(1) 34 s.SetType(uint8(objabi.STEXT)) 35 s.SetFlag(0x12) 36 s.SetSiz(12345) 37 s.SetAlign(8) 38 s.Write(w) 39 40 var r Reloc 41 r.SetOff(12) 42 r.SetSiz(4) 43 r.SetType(uint16(objabi.R_ADDR)) 44 r.SetAdd(54321) 45 r.SetSym(SymRef{11, 22}) 46 r.Write(w) 47 48 var a Aux 49 a.SetType(AuxFuncInfo) 50 a.SetSym(SymRef{33, 44}) 51 a.Write(w) 52 53 w.wr.Flush() 54 55 // Read them back and check. 56 b := buf.Bytes() 57 var s2 Sym 58 s2.fromBytes(b) 59 if s2.ABI() != 1 || s2.Type() != uint8(objabi.STEXT) || s2.Flag() != 0x12 || s2.Siz() != 12345 || s2.Align() != 8 { 60 t.Errorf("read Sym2 mismatch: got %v %v %v %v %v", s2.ABI(), s2.Type(), s2.Flag(), s2.Siz(), s2.Align()) 61 } 62 63 b = b[SymSize:] 64 var r2 Reloc 65 r2.fromBytes(b) 66 if r2.Off() != 12 || r2.Siz() != 4 || r2.Type() != uint16(objabi.R_ADDR) || r2.Add() != 54321 || r2.Sym() != (SymRef{11, 22}) { 67 t.Errorf("read Reloc2 mismatch: got %v %v %v %v %v", r2.Off(), r2.Siz(), r2.Type(), r2.Add(), r2.Sym()) 68 } 69 70 b = b[RelocSize:] 71 var a2 Aux 72 a2.fromBytes(b) 73 if a2.Type() != AuxFuncInfo || a2.Sym() != (SymRef{33, 44}) { 74 t.Errorf("read Aux2 mismatch: got %v %v", a2.Type(), a2.Sym()) 75 } 76} 77 78var issue41621prolog = ` 79package main 80var lines = []string{ 81` 82 83var issue41621epilog = ` 84} 85func getLines() []string { 86 return lines 87} 88func main() { 89 println(getLines()) 90} 91` 92 93func TestIssue41621LargeNumberOfRelocations(t *testing.T) { 94 if testing.Short() || (buildcfg.GOARCH != "amd64") { 95 t.Skipf("Skipping large number of relocations test in short mode or on %s", buildcfg.GOARCH) 96 } 97 testenv.MustHaveGoBuild(t) 98 99 tmpdir, err := os.MkdirTemp("", "lotsofrelocs") 100 if err != nil { 101 t.Fatalf("can't create temp directory: %v\n", err) 102 } 103 defer os.RemoveAll(tmpdir) 104 105 // Emit testcase. 106 var w bytes.Buffer 107 fmt.Fprintf(&w, issue41621prolog) 108 for i := 0; i < 1048576+13; i++ { 109 fmt.Fprintf(&w, "\t\"%d\",\n", i) 110 } 111 fmt.Fprintf(&w, issue41621epilog) 112 err = os.WriteFile(tmpdir+"/large.go", w.Bytes(), 0666) 113 if err != nil { 114 t.Fatalf("can't write output: %v\n", err) 115 } 116 117 // Emit go.mod 118 w.Reset() 119 fmt.Fprintf(&w, "module issue41621\n\ngo 1.12\n") 120 err = os.WriteFile(tmpdir+"/go.mod", w.Bytes(), 0666) 121 if err != nil { 122 t.Fatalf("can't write output: %v\n", err) 123 } 124 w.Reset() 125 126 // Build. 127 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "large") 128 cmd.Dir = tmpdir 129 out, err := cmd.CombinedOutput() 130 if err != nil { 131 t.Fatalf("Build failed: %v, output: %s", err, out) 132 } 133} 134