components/golang/patches/0056-release-branch.go1.5-cmd-go-fix-Go-buildid-reading-o.patch
changeset 5331 9c955076ffe3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/golang/patches/0056-release-branch.go1.5-cmd-go-fix-Go-buildid-reading-o.patch	Thu Jan 21 09:20:59 2016 -0800
@@ -0,0 +1,134 @@
+From 61e1caee5b3a79f8986248541839eb15d311a3a9 Mon Sep 17 00:00:00 2001
+From: Shawn Walker-Salas <[email protected]>
+Date: Wed, 26 Aug 2015 15:24:41 -0700
+Subject: [PATCH 56/63] [release-branch.go1.5] cmd/go: fix Go buildid reading
+ on Solaris
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+TestNoteReading fails on Solaris with linkmode=external due to some
+assumptions made about how ELF .note sections are written by some
+linkers.
+
+On current versions of Solaris and older derivatives, SHF_ALLOC is
+intentionally ignored for .note sections unless the .note section is
+assigned to the text segment via a mapfile.  Also, if .note sections
+are assigned to the text segment, no PT_NOTE program header will be
+created thwarting Go's attempts at attempting to quickly find the
+.note.
+
+Furthermore, Go assumes that the relevant note segment will be placed
+early in the file while the Solaris linker currently places the note
+segment last in the file, additionally thwarting Go's optimisation
+attempts that read only the first 16KB of the file to find the
+buildid.
+
+The fix is to detect when the note section is outside of the first
+16KB of the file and then fallback to additionally reading that
+section of the file.  This way, in future versions of Solaris when
+this linking behaviour is changed, the fast path will always succeed
+and we'll only be slower if it fails; likewise, any other linker that
+does this will also just work.
+
+Fixes #12178
+
+Change-Id: I61c1dc3f744ae3ad63938386d2ace8a432c0efe1
+Reviewed-on: https://go-review.googlesource.com/14210
+Run-TryBot: Aram Hăvărneanu <[email protected]>
+Reviewed-by: Aram Hăvărneanu <[email protected]>
+Reviewed-on: https://go-review.googlesource.com/17142
+Run-TryBot: Russ Cox <[email protected]>
+Reviewed-by: Russ Cox <[email protected]>
+---
+ src/cmd/go/note.go              | 32 ++++++++++++++++++++++++++------
+ src/cmd/go/note_test.go         |  3 ---
+ 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 f8d6588..c7346a5 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 a5ecab1..39b79c5 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 c9a5c99..9dedb0e 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
+-- 
+2.6.1
+