return int(sh.Size)
}
-func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int) int {
- n := 3*4 + uint64(sz) + resoff%4
+func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sizes ...int) int {
+ n := resoff % 4
+ // if section contains multiple notes (as is the case with FreeBSD signature),
+ // multiple note sizes can be specified
+ for _, sz := range sizes {
+ n += 3*4 + uint64(sz)
+ }
sh.Type = uint32(elf.SHT_NOTE)
sh.Flags = uint64(elf.SHF_ALLOC)
return int(sh.Size)
}
+// FreeBSD Signature (as per sys/elf_common.h)
+const (
+ ELF_NOTE_FREEBSD_NAMESZ = 8
+ ELF_NOTE_FREEBSD_DESCSZ = 4
+ ELF_NOTE_FREEBSD_ABI_TAG = 1
+ ELF_NOTE_FREEBSD_NOINIT_TAG = 2
+ ELF_NOTE_FREEBSD_FEATURE_CTL_TAG = 4
+ ELF_NOTE_FREEBSD_VERSION = 1203000 // 12.3-RELEASE
+ ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE = 0x1
+)
+
+const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00"
+
+func elffreebsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
+ n := ELF_NOTE_FREEBSD_NAMESZ + ELF_NOTE_FREEBSD_DESCSZ
+ // FreeBSD signature section contains 3 equally sized notes
+ return elfnote(sh, startva, resoff, n, n, n)
+}
+
+// elfwritefreebsdsig writes FreeBSD .note section.
+//
+// See https://www.netbsd.org/docs/kernel/elf-notes.html for the description of
+// a Note element format and
+// https://github.com/freebsd/freebsd-src/blob/main/sys/sys/elf_common.h#L790
+// for the FreeBSD-specific values.
+func elfwritefreebsdsig(out *OutBuf) int {
+ sh := elfshname(".note.tag")
+ if sh == nil {
+ return 0
+ }
+ out.SeekSet(int64(sh.Off))
+
+ // NT_FREEBSD_ABI_TAG
+ out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
+ out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
+ out.Write32(ELF_NOTE_FREEBSD_ABI_TAG)
+ out.WriteString(ELF_NOTE_FREEBSD_NAME)
+ out.Write32(ELF_NOTE_FREEBSD_VERSION)
+
+ // NT_FREEBSD_NOINIT_TAG
+ out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
+ out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
+ out.Write32(ELF_NOTE_FREEBSD_NOINIT_TAG)
+ out.WriteString(ELF_NOTE_FREEBSD_NAME)
+ out.Write32(0)
+
+ // NT_FREEBSD_FEATURE_CTL
+ out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
+ out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
+ out.Write32(ELF_NOTE_FREEBSD_FEATURE_CTL_TAG)
+ out.WriteString(ELF_NOTE_FREEBSD_NAME)
+ if *flagRace {
+ // The race detector can't handle ASLR, turn the ASLR off when compiling with -race.
+ out.Write32(ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE)
+ } else {
+ out.Write32(0)
+ }
+
+ return int(sh.Size)
+}
+
func addbuildinfo(val string) {
if !strings.HasPrefix(val, "0x") {
Exitf("-B argument must start with 0x: %s", val)
if ctxt.IsOpenbsd() {
shstrtab.Addstring(".note.openbsd.ident")
}
+ if ctxt.IsFreebsd() {
+ shstrtab.Addstring(".note.tag")
+ }
if len(buildinfo) > 0 {
shstrtab.Addstring(".note.gnu.build-id")
}
phsh(ph, sh)
}
- if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd {
+ if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd {
var sh *ElfShdr
switch ctxt.HeadType {
case objabi.Hnetbsd:
case objabi.Hopenbsd:
sh = elfshname(".note.openbsd.ident")
resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
+
+ case objabi.Hfreebsd:
+ sh = elfshname(".note.tag")
+ resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff)))
}
- // netbsd and openbsd require ident in an independent segment.
+ // NetBSD, OpenBSD and FreeBSD require ident in an independent segment.
pnotei := newElfPhdr()
pnotei.Type = elf.PT_NOTE
pnotei.Flags = elf.PF_R
if ctxt.HeadType == objabi.Hopenbsd {
a += int64(elfwriteopenbsdsig(ctxt.Out))
}
+ if ctxt.HeadType == objabi.Hfreebsd {
+ a += int64(elfwritefreebsdsig(ctxt.Out))
+ }
if len(buildinfo) > 0 {
a += int64(elfwritebuildinfo(ctxt.Out))
}