diff --git a/src/cmd/go/note.go b/src/cmd/go/note.go index 97e18651e4acca..5c953c4d004e37 100644 --- a/src/cmd/go/note.go +++ b/src/cmd/go/note.go @@ -69,11 +69,11 @@ func readELFNote(filename, name string, typ int32) ([]byte, error) { var elfGoNote = []byte("Go\x00\x00") -// readELFGoBuildID the Go build ID string from an ELF binary. -// The Go build ID is stored in a note described by an ELF PT_NOTE prog header. -// The caller has already opened filename, to get f, and read the first 4 kB out, in data. +// The Go build ID is stored in a note described by an ELF PT_NOTE prog +// header. The caller has already opened filename, to get f, and read +// at least 4 kB out, in data. func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, err error) { - // Assume the note content is in the first 4 kB, already read. + // Assume the note content is in the data, already read. // Rewrite the ELF header to set shnum to 0, so that we can pass // the data to elf.NewFile and it will decode the Prog list but not // try to read the section headers and the string table from disk. @@ -95,11 +95,31 @@ func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string, return "", &os.PathError{Path: filename, Op: "parse", Err: err} } for _, p := range ef.Progs { - if p.Type != elf.PT_NOTE || p.Off >= uint64(len(data)) || p.Off+p.Filesz >= uint64(len(data)) || p.Filesz < 16 { + if p.Type != elf.PT_NOTE || p.Filesz < 16 { continue } - note := data[p.Off : p.Off+p.Filesz] + var note []byte + if p.Off+p.Filesz < uint64(len(data)) { + note = data[p.Off : p.Off+p.Filesz] + } else { + // For some linkers, such as the Solaris linker, + // the buildid may not be found in data (which + // likely contains the first 16kB of the file) + // or even the first few megabytes of the file + // due to differences in note segment placement; + // in that case, extract the note data manually. + _, err = f.Seek(int64(p.Off), 0) + if err != nil { + return "", err + } + + note = make([]byte, p.Filesz) + _, err = io.ReadFull(f, note) + if err != nil { + return "", err + } + } nameSize := ef.ByteOrder.Uint32(note) valSize := ef.ByteOrder.Uint32(note[4:]) tag := ef.ByteOrder.Uint32(note[8:]) diff --git a/src/cmd/go/note_test.go b/src/cmd/go/note_test.go index 2fcfe34d67e2ad..0764b73312eead 100644 --- a/src/cmd/go/note_test.go +++ b/src/cmd/go/note_test.go @@ -33,9 +33,6 @@ func TestNoteReading(t *testing.T) { // no external linking t.Logf("no external linking - skipping linkmode=external test") - case "solaris": - t.Logf("skipping - golang.org/issue/12178") - default: tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go")) id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe")) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 187643e41b7165..baca0326a5bc61 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -1725,10 +1725,6 @@ func doelf() { Addstring(shstrtab, ".note.go.pkg-list") Addstring(shstrtab, ".note.go.deps") } - - if buildid != "" { - Addstring(shstrtab, ".note.go.buildid") - } } hasinitarr := Linkshared