delocate: be able to preprocess inputs. In the CMake build we did this with https://boringssl-review.googlesource.com/c/boringssl/+/44847. But in other environments delocate may need to run cpp itself. Change-Id: I429e849f6d7c566aa14e63be6c8e93f9dd6847ed Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/55306 Commit-Queue: Bob Beck <bbe@google.com> Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/util/fipstools/delocate/delocate.go b/util/fipstools/delocate/delocate.go index 9c4df04..7f4b8f5 100644 --- a/util/fipstools/delocate/delocate.go +++ b/util/fipstools/delocate/delocate.go
@@ -17,10 +17,13 @@ package main import ( + "bytes" "errors" "flag" "fmt" "os" + "os/exec" + "path/filepath" "sort" "strconv" "strings" @@ -1955,7 +1958,25 @@ return nil } -func parseInputs(inputs []inputFile) error { +// preprocess runs source through the C preprocessor. +func preprocess(cppCommand []string, path string) ([]byte, error) { + var args []string + args = append(args, cppCommand...) + args = append(args, path) + + cpp := exec.Command(args[0], args[1:]...) + cpp.Stderr = os.Stderr + var result bytes.Buffer + cpp.Stdout = &result + + if err := cpp.Run(); err != nil { + return nil, err + } + + return result.Bytes(), nil +} + +func parseInputs(inputs []inputFile, cppCommand []string) error { for i, input := range inputs { var contents string @@ -1979,7 +2000,14 @@ contents = string(c) } } else { - inBytes, err := os.ReadFile(input.path) + var inBytes []byte + var err error + + if len(cppCommand) > 0 { + inBytes, err = preprocess(cppCommand, input.path) + } else { + inBytes, err = os.ReadFile(input.path) + } if err != nil { return err } @@ -2001,12 +2029,36 @@ return nil } +// includePathFromHeaderFilePath returns an include directory path based on the +// path of a specific header file. It walks up the path and assumes that the +// include files are rooted in a directory called "openssl". +func includePathFromHeaderFilePath(path string) (string, error) { + dir := path + for { + var file string + dir, file = filepath.Split(dir) + + if file == "openssl" { + return dir, nil + } + + if len(dir) == 0 { + break + } + dir = dir[:len(dir)-1] + } + + return "", fmt.Errorf("failed to find 'openssl' path element in header file path %q", path) +} + func main() { // The .a file, if given, is expected to be an archive of textual // assembly sources. That's odd, but CMake really wants to create // archive files so it's the only way that we can make it work. arInput := flag.String("a", "", "Path to a .a file containing assembly sources") outFile := flag.String("o", "", "Path to output assembly") + ccPath := flag.String("cc", "", "Path to the C compiler for preprocessing inputs") + ccFlags := flag.String("cc-flags", "", "Flags for the C compiler when preprocessing") flag.Parse() @@ -2024,18 +2076,52 @@ }) } + includePaths := make(map[string]struct{}) + for i, path := range flag.Args() { if len(path) == 0 { continue } + // Header files are not processed but their path is remembered + // and passed as -I arguments when invoking the preprocessor. + if strings.HasSuffix(path, ".h") { + dir, err := includePathFromHeaderFilePath(path) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + includePaths[dir] = struct{}{} + continue + } + inputs = append(inputs, inputFile{ path: path, index: i + 1, }) } - if err := parseInputs(inputs); err != nil { + var cppCommand []string + if len(*ccPath) > 0 { + cppCommand = append(cppCommand, *ccPath) + cppCommand = append(cppCommand, strings.Fields(*ccFlags)...) + // Some of ccFlags might be superfluous when running the + // preprocessor, but we don't want the compiler complaining that + // "argument unused during compilation". + cppCommand = append(cppCommand, "-Wno-unused-command-line-argument") + // We are preprocessing for assembly output and need to simulate that + // environment for arm_arch.h. + cppCommand = append(cppCommand, "-D__ASSEMBLER__=1") + + for includePath := range includePaths { + cppCommand = append(cppCommand, "-I"+includePath) + } + + // -E requests only preprocessing. + cppCommand = append(cppCommand, "-E") + } + + if err := parseInputs(inputs, cppCommand); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) }
diff --git a/util/fipstools/delocate/delocate_test.go b/util/fipstools/delocate/delocate_test.go index 5176c3c..082b3aa 100644 --- a/util/fipstools/delocate/delocate_test.go +++ b/util/fipstools/delocate/delocate_test.go
@@ -65,7 +65,7 @@ }) } - if err := parseInputs(inputs); err != nil { + if err := parseInputs(inputs, nil); err != nil { t.Fatalf("parseInputs failed: %s", err) }