| // Copyright 2019 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. | |
| // +build dragonfly freebsd linux netbsd openbsd | |
| package main | |
| import ( | |
| "internal/testenv" | |
| "io/ioutil" | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "strings" | |
| "testing" | |
| ) | |
| var asmSource = ` | |
| .section .text1,"ax" | |
| s1: | |
| .byte 0 | |
| .section .text2,"ax" | |
| s2: | |
| .byte 0 | |
| ` | |
| var goSource = ` | |
| package main | |
| func main() {} | |
| ` | |
| // The linker used to crash if an ELF input file had multiple text sections | |
| // with the same name. | |
| func TestSectionsWithSameName(t *testing.T) { | |
| testenv.MustHaveGoBuild(t) | |
| testenv.MustHaveCGO(t) | |
| t.Parallel() | |
| objcopy, err := exec.LookPath("objcopy") | |
| if err != nil { | |
| t.Skipf("can't find objcopy: %v", err) | |
| } | |
| dir, err := ioutil.TempDir("", "go-link-TestSectionsWithSameName") | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| defer os.RemoveAll(dir) | |
| gopath := filepath.Join(dir, "GOPATH") | |
| env := append(os.Environ(), "GOPATH="+gopath) | |
| if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module elf_test\n"), 0666); err != nil { | |
| t.Fatal(err) | |
| } | |
| asmFile := filepath.Join(dir, "x.s") | |
| if err := ioutil.WriteFile(asmFile, []byte(asmSource), 0444); err != nil { | |
| t.Fatal(err) | |
| } | |
| goTool := testenv.GoToolPath(t) | |
| cmd := exec.Command(goTool, "env", "CC") | |
| cmd.Env = env | |
| ccb, err := cmd.Output() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| cc := strings.TrimSpace(string(ccb)) | |
| cmd = exec.Command(goTool, "env", "GOGCCFLAGS") | |
| cmd.Env = env | |
| cflagsb, err := cmd.Output() | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| cflags := strings.Fields(string(cflagsb)) | |
| asmObj := filepath.Join(dir, "x.o") | |
| t.Logf("%s %v -c -o %s %s", cc, cflags, asmObj, asmFile) | |
| if out, err := exec.Command(cc, append(cflags, "-c", "-o", asmObj, asmFile)...).CombinedOutput(); err != nil { | |
| t.Logf("%s", out) | |
| t.Fatal(err) | |
| } | |
| asm2Obj := filepath.Join(dir, "x2.syso") | |
| t.Logf("%s --rename-section .text2=.text1 %s %s", objcopy, asmObj, asm2Obj) | |
| if out, err := exec.Command(objcopy, "--rename-section", ".text2=.text1", asmObj, asm2Obj).CombinedOutput(); err != nil { | |
| t.Logf("%s", out) | |
| t.Fatal(err) | |
| } | |
| for _, s := range []string{asmFile, asmObj} { | |
| if err := os.Remove(s); err != nil { | |
| t.Fatal(err) | |
| } | |
| } | |
| goFile := filepath.Join(dir, "main.go") | |
| if err := ioutil.WriteFile(goFile, []byte(goSource), 0444); err != nil { | |
| t.Fatal(err) | |
| } | |
| cmd = exec.Command(goTool, "build") | |
| cmd.Dir = dir | |
| cmd.Env = env | |
| t.Logf("%s build", goTool) | |
| if out, err := cmd.CombinedOutput(); err != nil { | |
| t.Logf("%s", out) | |
| t.Fatal(err) | |
| } | |
| } |