mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: don't update offset of existing ELF section name
Fixes #76656 Change-Id: If2e823ba1577700af00f5883e4ea5c139e4749c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/726100 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Michael Stapelberg <stapelberg@google.com> Auto-Submit: Ian Lance Taylor <iant@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
509ddf3868
commit
32a9804c7b
2 changed files with 77 additions and 3 deletions
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"cmd/internal/hash"
|
"cmd/internal/hash"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/platform"
|
"internal/platform"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
|
|
@ -22,6 +23,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getCCAndCCFLAGS(t *testing.T, env []string) (string, []string) {
|
func getCCAndCCFLAGS(t *testing.T, env []string) (string, []string) {
|
||||||
|
|
@ -677,12 +679,23 @@ func testFlagDError(t *testing.T, dataAddr string, roundQuantum string, expected
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestELFHeadersSorted(t *testing.T) {
|
func TestELFHeadersSorted(t *testing.T) {
|
||||||
|
for _, buildmode := range []string{"exe", "pie"} {
|
||||||
|
t.Run(buildmode, func(t *testing.T) {
|
||||||
|
testELFHeadersSorted(t, buildmode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testELFHeadersSorted(t *testing.T, buildmode string) {
|
||||||
testenv.MustHaveGoBuild(t)
|
testenv.MustHaveGoBuild(t)
|
||||||
|
|
||||||
// We can only test this for internal linking mode.
|
// We can only test this for internal linking mode.
|
||||||
// For external linking the external linker will
|
// For external linking the external linker will
|
||||||
// decide how to sort the sections.
|
// decide how to sort the sections.
|
||||||
testenv.MustInternalLink(t, testenv.NoSpecialBuildTypes)
|
testenv.MustInternalLink(t, testenv.NoSpecialBuildTypes)
|
||||||
|
if buildmode == "pie" {
|
||||||
|
testenv.MustInternalLinkPIE(t)
|
||||||
|
}
|
||||||
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
@ -693,12 +706,71 @@ func TestELFHeadersSorted(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exe := filepath.Join(tmpdir, "x.exe")
|
exe := filepath.Join(tmpdir, "x.exe")
|
||||||
cmd := goCmd(t, "build", "-ldflags=-linkmode=internal", "-o", exe, src)
|
cmd := goCmd(t, "build", "-buildmode="+buildmode, "-ldflags=-linkmode=internal", "-o", exe, src)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
t.Fatalf("build failed: %v, output:\n%s", err, out)
|
t.Fatalf("build failed: %v, output:\n%s", err, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
ef, err := elf.Open(exe)
|
// Check that the first section header is all zeroes.
|
||||||
|
f, err := os.Open(exe)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var ident [elf.EI_NIDENT]byte
|
||||||
|
if _, err := f.Read(ident[:]); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bo binary.ByteOrder
|
||||||
|
switch elf.Data(ident[elf.EI_DATA]) {
|
||||||
|
case elf.ELFDATA2LSB:
|
||||||
|
bo = binary.LittleEndian
|
||||||
|
case elf.ELFDATA2MSB:
|
||||||
|
bo = binary.BigEndian
|
||||||
|
default:
|
||||||
|
t.Fatalf("unrecognized data encoding %d", ident[elf.EI_DATA])
|
||||||
|
}
|
||||||
|
|
||||||
|
var shoff int64
|
||||||
|
var shsize int
|
||||||
|
switch elf.Class(ident[elf.EI_CLASS]) {
|
||||||
|
case elf.ELFCLASS32:
|
||||||
|
var hdr elf.Header32
|
||||||
|
data := make([]byte, unsafe.Sizeof(hdr))
|
||||||
|
if _, err := f.ReadAt(data, 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
shoff = int64(bo.Uint32(data[unsafe.Offsetof(hdr.Shoff):]))
|
||||||
|
shsize = int(unsafe.Sizeof(elf.Section32{}))
|
||||||
|
|
||||||
|
case elf.ELFCLASS64:
|
||||||
|
var hdr elf.Header64
|
||||||
|
data := make([]byte, unsafe.Sizeof(hdr))
|
||||||
|
if _, err := f.ReadAt(data, 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
shoff = int64(bo.Uint64(data[unsafe.Offsetof(hdr.Shoff):]))
|
||||||
|
shsize = int(unsafe.Sizeof(elf.Section64{}))
|
||||||
|
|
||||||
|
default:
|
||||||
|
t.Fatalf("unrecognized class %d", ident[elf.EI_CLASS])
|
||||||
|
}
|
||||||
|
|
||||||
|
if shoff > 0 {
|
||||||
|
data := make([]byte, shsize)
|
||||||
|
if _, err := f.ReadAt(data, shoff); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, c := range data {
|
||||||
|
if c != 0 {
|
||||||
|
t.Errorf("section header 0 byte %d is %d, should be zero", i, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ef, err := elf.NewFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,9 @@ func elfWriteShstrtab(ctxt *Link) uint32 {
|
||||||
// are likely to be the only match.
|
// are likely to be the only match.
|
||||||
for _, sh := range shdr {
|
for _, sh := range shdr {
|
||||||
if suffix, ok := strings.CutPrefix(sh.nameString, elfRelType); ok {
|
if suffix, ok := strings.CutPrefix(sh.nameString, elfRelType); ok {
|
||||||
m[suffix] = off + uint32(len(elfRelType))
|
if _, found := m[suffix]; !found {
|
||||||
|
m[suffix] = off + uint32(len(elfRelType))
|
||||||
|
}
|
||||||
writeString(sh.nameString)
|
writeString(sh.nameString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue