Skip to content

Commit 0ff3231

Browse files
cmd/link: sort allocated ELF section headers by address
For an executable, emit the allocated section headers in address order, so that section headers are easier for humans to read. Change-Id: Ib5efb4734101e4a1f6b09d0e045ed643c79c7c0a Reviewed-on: https://go-review.googlesource.com/c/go/+/718620 Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Bypass: David Chase <drchase@google.com> Reviewed-by: David Chase <drchase@google.com>
1 parent 4879151 commit 0ff3231

File tree

4 files changed

+222
-48
lines changed

4 files changed

+222
-48
lines changed

src/cmd/link/elf_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,61 @@ func testFlagDError(t *testing.T, dataAddr string, roundQuantum string, expected
678678
t.Errorf("expected error message to contain %q, got:\n%s", expectedError, out)
679679
}
680680
}
681+
682+
func TestELFHeadersSorted(t *testing.T) {
683+
testenv.MustHaveGoBuild(t)
684+
685+
// We can only test this for internal linking mode.
686+
// For external linking the external linker will
687+
// decide how to sort the sections.
688+
testenv.MustInternalLink(t, testenv.NoSpecialBuildTypes)
689+
690+
t.Parallel()
691+
692+
tmpdir := t.TempDir()
693+
src := filepath.Join(tmpdir, "x.go")
694+
if err := os.WriteFile(src, []byte(goSourceWithData), 0o444); err != nil {
695+
t.Fatal(err)
696+
}
697+
698+
exe := filepath.Join(tmpdir, "x.exe")
699+
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-toolexec", os.Args[0], "-ldflags=-linkmode=internal", "-o", exe, src)
700+
cmd = testenv.CleanCmdEnv(cmd)
701+
cmd.Env = append(cmd.Env, "LINK_TEST_TOOLEXEC=1")
702+
if out, err := cmd.CombinedOutput(); err != nil {
703+
t.Fatalf("build failed: %v, output:\n%s", err, out)
704+
}
705+
706+
ef, err := elf.Open(exe)
707+
if err != nil {
708+
t.Fatal(err)
709+
}
710+
defer ef.Close()
711+
712+
// After the first zero section header,
713+
// we should see allocated sections,
714+
// then unallocated sections.
715+
// The allocated sections should be sorted by address.
716+
i := 1
717+
lastAddr := uint64(0)
718+
for i < len(ef.Sections) {
719+
sec := ef.Sections[i]
720+
if sec.Flags&elf.SHF_ALLOC == 0 {
721+
break
722+
}
723+
if sec.Addr < lastAddr {
724+
t.Errorf("section %d %q address %#x less than previous address %#x", i, sec.Name, sec.Addr, lastAddr)
725+
}
726+
lastAddr = sec.Addr
727+
i++
728+
}
729+
730+
firstUnalc := i
731+
for i < len(ef.Sections) {
732+
sec := ef.Sections[i]
733+
if sec.Flags&elf.SHF_ALLOC != 0 {
734+
t.Errorf("allocated section %d %q follows first unallocated section %d %q", i, sec.Name, firstUnalc, ef.Sections[firstUnalc].Name)
735+
}
736+
i++
737+
}
738+
}

src/cmd/link/internal/ld/dwarf.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2428,7 +2428,7 @@ func dwarfaddelfsectionsyms(ctxt *Link) {
24282428
for _, si := range dwarfp {
24292429
s := si.secSym()
24302430
sect := ldr.SymSect(si.secSym())
2431-
putelfsectionsym(ctxt, ctxt.Out, s, sect.Elfsect.(*ElfShdr).shnum)
2431+
putelfsectionsym(ctxt, ctxt.Out, s, elfShdrShnum(sect.Elfsect.(*ElfShdr)))
24322432
}
24332433
}
24342434

0 commit comments

Comments
 (0)