Commit ac1f48e2 authored by Russ Cox's avatar Russ Cox

cmd/link: add -buildid flag to write Go build ID to ELF output, same as cmd/compile

Other binary formats to follow.

Using our own note instead of the GNU build ID note because
we are not the GNU project, and I can't guarantee that the semantics
of our note and the semantics of the GNU note will match forever.
(Also they don't match today.)

For #11048.

Change-Id: Iec7e5a2e49d52b6d3a51b0aface2de7c77a45491
Reviewed-on: https://go-review.googlesource.com/10706Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent a2c50ece
......@@ -1189,6 +1189,11 @@ func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
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 {
......@@ -1203,11 +1208,26 @@ func elfwritebuildinfo() int {
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")
......@@ -1663,6 +1683,9 @@ func doelf() {
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")
......@@ -1702,6 +1725,10 @@ func doelf() {
Addstring(shstrtab, ".note.go.pkg-list")
Addstring(shstrtab, ".note.go.deps")
}
if buildid != "" {
Addstring(shstrtab, ".note.go.buildid")
}
}
hasinitarr := Linkshared
......@@ -1914,6 +1941,10 @@ func doelf() {
}
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.
......@@ -1988,6 +2019,13 @@ func Asmbelf(symo int64) {
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
}
......@@ -2084,6 +2122,16 @@ func Asmbelf(symo int64) {
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)
......@@ -2395,6 +2443,9 @@ elfobj:
if len(buildinfo) > 0 {
a += int64(elfwritebuildinfo())
}
if buildid != "" {
a += int64(elfwritegobuildid())
}
}
if a > elfreserve {
......
......@@ -38,9 +38,10 @@ import (
"strings"
)
var pkglistfornote []byte
// Reading object files.
var (
pkglistfornote []byte
buildid string
)
func Ldmain() {
Ctxt = linknew(Thelinkarch)
......@@ -104,6 +105,7 @@ func Ldmain() {
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'])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment