* marshal a 32-bit representation from the 64-bit structure.
*/
-var Elfstrdat []byte
+var elfstrdat, elfshstrdat []byte
/*
* Total amount of space to reserve at the start of the file
ldr := ctxt.loader
/* predefine strings we need for section headers */
- shstrtab := ldr.CreateSymForUpdate(".shstrtab", 0)
- shstrtab.SetType(sym.SELFROSECT)
+ addshstr := func(s string) int {
+ off := len(elfshstrdat)
+ elfshstrdat = append(elfshstrdat, s...)
+ elfshstrdat = append(elfshstrdat, 0)
+ return off
+ }
shstrtabAddstring := func(s string) {
- off := shstrtab.Addstring(s)
+ off := addshstr(s)
elfsetstring(ctxt, 0, s, int(off))
}
func asmbElf(ctxt *Link) {
var symo int64
- if !*FlagS {
- symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
- symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
+ symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
+ symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
+ ctxt.Out.SeekSet(symo)
+ if *FlagS {
+ ctxt.Out.Write(elfshstrdat)
+ } else {
ctxt.Out.SeekSet(symo)
asmElfSym(ctxt)
- ctxt.Out.Write(Elfstrdat)
+ ctxt.Out.Write(elfstrdat)
+ ctxt.Out.Write(elfshstrdat)
if ctxt.IsExternal() {
elfEmitReloc(ctxt)
}
elfobj:
sh := elfshname(".shstrtab")
- sh.Type = uint32(elf.SHT_STRTAB)
- sh.Addralign = 1
- shsym(sh, ldr, ldr.Lookup(".shstrtab", 0))
eh.Shstrndx = uint16(sh.shnum)
if ctxt.IsMIPS() {
elfshname(".symtab")
elfshname(".strtab")
}
+ elfshname(".shstrtab")
for _, sect := range Segtext.Sections {
elfshbits(ctxt.LinkMode, sect)
sh.Flags = 0
}
+ var shstroff uint64
if !*FlagS {
sh := elfshname(".symtab")
sh.Type = uint32(elf.SHT_SYMTAB)
sh = elfshname(".strtab")
sh.Type = uint32(elf.SHT_STRTAB)
sh.Off = uint64(symo) + uint64(symSize)
- sh.Size = uint64(len(Elfstrdat))
+ sh.Size = uint64(len(elfstrdat))
sh.Addralign = 1
+ shstroff = sh.Off + sh.Size
+ } else {
+ shstroff = uint64(symo)
}
+ sh = elfshname(".shstrtab")
+ sh.Type = uint32(elf.SHT_STRTAB)
+ sh.Off = shstroff
+ sh.Size = uint64(len(elfshstrdat))
+ sh.Addralign = 1
+
/* Main header */
copy(eh.Ident[:], elf.ELFMAG)
t.Errorf("Got %d entries for `libc.so`, want %d", got, want)
}
}
+
+func TestShStrTabAttributesIssue62600(t *testing.T) {
+ t.Parallel()
+ testenv.MustHaveGoBuild(t)
+ dir := t.TempDir()
+
+ const prog = `
+package main
+
+func main() {
+ println("whee")
+}
+`
+ src := filepath.Join(dir, "issue62600.go")
+ if err := os.WriteFile(src, []byte(prog), 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ binFile := filepath.Join(dir, "issue62600")
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", binFile, src)
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
+ }
+
+ fi, err := os.Open(binFile)
+ if err != nil {
+ t.Fatalf("failed to open built file: %v", err)
+ }
+ defer fi.Close()
+
+ elfFile, err := elf.NewFile(fi)
+ if err != nil {
+ t.Skip("The system may not support ELF, skipped.")
+ }
+
+ section := elfFile.Section(".shstrtab")
+ if section == nil {
+ t.Fatal("no .shstrtab")
+ }
+
+ // The .shstrtab section should have a zero address, non-zero
+ // size, no ALLOC flag, and the offset should not fall into any of
+ // the segments defined by the program headers.
+ if section.Addr != 0 {
+ t.Fatalf("expected Addr == 0 for .shstrtab got %x", section.Addr)
+ }
+ if section.Size == 0 {
+ t.Fatal("expected nonzero Size for .shstrtab got 0")
+ }
+ if section.Flags&elf.SHF_ALLOC != 0 {
+ t.Fatal("expected zero alloc flag got nonzero for .shstrtab")
+ }
+ for idx, p := range elfFile.Progs {
+ if section.Offset >= p.Off && section.Offset < p.Off+p.Filesz {
+ t.Fatalf("badly formed .shstrtab, is contained in segment %d", idx)
+ }
+ }
+}
// Symbol table.
func putelfstr(s string) int {
- if len(Elfstrdat) == 0 && s != "" {
+ if len(elfstrdat) == 0 && s != "" {
// first entry must be empty string
putelfstr("")
}
- off := len(Elfstrdat)
- Elfstrdat = append(Elfstrdat, s...)
- Elfstrdat = append(Elfstrdat, 0)
+ off := len(elfstrdat)
+ elfstrdat = append(elfstrdat, s...)
+ elfstrdat = append(elfstrdat, 0)
return off
}