Use Go modules with delocate. This makes running go test, etc., in util/fipstools/delocate work! This adds a go_executable command to CMake like: go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate) which internally gets dependencies and whatnot so it behaves like usual Go. Update-Note: delocate has been rearranged a bit. Change-Id: I244a7317dd8d4f2ab77a0daa624ed3e0b385faef Reviewed-on: https://boringssl-review.googlesource.com/31885 Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt index c614a65..1586d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -334,6 +334,43 @@ add_definitions(-DOPENSSL_SMALL) endif() +function(go_executable dest package) + set(godeps "${CMAKE_SOURCE_DIR}/util/godeps.go") + if(${CMAKE_VERSION} VERSION_LESS "3.7" OR + NOT ${CMAKE_GENERATOR} STREQUAL "Ninja") + # The DEPFILE parameter to add_custom_command is new as of CMake 3.7 and + # only works with Ninja. Query the sources at configure time. Additionally, + # everything depends on go.mod. That affects what external packages to use. + execute_process(COMMAND ${GO_EXECUTABLE} run ${godeps} -format cmake + -pkg ${package} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE sources + RESULT_VARIABLE godeps_result) + add_custom_command(OUTPUT ${dest} + COMMAND ${GO_EXECUTABLE} build + -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${sources} ${CMAKE_SOURCE_DIR}/go.mod) + else() + # Ninja expects the target in the depfile to match the output. This is a + # relative path from the build directory. + string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length) + math(EXPR root_dir_length "${root_dir_length} + 1") + string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target) + set(target "${target}/${dest}") + + set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d") + add_custom_command(OUTPUT ${dest} + COMMAND ${GO_EXECUTABLE} build + -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package} + COMMAND ${GO_EXECUTABLE} run ${godeps} -format depfile + -target ${target} -pkg ${package} -out ${depfile} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${godeps} ${CMAKE_SOURCE_DIR}/go.mod + DEPFILE ${depfile}) + endif() +endfunction() + # CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an # architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR # alone, and expects all architecture-specific logic to be conditioned within
diff --git a/crypto/fipsmodule/CMakeLists.txt b/crypto/fipsmodule/CMakeLists.txt index 1242aa2..9868dd8 100644 --- a/crypto/fipsmodule/CMakeLists.txt +++ b/crypto/fipsmodule/CMakeLists.txt
@@ -141,21 +141,12 @@ set_target_properties(bcm_c_generated_asm PROPERTIES COMPILE_OPTIONS "-S") set_target_properties(bcm_c_generated_asm PROPERTIES POSITION_INDEPENDENT_CODE ON) - function(prepend_path values prefix output) - set(result) - foreach(value ${values}) - list(APPEND result "${prefix}/${value}") - endforeach(value) - set(${output} ${result} PARENT_SCOPE) - endfunction() - - prepend_path("${BCM_ASM_SOURCES}" "${CMAKE_CURRENT_BINARY_DIR}" DELOCATE_ASM_ARGS) - + go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate) add_custom_command( OUTPUT bcm-delocated.S - COMMAND ${GO_EXECUTABLE} run util/fipstools/delocate.go util/fipstools/delocate.peg.go util/fipstools/ar.go util/fipstools/const.go -a $<TARGET_FILE:bcm_c_generated_asm> -o ${CMAKE_CURRENT_BINARY_DIR}/bcm-delocated.S ${DELOCATE_ASM_ARGS} - DEPENDS bcm_c_generated_asm ${BCM_ASM_SOURCES} ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.go ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.peg.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ./delocate -a $<TARGET_FILE:bcm_c_generated_asm> -o bcm-delocated.S ${BCM_ASM_SOURCES} + DEPENDS bcm_c_generated_asm delocate ${BCM_ASM_SOURCES} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) add_library( @@ -171,11 +162,13 @@ set_target_properties(bcm_hashunset PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(bcm_hashunset PROPERTIES LINKER_LANGUAGE C) + go_executable(inject-hash + boringssl.googlesource.com/boringssl/util/fipstools/inject-hash) add_custom_command( OUTPUT bcm.o - COMMAND ${GO_EXECUTABLE} run util/fipstools/inject-hash.go util/fipstools/ar.go util/fipstools/const.go -o ${CMAKE_CURRENT_BINARY_DIR}/bcm.o -in-archive $<TARGET_FILE:bcm_hashunset> - DEPENDS bcm_hashunset ${CMAKE_SOURCE_DIR}/util/fipstools/inject-hash.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ./inject-hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset> + DEPENDS bcm_hashunset inject-hash + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) # The outputs of add_custom_command cannot be referenced outside of the
diff --git a/util/fipstools/delocate.go b/util/fipstools/delocate/delocate.go similarity index 99% rename from util/fipstools/delocate.go rename to util/fipstools/delocate/delocate.go index d58e5be..a8c4fd0 100644 --- a/util/fipstools/delocate.go +++ b/util/fipstools/delocate/delocate.go
@@ -25,6 +25,8 @@ "sort" "strconv" "strings" + + "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon" ) // inputFile represents a textual assembly file. @@ -1405,7 +1407,7 @@ w.WriteString(".type BORINGSSL_bcm_text_hash, @object\n") w.WriteString(".size BORINGSSL_bcm_text_hash, 64\n") w.WriteString("BORINGSSL_bcm_text_hash:\n") - for _, b := range uninitHashValue { + for _, b := range fipscommon.UninitHashValue { w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n") } @@ -1423,7 +1425,7 @@ } defer arFile.Close() - ar, err := ParseAR(arFile) + ar, err := fipscommon.ParseAR(arFile) if err != nil { return err }
diff --git a/util/fipstools/delocate.peg b/util/fipstools/delocate/delocate.peg similarity index 100% rename from util/fipstools/delocate.peg rename to util/fipstools/delocate/delocate.peg
diff --git a/util/fipstools/delocate.peg.go b/util/fipstools/delocate/delocate.peg.go similarity index 100% rename from util/fipstools/delocate.peg.go rename to util/fipstools/delocate/delocate.peg.go
diff --git a/util/fipstools/delocate_test.go b/util/fipstools/delocate/delocate_test.go similarity index 100% rename from util/fipstools/delocate_test.go rename to util/fipstools/delocate/delocate_test.go
diff --git a/util/fipstools/testdata/ppc64le-GlobalEntry/in.s b/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s similarity index 100% rename from util/fipstools/testdata/ppc64le-GlobalEntry/in.s rename to util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s
diff --git a/util/fipstools/testdata/ppc64le-GlobalEntry/out.s b/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s similarity index 100% rename from util/fipstools/testdata/ppc64le-GlobalEntry/out.s rename to util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s
diff --git a/util/fipstools/testdata/ppc64le-LoadToR0/in.s b/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s similarity index 100% rename from util/fipstools/testdata/ppc64le-LoadToR0/in.s rename to util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s
diff --git a/util/fipstools/testdata/ppc64le-LoadToR0/out.s b/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s similarity index 100% rename from util/fipstools/testdata/ppc64le-LoadToR0/out.s rename to util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s
diff --git a/util/fipstools/testdata/ppc64le-Sample/in.s b/util/fipstools/delocate/testdata/ppc64le-Sample/in.s similarity index 100% rename from util/fipstools/testdata/ppc64le-Sample/in.s rename to util/fipstools/delocate/testdata/ppc64le-Sample/in.s
diff --git a/util/fipstools/testdata/ppc64le-Sample/out.s b/util/fipstools/delocate/testdata/ppc64le-Sample/out.s similarity index 100% rename from util/fipstools/testdata/ppc64le-Sample/out.s rename to util/fipstools/delocate/testdata/ppc64le-Sample/out.s
diff --git a/util/fipstools/testdata/ppc64le-Sample2/in.s b/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s similarity index 100% rename from util/fipstools/testdata/ppc64le-Sample2/in.s rename to util/fipstools/delocate/testdata/ppc64le-Sample2/in.s
diff --git a/util/fipstools/testdata/ppc64le-Sample2/out.s b/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s similarity index 100% rename from util/fipstools/testdata/ppc64le-Sample2/out.s rename to util/fipstools/delocate/testdata/ppc64le-Sample2/out.s
diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s b/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s similarity index 100% rename from util/fipstools/testdata/ppc64le-TOCWithOffset/in.s rename to util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s
diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s b/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s similarity index 100% rename from util/fipstools/testdata/ppc64le-TOCWithOffset/out.s rename to util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s
diff --git a/util/fipstools/testdata/x86_64-BSS/in.s b/util/fipstools/delocate/testdata/x86_64-BSS/in.s similarity index 100% rename from util/fipstools/testdata/x86_64-BSS/in.s rename to util/fipstools/delocate/testdata/x86_64-BSS/in.s
diff --git a/util/fipstools/testdata/x86_64-BSS/out.s b/util/fipstools/delocate/testdata/x86_64-BSS/out.s similarity index 100% rename from util/fipstools/testdata/x86_64-BSS/out.s rename to util/fipstools/delocate/testdata/x86_64-BSS/out.s
diff --git a/util/fipstools/testdata/x86_64-Basic/in.s b/util/fipstools/delocate/testdata/x86_64-Basic/in.s similarity index 100% rename from util/fipstools/testdata/x86_64-Basic/in.s rename to util/fipstools/delocate/testdata/x86_64-Basic/in.s
diff --git a/util/fipstools/testdata/x86_64-Basic/out.s b/util/fipstools/delocate/testdata/x86_64-Basic/out.s similarity index 100% rename from util/fipstools/testdata/x86_64-Basic/out.s rename to util/fipstools/delocate/testdata/x86_64-Basic/out.s
diff --git a/util/fipstools/testdata/x86_64-GOTRewrite/in.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s similarity index 100% rename from util/fipstools/testdata/x86_64-GOTRewrite/in.s rename to util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
diff --git a/util/fipstools/testdata/x86_64-GOTRewrite/out.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s similarity index 100% rename from util/fipstools/testdata/x86_64-GOTRewrite/out.s rename to util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/in1.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s similarity index 100% rename from util/fipstools/testdata/x86_64-LabelRewrite/in1.s rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/in2.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s similarity index 100% rename from util/fipstools/testdata/x86_64-LabelRewrite/in2.s rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/out.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s similarity index 100% rename from util/fipstools/testdata/x86_64-LabelRewrite/out.s rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
diff --git a/util/fipstools/testdata/x86_64-Sections/in.s b/util/fipstools/delocate/testdata/x86_64-Sections/in.s similarity index 100% rename from util/fipstools/testdata/x86_64-Sections/in.s rename to util/fipstools/delocate/testdata/x86_64-Sections/in.s
diff --git a/util/fipstools/testdata/x86_64-Sections/out.s b/util/fipstools/delocate/testdata/x86_64-Sections/out.s similarity index 100% rename from util/fipstools/testdata/x86_64-Sections/out.s rename to util/fipstools/delocate/testdata/x86_64-Sections/out.s
diff --git a/util/fipstools/ar.go b/util/fipstools/fipscommon/ar.go similarity index 99% rename from util/fipstools/ar.go rename to util/fipstools/fipscommon/ar.go index 51e7aa5..85b378d 100644 --- a/util/fipstools/ar.go +++ b/util/fipstools/fipscommon/ar.go
@@ -14,7 +14,7 @@ // ar.go contains functions for parsing .a archive files. -package main +package fipscommon import ( "bytes"
diff --git a/util/fipstools/const.go b/util/fipstools/fipscommon/const.go similarity index 91% rename from util/fipstools/const.go rename to util/fipstools/fipscommon/const.go index 2e009ac..5693414 100644 --- a/util/fipstools/const.go +++ b/util/fipstools/fipscommon/const.go
@@ -12,11 +12,11 @@ // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -package main +package fipscommon -// uninitHashValue is the default hash value that we inject into the module. +// UninitHashValue is the default hash value that we inject into the module. // This value need only be distinct, i.e. so that we can safely // search-and-replace it in an object file. -var uninitHashValue = [64]byte{ +var UninitHashValue = [64]byte{ 0xae, 0x2c, 0xea, 0x2a, 0xbd, 0xa6, 0xf3, 0xec, 0x97, 0x7f, 0x9b, 0xf6, 0x94, 0x9a, 0xfc, 0x83, 0x68, 0x27, 0xcb, 0xa0, 0xa0, 0x9f, 0x6b, 0x6f, 0xde, 0x52, 0xcd, 0xe2, 0xcd, 0xff, 0x31, 0x80, 0xa2, 0xd4, 0xc3, 0x66, 0x0f, 0xc2, 0x6a, 0x7b, 0xf4, 0xbe, 0x39, 0xa2, 0xd7, 0x25, 0xdb, 0x21, 0x98, 0xe9, 0xd5, 0x53, 0xbf, 0x5c, 0x32, 0x06, 0x83, 0x34, 0x0c, 0x65, 0x89, 0x52, 0xbd, 0x1f, }
diff --git a/util/fipstools/inject-hash.go b/util/fipstools/inject-hash/inject-hash.go similarity index 94% rename from util/fipstools/inject-hash.go rename to util/fipstools/inject-hash/inject-hash.go index 688024d..14418a3 100644 --- a/util/fipstools/inject-hash.go +++ b/util/fipstools/inject-hash/inject-hash.go
@@ -28,6 +28,8 @@ "io" "io/ioutil" "os" + + "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon" ) func do(outPath, oInput string, arInput string) error { @@ -43,7 +45,7 @@ } defer arFile.Close() - ar, err := ParseAR(arFile) + ar, err := fipscommon.ParseAR(arFile) if err != nil { return err } @@ -145,12 +147,12 @@ // Replace the default hash value in the object with the calculated // value and write it out. - offset := bytes.Index(objectBytes, uninitHashValue[:]) + offset := bytes.Index(objectBytes, fipscommon.UninitHashValue[:]) if offset < 0 { return errors.New("did not find uninitialised hash value in object file") } - if bytes.Index(objectBytes[offset+1:], uninitHashValue[:]) >= 0 { + if bytes.Index(objectBytes[offset+1:], fipscommon.UninitHashValue[:]) >= 0 { return errors.New("found two occurrences of uninitialised hash value in object file") }
diff --git a/util/godeps.go b/util/godeps.go new file mode 100644 index 0000000..960faa4 --- /dev/null +++ b/util/godeps.go
@@ -0,0 +1,203 @@ +// Copyright (c) 2018, Google Inc. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// godeps prints out dependencies of a package in either CMake or Make depfile +// format, for incremental rebuilds. +// +// The depfile format is preferred. It works correctly when new files are added. +// However, CMake only supports depfiles for custom commands with Ninja and +// starting CMake 3.7. For other configurations, we also support CMake's format, +// but CMake must be rerun when file lists change. +package main + +import ( + "flag" + "fmt" + "go/build" + "os" + "path/filepath" + "sort" + "strings" +) + +var ( + format = flag.String("format", "cmake", "The format to output to, either 'cmake' or 'depfile'") + mainPkg = flag.String("pkg", "", "The package to print dependencies for") + target = flag.String("target", "", "The name of the output file") + out = flag.String("out", "", "The path to write the output to. If unset, this is stdout") +) + +func cMakeQuote(in string) string { + // See https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#quoted-argument + var b strings.Builder + b.Grow(len(in)) + // Iterate over in as bytes. + for i := 0; i < len(in); i++ { + switch c := in[i]; c { + case '\\', '"': + b.WriteByte('\\') + b.WriteByte(c) + case '\t': + b.WriteString("\\t") + case '\r': + b.WriteString("\\r") + case '\n': + b.WriteString("\\n") + default: + b.WriteByte(in[i]) + } + } + return b.String() +} + +func writeCMake(outFile *os.File, files []string) error { + for i, file := range files { + if i != 0 { + if _, err := outFile.WriteString(";"); err != nil { + return err + } + } + if _, err := outFile.WriteString(cMakeQuote(file)); err != nil { + return err + } + } + return nil +} + +func makeQuote(in string) string { + // See https://www.gnu.org/software/make/manual/make.html#Rule-Syntax + var b strings.Builder + b.Grow(len(in)) + // Iterate over in as bytes. + for i := 0; i < len(in); i++ { + switch c := in[i]; c { + case '$': + b.WriteString("$$") + case '#', '\\', ' ': + b.WriteByte('\\') + b.WriteByte(c) + default: + b.WriteByte(c) + } + } + return b.String() +} + +func writeDepfile(outFile *os.File, files []string) error { + if _, err := fmt.Fprintf(outFile, "%s:", makeQuote(*target)); err != nil { + return err + } + for _, file := range files { + if _, err := fmt.Fprintf(outFile, " %s", makeQuote(file)); err != nil { + return err + } + } + _, err := outFile.WriteString("\n") + return err +} + +func appendPrefixed(list, newFiles []string, prefix string) []string { + for _, file := range newFiles { + list = append(list, filepath.Join(prefix, file)) + } + return list +} + +func main() { + flag.Parse() + + if len(*mainPkg) == 0 { + fmt.Fprintf(os.Stderr, "-pkg argument is required.\n") + os.Exit(1) + } + + var isDepfile bool + switch *format { + case "depfile": + isDepfile = true + case "cmake": + isDepfile = false + default: + fmt.Fprintf(os.Stderr, "Unknown format: %q\n", *format) + os.Exit(1) + } + + if isDepfile && len(*target) == 0 { + fmt.Fprintf(os.Stderr, "-target argument is required for depfile.\n") + os.Exit(1) + } + + done := make(map[string]struct{}) + var files []string + var recurse func(pkgName string) error + recurse = func(pkgName string) error { + pkg, err := build.Default.Import(pkgName, ".", 0) + if err != nil { + return err + } + + // Skip standard packages. + if pkg.Goroot { + return nil + } + + // Skip already-visited packages. + if _, ok := done[pkg.Dir]; ok { + return nil + } + done[pkg.Dir] = struct{}{} + + files = appendPrefixed(files, pkg.GoFiles, pkg.Dir) + files = appendPrefixed(files, pkg.CgoFiles, pkg.Dir) + // Include ignored Go files. A subsequent change may cause them + // to no longer be ignored. + files = appendPrefixed(files, pkg.IgnoredGoFiles, pkg.Dir) + + // Recurse into imports. + for _, importName := range pkg.Imports { + if err := recurse(importName); err != nil { + return err + } + } + return nil + } + if err := recurse(*mainPkg); err != nil { + fmt.Fprintf(os.Stderr, "Error getting dependencies: %s\n", err) + os.Exit(1) + } + + sort.Strings(files) + + outFile := os.Stdout + if len(*out) != 0 { + var err error + outFile, err = os.Create(*out) + if err != nil { + fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err) + os.Exit(1) + } + defer outFile.Close() + } + + var err error + if isDepfile { + err = writeDepfile(outFile, files) + } else { + err = writeCMake(outFile, files) + } + if err != nil { + fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err) + os.Exit(1) + } +}