diff options
author | Meng Zhuo <mzh@golangcn.org> | 2021-03-30 19:58:35 +0800 |
---|---|---|
committer | Meng Zhuo <mzh@golangcn.org> | 2021-11-29 00:58:50 +0000 |
commit | 1ea4d3b91164fb08b7022958b6cd8e290f12e017 (patch) | |
tree | ee0b3d919d6246ee5d5a6c495a49eeed90308a37 /src/cmd/link | |
parent | 78af02e8b5c5c9d3c6d5026fd72f57026a14952a (diff) | |
download | go-1ea4d3b91164fb08b7022958b6cd8e290f12e017.tar.gz go-1ea4d3b91164fb08b7022958b6cd8e290f12e017.zip |
cmd/link: merge note sections into one segment
The ld from binutils merges note sections into one PT_NOTE
segment.
We should do that for consistency with binutils.
Change-Id: I45703525c720972d49c36c4f10ac47d1628b5698
Reviewed-on: https://go-review.googlesource.com/c/go/+/265957
Trust: Meng Zhuo <mzh@golangcn.org>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Meng Zhuo <mzh@golangcn.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/link')
-rw-r--r-- | src/cmd/link/elf_test.go | 55 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/elf.go | 39 |
2 files changed, 71 insertions, 23 deletions
diff --git a/src/cmd/link/elf_test.go b/src/cmd/link/elf_test.go index 012c0b5169..760d9ea60d 100644 --- a/src/cmd/link/elf_test.go +++ b/src/cmd/link/elf_test.go @@ -201,6 +201,61 @@ func TestMinusRSymsWithSameName(t *testing.T) { } } +func TestMergeNoteSections(t *testing.T) { + testenv.MustHaveGoBuild(t) + expected := 1 + + switch runtime.GOOS { + case "linux", "freebsd", "dragonfly": + case "openbsd", "netbsd": + // These OSes require independent segment + expected = 2 + default: + t.Skip("We should only test on elf output.") + } + t.Parallel() + + goFile := filepath.Join(t.TempDir(), "notes.go") + if err := ioutil.WriteFile(goFile, []byte(goSource), 0444); err != nil { + t.Fatal(err) + } + outFile := filepath.Join(t.TempDir(), "notes.exe") + goTool := testenv.GoToolPath(t) + // sha1sum of "gopher" + id := "0xf4e8cd51ce8bae2996dc3b74639cdeaa1f7fee5f" + cmd := exec.Command(goTool, "build", "-o", outFile, "-ldflags", + "-B "+id, goFile) + cmd.Dir = t.TempDir() + if out, err := cmd.CombinedOutput(); err != nil { + t.Logf("%s", out) + t.Fatal(err) + } + + ef, err := elf.Open(outFile) + if err != nil { + t.Fatalf("open elf file failed:%v", err) + } + defer ef.Close() + sec := ef.Section(".note.gnu.build-id") + if sec == nil { + t.Fatalf("can't find gnu build id") + } + + sec = ef.Section(".note.go.buildid") + if sec == nil { + t.Fatalf("can't find go build id") + } + cnt := 0 + for _, ph := range ef.Progs { + if ph.Type == elf.PT_NOTE { + cnt += 1 + } + } + if cnt != expected { + t.Fatalf("want %d PT_NOTE segment, got %d", expected, cnt) + } +} + const pieSourceTemplate = ` package main diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index fb75c761a1..4a143dfcaa 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -1682,13 +1682,18 @@ func asmbElf(ctxt *Link) { var pph *ElfPhdr var pnote *ElfPhdr + getpnote := func() *ElfPhdr { + if pnote == nil { + pnote = newElfPhdr() + pnote.Type = elf.PT_NOTE + pnote.Flags = elf.PF_R + } + return pnote + } if *flagRace && ctxt.IsNetbsd() { sh := elfshname(".note.netbsd.pax") resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff))) - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + phsh(getpnote(), sh) } if ctxt.LinkMode == LinkExternal { /* skip program headers */ @@ -1787,7 +1792,6 @@ func asmbElf(ctxt *Link) { phsh(ph, sh) } - pnote = nil if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd { var sh *ElfShdr switch ctxt.HeadType { @@ -1799,34 +1803,23 @@ func asmbElf(ctxt *Link) { sh = elfshname(".note.openbsd.ident") resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff))) } - - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + // netbsd and openbsd require ident in an independent segment. + pnotei := newElfPhdr() + pnotei.Type = elf.PT_NOTE + pnotei.Flags = elf.PF_R + phsh(pnotei, sh) } if len(buildinfo) > 0 { sh := elfshname(".note.gnu.build-id") resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff))) - - if pnote == nil { - pnote = newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - } - - phsh(pnote, sh) + phsh(getpnote(), sh) } if *flagBuildid != "" { sh := elfshname(".note.go.buildid") resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff))) - - pnote := newElfPhdr() - pnote.Type = elf.PT_NOTE - pnote.Flags = elf.PF_R - phsh(pnote, sh) + phsh(getpnote(), sh) } // Additions to the reserved area must be above this line. |