aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link
diff options
context:
space:
mode:
authorMeng Zhuo <mzh@golangcn.org>2021-03-30 19:58:35 +0800
committerMeng Zhuo <mzh@golangcn.org>2021-11-29 00:58:50 +0000
commit1ea4d3b91164fb08b7022958b6cd8e290f12e017 (patch)
treeee0b3d919d6246ee5d5a6c495a49eeed90308a37 /src/cmd/link
parent78af02e8b5c5c9d3c6d5026fd72f57026a14952a (diff)
downloadgo-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.go55
-rw-r--r--src/cmd/link/internal/ld/elf.go39
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.