github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/link/ld/elf_test.go (about) 1 // Copyright 2019 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 5 //go:build cgo 6 7 package ld 8 9 import ( 10 "debug/elf" 11 "os" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 17 "github.com/go-asm/go/testenv" 18 ) 19 20 func TestDynSymShInfo(t *testing.T) { 21 t.Parallel() 22 testenv.MustHaveGoBuild(t) 23 dir := t.TempDir() 24 25 const prog = ` 26 package main 27 28 import "net" 29 30 func main() { 31 net.Dial("", "") 32 } 33 ` 34 src := filepath.Join(dir, "issue33358.go") 35 if err := os.WriteFile(src, []byte(prog), 0666); err != nil { 36 t.Fatal(err) 37 } 38 39 binFile := filepath.Join(dir, "issue33358") 40 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", binFile, src) 41 if out, err := cmd.CombinedOutput(); err != nil { 42 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) 43 } 44 45 fi, err := os.Open(binFile) 46 if err != nil { 47 t.Fatalf("failed to open built file: %v", err) 48 } 49 defer fi.Close() 50 51 elfFile, err := elf.NewFile(fi) 52 if err != nil { 53 t.Skip("The system may not support ELF, skipped.") 54 } 55 56 section := elfFile.Section(".dynsym") 57 if section == nil { 58 t.Fatal("no dynsym") 59 } 60 61 symbols, err := elfFile.DynamicSymbols() 62 if err != nil { 63 t.Fatalf("failed to get dynamic symbols: %v", err) 64 } 65 66 var numLocalSymbols uint32 67 for i, s := range symbols { 68 if elf.ST_BIND(s.Info) != elf.STB_LOCAL { 69 numLocalSymbols = uint32(i + 1) 70 break 71 } 72 } 73 74 if section.Info != numLocalSymbols { 75 t.Fatalf("Unexpected sh info, want greater than 0, got: %d", section.Info) 76 } 77 } 78 79 func TestNoDuplicateNeededEntries(t *testing.T) { 80 testenv.MustHaveGoBuild(t) 81 testenv.MustHaveCGO(t) 82 83 // run this test on just a small set of platforms (no need to test it 84 // across the board given the nature of the test). 85 pair := runtime.GOOS + "-" + runtime.GOARCH 86 switch pair { 87 case "linux-amd64", "linux-arm64", "freebsd-amd64", "openbsd-amd64": 88 default: 89 t.Skip("no need for test on " + pair) 90 } 91 92 t.Parallel() 93 94 dir := t.TempDir() 95 96 wd, err := os.Getwd() 97 if err != nil { 98 t.Fatalf("Failed to get working directory: %v", err) 99 } 100 101 path := filepath.Join(dir, "x") 102 argv := []string{"build", "-o", path, filepath.Join(wd, "testdata", "issue39256")} 103 out, err := testenv.Command(t, testenv.GoToolPath(t), argv...).CombinedOutput() 104 if err != nil { 105 t.Fatalf("Build failure: %s\n%s\n", err, string(out)) 106 } 107 108 f, err := elf.Open(path) 109 if err != nil { 110 t.Fatalf("Failed to open ELF file: %v", err) 111 } 112 libs, err := f.ImportedLibraries() 113 if err != nil { 114 t.Fatalf("Failed to read imported libraries: %v", err) 115 } 116 117 var count int 118 for _, lib := range libs { 119 if lib == "libc.so" || strings.HasPrefix(lib, "libc.so.") { 120 count++ 121 } 122 } 123 124 if got, want := count, 1; got != want { 125 t.Errorf("Got %d entries for `libc.so`, want %d", got, want) 126 } 127 } 128 129 func TestShStrTabAttributesIssue62600(t *testing.T) { 130 t.Parallel() 131 testenv.MustHaveGoBuild(t) 132 dir := t.TempDir() 133 134 const prog = ` 135 package main 136 137 func main() { 138 println("whee") 139 } 140 ` 141 src := filepath.Join(dir, "issue62600.go") 142 if err := os.WriteFile(src, []byte(prog), 0666); err != nil { 143 t.Fatal(err) 144 } 145 146 binFile := filepath.Join(dir, "issue62600") 147 cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", binFile, src) 148 if out, err := cmd.CombinedOutput(); err != nil { 149 t.Fatalf("%v: %v:\n%s", cmd.Args, err, out) 150 } 151 152 fi, err := os.Open(binFile) 153 if err != nil { 154 t.Fatalf("failed to open built file: %v", err) 155 } 156 defer fi.Close() 157 158 elfFile, err := elf.NewFile(fi) 159 if err != nil { 160 t.Skip("The system may not support ELF, skipped.") 161 } 162 163 section := elfFile.Section(".shstrtab") 164 if section == nil { 165 t.Fatal("no .shstrtab") 166 } 167 168 // The .shstrtab section should have a zero address, non-zero 169 // size, no ALLOC flag, and the offset should not fall into any of 170 // the segments defined by the program headers. 171 if section.Addr != 0 { 172 t.Fatalf("expected Addr == 0 for .shstrtab got %x", section.Addr) 173 } 174 if section.Size == 0 { 175 t.Fatal("expected nonzero Size for .shstrtab got 0") 176 } 177 if section.Flags&elf.SHF_ALLOC != 0 { 178 t.Fatal("expected zero alloc flag got nonzero for .shstrtab") 179 } 180 for idx, p := range elfFile.Progs { 181 if section.Offset >= p.Off && section.Offset < p.Off+p.Filesz { 182 t.Fatalf("badly formed .shstrtab, is contained in segment %d", idx) 183 } 184 } 185 }