diff options
-rw-r--r-- | src/cmd/go/note.go | 32 | ||||
-rw-r--r-- | src/cmd/go/note_test.go | 3 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/elf.go | 4 |
3 files changed, 26 insertions, 13 deletions
diff --git a/src/cmd/go/note.go b/src/cmd/go/note.go index f8d6588b73..c7346a5731 100644 --- a/src/cmd/go/note.go +++ b/src/cmd/go/note.go @@ -70,11 +70,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. @@ -96,11 +96,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 a5ecab17ed..39b79c5cfd 100644 --- a/src/cmd/go/note_test.go +++ b/src/cmd/go/note_test.go @@ -50,9 +50,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 c9a5c99c34..9dedb0eabe 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -1739,10 +1739,6 @@ func doelf() { Addstring(shstrtab, ".note.go.pkg-list") Addstring(shstrtab, ".note.go.deps") } - - if buildid != "" { - Addstring(shstrtab, ".note.go.buildid") - } } hasinitarr := Linkshared |