From 8558beec7bc555a3e8d7f5cf05ba847354e992f4 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sun, 11 Dec 2016 15:05:31 -0500 Subject: [PATCH] Add apply_patches function and initial patches These patches are for two issues: * Enabling Go to build on Alpine by disabling PIC per: https://github.com/golang/go/issues/6940 https://github.com/docker-library/golang/blob/master/1.7/alpine/no-pic.patch * Fixing Go 1.4 bug appearing on macOS 10.12.1 per: https://github.com/golang/go/issues/16352#issuecomment-255835099 --- patches/alpine/README.txt | 6 + patches/alpine/go1.4/no-pic.patch | 15 ++ patches/alpine/go1.5/no-pic.patch | 15 ++ patches/alpine/go1.6/no-pic.patch | 16 ++ patches/alpine/go1.7/no-pic.patch | 16 ++ patches/alpine/go1.8/no-pic.patch | 16 ++ patches/go1.4/release-branch.patch | 327 ++++++++++++++++++++++++++ patches/go1.7/TestLoadFixed-fix.patch | 34 +++ scripts/install | 31 +++ 9 files changed, 476 insertions(+) create mode 100644 patches/alpine/README.txt create mode 100644 patches/alpine/go1.4/no-pic.patch create mode 100644 patches/alpine/go1.5/no-pic.patch create mode 100644 patches/alpine/go1.6/no-pic.patch create mode 100644 patches/alpine/go1.7/no-pic.patch create mode 100644 patches/alpine/go1.8/no-pic.patch create mode 100644 patches/go1.4/release-branch.patch create mode 100644 patches/go1.7/TestLoadFixed-fix.patch diff --git a/patches/alpine/README.txt b/patches/alpine/README.txt new file mode 100644 index 00000000..721793ce --- /dev/null +++ b/patches/alpine/README.txt @@ -0,0 +1,6 @@ +All no-pic patches were based upon: +https://raw.githubusercontent.com/docker-library/golang/master/1.6/alpine/no-pic.patch +https://raw.githubusercontent.com/docker-library/golang/master/1.7/alpine/no-pic.patch + +go1.4/no-pic.patch was hand-crafted from the above, based upon: +https://go.googlesource.com/go/+/go1.4.3/src/cmd/ld/lib.c diff --git a/patches/alpine/go1.4/no-pic.patch b/patches/alpine/go1.4/no-pic.patch new file mode 100644 index 00000000..8b99892d --- /dev/null +++ b/patches/alpine/go1.4/no-pic.patch @@ -0,0 +1,15 @@ +diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c +--- a/src/cmd/ld/lib.c ++++ b/src/cmd/ld/lib.c +@@ -692,6 +692,11 @@ hostlink(void) { + p = strchr(p + 1, ' '); + } + ++ // The Go linker does not currently support building PIE ++ // executables when using the external linker. See: ++ // https://github.com/golang/go/issues/6940 ++ argv[argc++] = "-fno-PIC"; ++ + argv[argc] = nil; + + quotefmtinstall(); diff --git a/patches/alpine/go1.5/no-pic.patch b/patches/alpine/go1.5/no-pic.patch new file mode 100644 index 00000000..82ba80b1 --- /dev/null +++ b/patches/alpine/go1.5/no-pic.patch @@ -0,0 +1,15 @@ +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1071,6 +1071,11 @@ func hostlink() { + argv = append(argv, peimporteddlls()...) + } + ++ // The Go linker does not currently support building PIE ++ // executables when using the external linker. See: ++ // https://github.com/golang/go/issues/6940 ++ argv = append(argv, "-fno-PIC") ++ + if Debug['v'] != 0 { + fmt.Fprintf(&Bso, "host link:") + for _, v := range argv { diff --git a/patches/alpine/go1.6/no-pic.patch b/patches/alpine/go1.6/no-pic.patch new file mode 100644 index 00000000..db1f809d --- /dev/null +++ b/patches/alpine/go1.6/no-pic.patch @@ -0,0 +1,16 @@ +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index 8ccbec9dd634..4e96bfadc260 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1194,6 +1194,11 @@ func hostlink() { + argv = append(argv, peimporteddlls()...) + } + ++ // The Go linker does not currently support building PIE ++ // executables when using the external linker. See: ++ // https://github.com/golang/go/issues/6940 ++ argv = append(argv, "-fno-PIC") ++ + if Debug['v'] != 0 { + fmt.Fprintf(&Bso, "host link:") + for _, v := range argv { diff --git a/patches/alpine/go1.7/no-pic.patch b/patches/alpine/go1.7/no-pic.patch new file mode 100644 index 00000000..b10f2905 --- /dev/null +++ b/patches/alpine/go1.7/no-pic.patch @@ -0,0 +1,16 @@ +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index 14f4fa9..5599307 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1272,6 +1272,11 @@ func hostlink() { + argv = append(argv, peimporteddlls()...) + } + ++ // The Go linker does not currently support building PIE ++ // executables when using the external linker. See: ++ // https://github.com/golang/go/issues/6940 ++ argv = append(argv, "-fno-PIC") ++ + if Debug['v'] != 0 { + fmt.Fprintf(Bso, "host link:") + for _, v := range argv { diff --git a/patches/alpine/go1.8/no-pic.patch b/patches/alpine/go1.8/no-pic.patch new file mode 100644 index 00000000..b10f2905 --- /dev/null +++ b/patches/alpine/go1.8/no-pic.patch @@ -0,0 +1,16 @@ +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index 14f4fa9..5599307 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -1272,6 +1272,11 @@ func hostlink() { + argv = append(argv, peimporteddlls()...) + } + ++ // The Go linker does not currently support building PIE ++ // executables when using the external linker. See: ++ // https://github.com/golang/go/issues/6940 ++ argv = append(argv, "-fno-PIC") ++ + if Debug['v'] != 0 { + fmt.Fprintf(Bso, "host link:") + for _, v := range argv { diff --git a/patches/go1.4/release-branch.patch b/patches/go1.4/release-branch.patch new file mode 100644 index 00000000..941f3ee6 --- /dev/null +++ b/patches/go1.4/release-branch.patch @@ -0,0 +1,327 @@ +This was generated via: + + git clone https://go.googlesource.com/go archive/go + cd archive/go + git diff go1.4.3..origin/release-branch.go1.4 > + ../../patches/release-branch.go1.4.patch + +The branch tip was: 79d85a4965ea7c46db483314c3981751909d7883 +from October 14, 2016. + +The diff for the VERSION file was removed. + +This is most needed to build a bootstrap Go version 1.4.3 on macOS 10.12.1 per: +https://github.com/golang/go/issues/16352#issuecomment-255835099 +diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c +index 18b5aa3119..2e9d339aef 100644 +--- a/src/cmd/6l/asm.c ++++ b/src/cmd/6l/asm.c +@@ -118,6 +118,8 @@ adddynrel(LSym *s, Reloc *r) + return; + + case 256 + R_X86_64_GOTPCREL: ++ case 256 + R_X86_64_GOTPCRELX: ++ case 256 + R_X86_64_REX_GOTPCRELX: + if(targ->type != SDYNIMPORT) { + // have symbol + if(r->off >= 2 && s->p[r->off-2] == 0x8b) { +diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c +index 98c0424037..cff29488e8 100644 +--- a/src/cmd/8l/asm.c ++++ b/src/cmd/8l/asm.c +@@ -115,6 +115,7 @@ adddynrel(LSym *s, Reloc *r) + return; + + case 256 + R_386_GOT32: ++ case 256 + R_386_GOT32X: + if(targ->type != SDYNIMPORT) { + // have symbol + if(r->off >= 2 && s->p[r->off-2] == 0x8b) { +diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go +index ed5613edd2..202106b805 100644 +--- a/src/cmd/api/run.go ++++ b/src/cmd/api/run.go +@@ -33,6 +33,10 @@ const goToolsVersion = "6698ca2900e2" + var goroot string + + func main() { ++ // Go 1.4 will never have new API, and the code below has bit-rotted. ++ fmt.Println("Skipping cmd/api checks") ++ return ++ + log.SetFlags(0) + goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat} + if goroot == "" { +diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h +index e84d996f25..e909a828d1 100644 +--- a/src/cmd/ld/elf.h ++++ b/src/cmd/ld/elf.h +@@ -502,8 +502,9 @@ typedef struct { + #define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ + #define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ + #define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +- +-#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ ++#define R_X86_64_GOTPCRELX 41 ++#define R_X86_64_REX_GOTPCRELX 42 ++#define R_X86_64_COUNT 26 /* Count of defined relocation types. */ + + + #define R_ALPHA_NONE 0 /* No reloc */ +@@ -612,8 +613,9 @@ typedef struct { + #define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ + #define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ + #define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ ++#define R_386_GOT32X 43 + +-#define R_386_COUNT 38 /* Count of defined relocation types. */ ++#define R_386_COUNT 39 /* Count of defined relocation types. */ + + #define R_PPC_NONE 0 /* No relocation. */ + #define R_PPC_ADDR32 1 +diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c +index dd5fa0d2a8..2e2fbd1737 100644 +--- a/src/cmd/ld/ldelf.c ++++ b/src/cmd/ld/ldelf.c +@@ -888,12 +888,15 @@ reltype(char *pn, int elftype, uchar *siz) + case R('6', R_X86_64_PC32): + case R('6', R_X86_64_PLT32): + case R('6', R_X86_64_GOTPCREL): ++ case R('6', R_X86_64_GOTPCRELX): ++ case R('6', R_X86_64_REX_GOTPCRELX): + case R('8', R_386_32): + case R('8', R_386_PC32): + case R('8', R_386_GOT32): + case R('8', R_386_PLT32): + case R('8', R_386_GOTOFF): + case R('8', R_386_GOTPC): ++ case R('8', R_386_GOT32X): + *siz = 4; + break; + case R('6', R_X86_64_64): +diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s +index a961c71a83..3ae60eb8cc 100644 +--- a/src/runtime/sys_darwin_386.s ++++ b/src/runtime/sys_darwin_386.s +@@ -182,11 +182,17 @@ timeloop: + + systime: + // Fall back to system call (usually first call in this thread) +- LEAL 12(SP), AX // must be non-nil, unused ++ LEAL 16(SP), AX // must be non-nil, unused + MOVL AX, 4(SP) + MOVL $0, 8(SP) // time zone pointer ++ MOVL $0, 12(SP) // required as of Sierra; Issue 16570 + MOVL $116, AX + INT $0x80 ++ CMPL AX, $0 ++ JNE inreg ++ MOVL 16(SP), AX ++ MOVL 20(SP), DX ++inreg: + // sec is in AX, usec in DX + // convert to DX:AX nsec + MOVL DX, BX +diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s +index bd397d72a7..fe9f38490f 100644 +--- a/src/runtime/sys_darwin_amd64.s ++++ b/src/runtime/sys_darwin_amd64.s +@@ -141,10 +141,16 @@ timeloop: + + systime: + // Fall back to system call (usually first call in this thread). +- MOVQ SP, DI // must be non-nil, unused ++ MOVQ SP, DI + MOVQ $0, SI ++ MOVQ $0, DX // required as of Sierra; Issue 16570 + MOVL $(0x2000000+116), AX + SYSCALL ++ CMPQ AX, $0 ++ JNE inreg ++ MOVQ 0(SP), AX ++ MOVL 8(SP), DX ++inreg: + // sec is in AX, usec in DX + // return nsec in AX + IMULQ $1000000000, AX +diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s +index 0f6d4bbb5e..f9dec7597c 100644 +--- a/src/runtime/sys_linux_386.s ++++ b/src/runtime/sys_linux_386.s +@@ -379,9 +379,18 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 + #define SEG_NOT_PRESENT 0x20 + #define USEABLE 0x40 + ++// `-1` means the kernel will pick a TLS entry on the first setldt call, ++// which happens during runtime init, and that we'll store back the saved ++// entry and reuse that on subsequent calls when creating new threads. ++DATA runtime·tls_entry_number+0(SB)/4, $-1 ++GLOBL runtime·tls_entry_number(SB), NOPTR, $4 ++ + // setldt(int entry, int address, int limit) ++// We use set_thread_area, which mucks with the GDT, instead of modify_ldt, ++// which would modify the LDT, but is disabled on some kernels. ++// The name, setldt, is a misnomer, although we leave this name as it is for ++// the compatibility with other platforms. + TEXT runtime·setldt(SB),NOSPLIT,$32 +- MOVL entry+0(FP), BX // entry + MOVL address+4(FP), CX // base address + + /* +@@ -400,18 +409,19 @@ TEXT runtime·setldt(SB),NOSPLIT,$32 + ADDL $0x8, CX // address + MOVL CX, 0(CX) + ++ // get entry number ++ MOVL runtime·tls_entry_number(SB), DX ++ + // set up user_desc + LEAL 16(SP), AX // struct user_desc +- MOVL BX, 0(AX) +- MOVL CX, 4(AX) +- MOVL $0xfffff, 8(AX) ++ MOVL DX, 0(AX) // unsigned int entry_number ++ MOVL CX, 4(AX) // unsigned long base_addr ++ MOVL $0xfffff, 8(AX) // unsigned int limit + MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits + +- // call modify_ldt +- MOVL $1, BX // func = 1 (write) +- MOVL AX, CX // user_desc +- MOVL $16, DX // sizeof(user_desc) +- MOVL $123, AX // syscall - modify_ldt ++ // call set_thread_area ++ MOVL AX, BX // user_desc ++ MOVL $243, AX // syscall - set_thread_area + CALL *runtime·_vdso(SB) + + // breakpoint on error +@@ -419,10 +429,18 @@ TEXT runtime·setldt(SB),NOSPLIT,$32 + JLS 2(PC) + INT $3 + +- // compute segment selector - (entry*8+7) +- MOVL entry+0(FP), AX ++ // read allocated entry number back out of user_desc ++ LEAL 16(SP), AX // get our user_desc back ++ MOVL 0(AX), AX ++ ++ // store entry number if the kernel allocated it ++ CMPL DX, $-1 ++ JNE 2(PC) ++ MOVL AX, runtime·tls_entry_number(SB) ++ ++ // compute segment selector - (entry*8+3) + SHLL $3, AX +- ADDL $7, AX ++ ADDL $3, AX + MOVW AX, GS + + RET +diff --git a/src/syscall/syscall_darwin_386.go b/src/syscall/syscall_darwin_386.go +index 2074e7ac2e..f75de000bd 100644 +--- a/src/syscall/syscall_darwin_386.go ++++ b/src/syscall/syscall_darwin_386.go +@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) { + } + + //sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error) +-func Gettimeofday(tv *Timeval) (err error) { +- // The tv passed to gettimeofday must be non-nil +- // but is otherwise unused. The answers come back +- // in the two registers. ++func Gettimeofday(tv *Timeval) error { ++ // The tv passed to gettimeofday must be non-nil. ++ // Before macOS Sierra (10.12), tv was otherwise unused and ++ // the answers came back in the two registers. ++ // As of Sierra, gettimeofday return zeros and populates ++ // tv itself. + sec, usec, err := gettimeofday(tv) +- tv.Sec = int32(sec) +- tv.Usec = int32(usec) +- return err ++ if err != nil { ++ return err ++ } ++ if sec != 0 || usec != 0 { ++ tv.Sec = int32(sec) ++ tv.Usec = int32(usec) ++ } ++ return nil + } + + func SetKevent(k *Kevent_t, fd, mode, flags int) { +diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go +index 81b1fd3d2b..711d08d2ff 100644 +--- a/src/syscall/syscall_darwin_amd64.go ++++ b/src/syscall/syscall_darwin_amd64.go +@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) { + } + + //sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error) +-func Gettimeofday(tv *Timeval) (err error) { +- // The tv passed to gettimeofday must be non-nil +- // but is otherwise unused. The answers come back +- // in the two registers. ++func Gettimeofday(tv *Timeval) error { ++ // The tv passed to gettimeofday must be non-nil. ++ // Before macOS Sierra (10.12), tv was otherwise unused and ++ // the answers came back in the two registers. ++ // As of Sierra, gettimeofday return zeros and populates ++ // tv itself. + sec, usec, err := gettimeofday(tv) +- tv.Sec = sec +- tv.Usec = usec +- return err ++ if err != nil { ++ return err ++ } ++ if sec != 0 || usec != 0 { ++ tv.Sec = sec ++ tv.Usec = usec ++ } ++ return nil + } + + func SetKevent(k *Kevent_t, fd, mode, flags int) { +diff --git a/src/syscall/syscall_darwin_test.go b/src/syscall/syscall_darwin_test.go +new file mode 100644 +index 0000000000..dd0e32b968 +--- /dev/null ++++ b/src/syscall/syscall_darwin_test.go +@@ -0,0 +1,23 @@ ++// Copyright 2016 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// +build darwin ++// +build amd64 386 ++ ++package syscall_test ++ ++import ( ++ "syscall" ++ "testing" ++) ++ ++func TestDarwinGettimeofday(t *testing.T) { ++ tv := &syscall.Timeval{} ++ if err := syscall.Gettimeofday(tv); err != nil { ++ t.Fatal(err) ++ } ++ if tv.Sec == 0 && tv.Usec == 0 { ++ t.Fatal("Sec and Usec both zero") ++ } ++} +diff --git a/src/time/time_test.go b/src/time/time_test.go +index 7e31dd78a9..b438817608 100644 +--- a/src/time/time_test.go ++++ b/src/time/time_test.go +@@ -915,6 +915,7 @@ func TestCountMallocs(t *testing.T) { + } + + func TestLoadFixed(t *testing.T) { ++ t.Skip("skipping test for Go 1.4; Issue 17545") + // Issue 4064: handle locations without any zone transitions. + loc, err := LoadLocation("Etc/GMT+1") + if err != nil { diff --git a/patches/go1.7/TestLoadFixed-fix.patch b/patches/go1.7/TestLoadFixed-fix.patch new file mode 100644 index 00000000..cb76fd26 --- /dev/null +++ b/patches/go1.7/TestLoadFixed-fix.patch @@ -0,0 +1,34 @@ +See: https://github.com/golang/go/issues/17276 + +commit c5434f2973a87acff76bac359236e690d632ce95 +Author: Alberto Donizetti +Date: Thu Sep 29 13:59:10 2016 +0200 + + time: update test for tzdata-2016g + + Fixes #17276 + + Change-Id: I0188cf9bc5fdb48c71ad929cc54206d03e0b96e4 + Reviewed-on: https://go-review.googlesource.com/29995 + Reviewed-by: Brad Fitzpatrick + Run-TryBot: Brad Fitzpatrick + TryBot-Result: Gobot Gobot + +diff --git a/src/time/time_test.go b/src/time/time_test.go +index 68236fd64d..2e47d0819d 100644 +--- a/src/time/time_test.go ++++ b/src/time/time_test.go +@@ -943,8 +943,11 @@ func TestLoadFixed(t *testing.T) { + // but Go and most other systems use "east is positive". + // So GMT+1 corresponds to -3600 in the Go zone, not +3600. + name, offset := Now().In(loc).Zone() +- if name != "GMT+1" || offset != -1*60*60 { +- t.Errorf("Now().In(loc).Zone() = %q, %d, want %q, %d", name, offset, "GMT+1", -1*60*60) ++ // The zone abbreviation is "-01" since tzdata-2016g, and "GMT+1" ++ // on earlier versions; we accept both. (Issue #17276). ++ if !(name == "GMT+1" || name == "-01") || offset != -1*60*60 { ++ t.Errorf("Now().In(loc).Zone() = %q, %d, want %q or %q, %d", ++ name, offset, "GMT+1", "-01", -1*60*60) + } + } + diff --git a/scripts/install b/scripts/install index 4397398c..0712fd5f 100755 --- a/scripts/install +++ b/scripts/install @@ -92,6 +92,36 @@ compile_go() { (rm -rf "$GO_INSTALL_ROOT" && display_fatal "Failed to compile. Check the logs at $GVM_ROOT/logs/go-$GO_NAME-compile.log") } +apply_patches() { + cd "$GO_INSTALL_ROOT/src" || + display_fatal "Couldn't cd into $GO_INSTALL_ROOT/src" + + minor_version="${VERSION:0:5}" + patch_dir="$GVM_ROOT/patches" + patches=() + + for patch_file in ${patch_dir}/${minor_version}/*.patch; do + if [ "$patch_file" != "${patch_dir}/${minor_version}*.patch" ]; then + patches+=("$patch_file") + fi + done + + if [ -f "/etc/apk/repositories" ]; then + patch_file="${patch_dir}/alpine/${minor_version}/no-pic.patch" + if [ -f "$patch_file" ]; then + patches+=("$patch_file") + fi + fi + + for patch_file in "${patches[@]}"; do + display_message "Applying $patch_file..." + if ! patch -p2 <"$patch_file"; then + display_error "Failed to apply $patch_file" + return + fi + done +} + create_enviroment() { new_env_file=$GVM_ROOT/environments/$GO_NAME echo "export GVM_ROOT; GVM_ROOT=\"$GVM_ROOT\"" > "$new_env_file" @@ -145,6 +175,7 @@ install_go() { create_global_package_set copy_source + apply_patches compile_go create_enviroment