return elfnote(sh, startva, resoff, n, true)
}
+func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
+ n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(buildid)), 4))
+ return elfnote(sh, startva, resoff, n, true)
+}
+
func elfwritebuildinfo() int {
sh := elfwritenotehdr(".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
if sh == nil {
return int(sh.size)
}
+func elfwritegobuildid() int {
+ sh := elfwritenotehdr(".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(buildid)), ELF_NOTE_GOBUILDID_TAG)
+ if sh == nil {
+ return 0
+ }
+
+ Cwrite(ELF_NOTE_GO_NAME)
+ Cwrite([]byte(buildid))
+ var zero = make([]byte, 4)
+ Cwrite(zero[:int(Rnd(int64(len(buildid)), 4)-int64(len(buildid)))])
+
+ return int(sh.size)
+}
+
// Go specific notes
const (
ELF_NOTE_GOPKGLIST_TAG = 1
ELF_NOTE_GOABIHASH_TAG = 2
ELF_NOTE_GODEPS_TAG = 3
+ ELF_NOTE_GOBUILDID_TAG = 4
)
var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
if len(buildinfo) > 0 {
Addstring(shstrtab, ".note.gnu.build-id")
}
+ if buildid != "" {
+ Addstring(shstrtab, ".note.go.buildid")
+ }
Addstring(shstrtab, ".elfdata")
Addstring(shstrtab, ".rodata")
Addstring(shstrtab, ".typelink")
Addstring(shstrtab, ".note.go.pkg-list")
Addstring(shstrtab, ".note.go.deps")
}
+
+ if buildid != "" {
+ Addstring(shstrtab, ".note.go.buildid")
+ }
}
hasinitarr := Linkshared
}
addgonote(".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
}
+
+ if Linkmode == LinkExternal && buildid != "" {
+ addgonote(".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(buildid))
+ }
}
// Do not write DT_NULL. elfdynhash will finish it.
sh = elfshname(".note.go.deps")
sh.type_ = SHT_NOTE
}
+
+ if buildid != "" {
+ sh := elfshname(".note.go.buildid")
+ sh.type_ = SHT_NOTE
+ sh.flags = SHF_ALLOC
+ }
+
goto elfobj
}
phsh(pnote, sh)
}
+ if buildid != "" {
+ sh := elfshname(".note.go.buildid")
+ resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
+
+ pnote := newElfPhdr()
+ pnote.type_ = PT_NOTE
+ pnote.flags = PF_R
+ phsh(pnote, sh)
+ }
+
// Additions to the reserved area must be above this line.
elfphload(&Segtext)
if len(buildinfo) > 0 {
a += int64(elfwritebuildinfo())
}
+ if buildid != "" {
+ a += int64(elfwritegobuildid())
+ }
}
if a > elfreserve {
"strings"
)
-var pkglistfornote []byte
-
-// Reading object files.
+var (
+ pkglistfornote []byte
+ buildid string
+)
func Ldmain() {
Ctxt = linknew(Thelinkarch)
obj.Flagfn1("X", "set the value of a string variable; the next two arguments are its name and value", addstrdata1)
obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
obj.Flagcount("a", "disassemble output", &Debug['a'])
+ obj.Flagstr("buildid", "record `id` as Go toolchain build id", &buildid)
flag.Var(&Buildmode, "buildmode", "set build `mode`")
obj.Flagcount("c", "dump call graph", &Debug['c'])
obj.Flagcount("d", "disable dynamic executable", &Debug['d'])