diff options
author | Than McIntosh <thanm@google.com> | 2024-03-13 19:03:43 +0000 |
---|---|---|
committer | Than McIntosh <thanm@google.com> | 2024-04-22 13:29:54 +0000 |
commit | 2dddc7ef881669276c96356ec44c4e46ec20b1e9 (patch) | |
tree | 01c84bf6e5a2c56ed33aa3eb4251ed207fc504ea /src/cmd/link/internal/ld/elf_test.go | |
parent | 7f76c00fc5678fa782708ba8fece63750cb89d03 (diff) | |
download | go-2dddc7ef881669276c96356ec44c4e46ec20b1e9.tar.gz go-2dddc7ef881669276c96356ec44c4e46ec20b1e9.zip |
cmd/link: move .dynamic and .got sections to relro if applicable
This is the second of two CLs to roll forward the changes in CL
473495, which was subsequently reverted.
In this patch we move the .dynamic and .got sections from the writable
data segment to the relro segment if the platform supports relro and
we're producing a PIE binary, and also moves .got.plt into relro if
eager binding is in effect (e.g. -bindnow or -Wl,-z,now).
Updates #45681.
Change-Id: I9f4fba6e825b96d1b5e27fb75844450dd0a650b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/571417
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/link/internal/ld/elf_test.go')
-rw-r--r-- | src/cmd/link/internal/ld/elf_test.go | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/src/cmd/link/internal/ld/elf_test.go b/src/cmd/link/internal/ld/elf_test.go index 16bf4039b1..b48cf66038 100644 --- a/src/cmd/link/internal/ld/elf_test.go +++ b/src/cmd/link/internal/ld/elf_test.go @@ -198,6 +198,7 @@ func TestElfBindNow(t *testing.T) { name string args []string prog string + wantSecsRO []string mustHaveBuildModePIE bool mustHaveCGO bool mustInternalLink bool @@ -213,6 +214,7 @@ func TestElfBindNow(t *testing.T) { mustHaveBuildModePIE: true, mustInternalLink: true, wantDf1Pie: true, + wantSecsRO: []string{".dynamic", ".got"}, }, { name: "bindnow-linkmode-internal", @@ -232,6 +234,7 @@ func TestElfBindNow(t *testing.T) { wantDfBindNow: true, wantDf1Now: true, wantDf1Pie: true, + wantSecsRO: []string{".dynamic", ".got", ".got.plt"}, }, { name: "bindnow-pie-linkmode-external", @@ -242,6 +245,8 @@ func TestElfBindNow(t *testing.T) { wantDfBindNow: true, wantDf1Now: true, wantDf1Pie: true, + // NB: external linker produces .plt.got, not .got.plt + wantSecsRO: []string{".dynamic", ".got"}, }, } @@ -251,10 +256,14 @@ func TestElfBindNow(t *testing.T) { return true } } - return false } + segContainsSec := func(p *elf.Prog, s *elf.Section) bool { + return s.Addr >= p.Vaddr && + s.Addr+s.FileSize <= p.Vaddr+p.Filesz + } + for _, test := range tests { t.Run(test.name, func(t *testing.T) { if test.mustInternalLink { @@ -329,6 +338,53 @@ func TestElfBindNow(t *testing.T) { if gotDf1Pie := gotDynFlag(flags1, uint64(elf.DF_1_PIE)); gotDf1Pie != test.wantDf1Pie { t.Fatalf("DT_FLAGS_1 DF_1_PIE got: %v, want: %v", gotDf1Pie, test.wantDf1Pie) } + + for _, wsroname := range test.wantSecsRO { + // Locate section of interest. + var wsro *elf.Section + for _, s := range elfFile.Sections { + if s.Name == wsroname { + wsro = s + break + } + } + if wsro == nil { + t.Fatalf("test %s: can't locate %q section", + test.name, wsroname) + } + + // Now walk the program headers. Section should be part of + // some segment that is readonly. + foundRO := false + foundSegs := []*elf.Prog{} + for _, p := range elfFile.Progs { + if segContainsSec(p, wsro) { + foundSegs = append(foundSegs, p) + if p.Flags == elf.PF_R { + foundRO = true + } + } + } + if !foundRO { + // Things went off the rails. Write out some + // useful information for a human looking at the + // test failure. + t.Logf("test %s: %q section not in readonly segment", + wsro.Name, test.name) + t.Logf("section %s location: st=0x%x en=0x%x\n", + wsro.Name, wsro.Addr, wsro.Addr+wsro.FileSize) + t.Logf("sec %s found in these segments: ", wsro.Name) + for _, p := range foundSegs { + t.Logf(" %q", p.Type) + } + t.Logf("\nall segments: \n") + for k, p := range elfFile.Progs { + t.Logf("%d t=%s fl=%s st=0x%x en=0x%x\n", + k, p.Type, p.Flags, p.Vaddr, p.Vaddr+p.Filesz) + } + t.Fatalf("test %s failed", test.name) + } + } }) } } |