Delete unused util/* inherited from BoringSSL.

This commit is contained in:
Brian Smith 2020-11-10 18:45:26 -08:00
parent da43d82fd6
commit eb1fad6ad2
19 changed files with 0 additions and 1026 deletions

23
.gitignore vendored
View File

@ -7,29 +7,6 @@ ssl/test/runner/runner
doc/*.html
doc/doc.css
util/bot/android_ndk
util/bot/android_tools
util/bot/cmake-linux64
util/bot/cmake-linux64.tar.gz
util/bot/cmake-mac
util/bot/cmake-mac.tar.gz
util/bot/cmake-win32
util/bot/cmake-win32.zip
util/bot/golang
util/bot/gyp
util/bot/libcxx
util/bot/libcxxabi
util/bot/llvm-build
util/bot/nasm-win32.exe
util/bot/perl-win32
util/bot/perl-win32.zip
util/bot/sde-linux64
util/bot/sde-linux64.tar.bz2
util/bot/sde-win32
util/bot/sde-win32.tar.bz2
util/bot/win_toolchain.json
util/bot/yasm-win32.exe
*.bk
*.orig
*~

View File

@ -1,154 +0,0 @@
// Copyright (c) 2017, 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. */
// ar.go contains functions for parsing .a archive files.
package ar
import (
"bytes"
"errors"
"fmt"
"io"
"strconv"
"strings"
)
// ParseAR parses an archive file from r and returns a map from filename to
// contents, or else an error.
func ParseAR(r io.Reader) (map[string][]byte, error) {
// See https://en.wikipedia.org/wiki/Ar_(Unix)#File_format_details
const expectedMagic = "!<arch>\n"
var magic [len(expectedMagic)]byte
if _, err := io.ReadFull(r, magic[:]); err != nil {
return nil, err
}
if string(magic[:]) != expectedMagic {
return nil, errors.New("ar: not an archive file")
}
const filenameTableName = "//"
const symbolTableName = "/"
var longFilenameTable []byte
ret := make(map[string][]byte)
for {
var header [60]byte
if _, err := io.ReadFull(r, header[:]); err != nil {
if err == io.EOF {
break
}
return nil, errors.New("ar: error reading file header: " + err.Error())
}
name := strings.TrimRight(string(header[:16]), " ")
sizeStr := strings.TrimRight(string(header[48:58]), "\x00 ")
size, err := strconv.ParseUint(sizeStr, 10, 64)
if err != nil {
return nil, errors.New("ar: failed to parse file size: " + err.Error())
}
// File contents are padded to a multiple of two bytes
storedSize := size
if storedSize%2 == 1 {
storedSize++
}
contents := make([]byte, storedSize)
if _, err := io.ReadFull(r, contents); err != nil {
return nil, errors.New("ar: error reading file contents: " + err.Error())
}
contents = contents[:size]
switch {
case name == filenameTableName:
if longFilenameTable != nil {
return nil, errors.New("ar: two filename tables found")
}
longFilenameTable = contents
continue
case name == symbolTableName:
continue
case len(name) > 1 && name[0] == '/':
if longFilenameTable == nil {
return nil, errors.New("ar: long filename reference found before filename table")
}
// A long filename is stored as "/" followed by a
// base-10 offset in the filename table.
offset, err := strconv.ParseUint(name[1:], 10, 64)
if err != nil {
return nil, errors.New("ar: failed to parse filename offset: " + err.Error())
}
if offset > uint64((^uint(0))>>1) {
return nil, errors.New("ar: filename offset overflow")
}
if int(offset) > len(longFilenameTable) {
return nil, errors.New("ar: filename offset out of bounds")
}
filename := longFilenameTable[offset:]
// Windows terminates filenames with NUL characters,
// while sysv/GNU uses /.
if i := bytes.IndexAny(filename, "/\x00"); i < 0 {
return nil, errors.New("ar: unterminated filename in table")
} else {
filename = filename[:i]
}
name = string(filename)
default:
name = strings.TrimRight(name, "/")
}
// Post-processing for BSD:
// https://en.wikipedia.org/wiki/Ar_(Unix)#BSD_variant
//
// If the name is of the form #1/XXX, XXX identifies the length of the
// name, and the name itself is stored as a prefix of the data, possibly
// null-padded.
var namelen uint
n, err := fmt.Sscanf(name, "#1/%d", &namelen)
if err == nil && n == 1 && len(contents) >= int(namelen) {
name = string(contents[:namelen])
contents = contents[namelen:]
// Names can be null padded; find the first null (if any). Note that
// this also handles the case of a null followed by non-null
// characters. It's not clear whether those can ever show up in
// practice, but we might as well handle them in case they can show
// up.
var null int
for ; null < len(name); null++ {
if name[null] == 0 {
break
}
}
name = name[:null]
}
if name == "__.SYMDEF" || name == "__.SYMDEF SORTED" {
continue
}
ret[name] = contents
}
return ret, nil
}

View File

@ -1,118 +0,0 @@
// 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. */
package ar
import (
"bytes"
"flag"
"io/ioutil"
"os"
"path/filepath"
"testing"
)
var testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.")
type arTest struct {
name string
in string
out map[string]string
// allowPadding is true if the contents may have trailing newlines at end.
// On macOS, ar calls ranlib which pads all inputs up to eight bytes with
// newlines. Unlike ar's native padding up to two bytes, this padding is
// included in the size field, so it is not removed when decoding.
allowPadding bool
}
func (test *arTest) Path(file string) string {
return filepath.Join(*testDataDir, test.name, file)
}
func removeTrailingNewlines(in []byte) []byte {
for len(in) > 0 && in[len(in)-1] == '\n' {
in = in[:len(in)-1]
}
return in
}
var arTests = []arTest{
{
"linux",
"libsample.a",
map[string]string{
"foo.c.o": "foo.c.o",
"bar.cc.o": "bar.cc.o",
},
false,
},
{
"mac",
"libsample.a",
map[string]string{
"foo.c.o": "foo.c.o",
"bar.cc.o": "bar.cc.o",
},
true,
},
{
"windows",
"sample.lib",
map[string]string{
"CMakeFiles\\sample.dir\\foo.c.obj": "foo.c.obj",
"CMakeFiles\\sample.dir\\bar.cc.obj": "bar.cc.obj",
},
false,
},
}
func TestAR(t *testing.T) {
for _, test := range arTests {
t.Run(test.name, func(t *testing.T) {
in, err := os.Open(test.Path(test.in))
if err != nil {
t.Fatalf("opening input failed: %s", err)
}
defer in.Close()
ret, err := ParseAR(in)
if err != nil {
t.Fatalf("reading input failed: %s", err)
}
for file, contentsPath := range test.out {
expected, err := ioutil.ReadFile(test.Path(contentsPath))
if err != nil {
t.Fatalf("error reading %s: %s", contentsPath, err)
}
got, ok := ret[file]
if test.allowPadding {
got = removeTrailingNewlines(got)
expected = removeTrailingNewlines(got)
}
if !ok {
t.Errorf("file %s missing from output", file)
} else if !bytes.Equal(got, expected) {
t.Errorf("contents for file %s did not match", file)
}
}
for file, _ := range ret {
if _, ok := test.out[file]; !ok {
t.Errorf("output contained unexpected file %q", file)
}
}
})
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +0,0 @@
cmake_minimum_required(VERSION 3.0)
project(Sample)
add_library(sample STATIC foo.c bar.cc)

View File

@ -1,15 +0,0 @@
extern "C" {
void foo();
void bar() {}
}
namespace bar_namespace {
void SomeExternalFunction();
void SomeFunction() {
foo();
SomeExternalFunction();
}
} // namespace bar_namespace

View File

@ -1,7 +0,0 @@
extern void external_symbol(void);
extern void bar(void);
void foo(void) {
external_symbol();
bar();
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,152 +0,0 @@
#!/usr/bin/python
# Copyright (c) 2016, 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.
import os
import os.path
import subprocess
import sys
# The LCOV output format for each source file is:
#
# SF:<filename>
# DA:<line>,<execution count>
# ...
# end_of_record
#
# The <execution count> can either be 0 for an unexecuted instruction or a
# value representing the number of executions. The DA line should be omitted
# for lines not representing an instruction.
SECTION_SEPERATOR = '-' * 80
def is_asm(l):
"""Returns whether a line should be considered to be an instruction."""
l = l.strip()
# Empty lines
if l == '':
return False
# Comments
if l.startswith('#'):
return False
# Assembly Macros
if l.startswith('.'):
return False
# Label
if l.endswith(':'):
return False
return True
def merge(callgrind_files, srcs):
"""Calls callgrind_annotate over the set of callgrind output
|callgrind_files| using the sources |srcs| and merges the results
together."""
out = ''
for file in callgrind_files:
data = subprocess.check_output(['callgrind_annotate', file] + srcs)
out += '%s\n%s\n' % (data, SECTION_SEPERATOR)
return out
def parse(filename, data, current):
"""Parses an annotated execution flow |data| from callgrind_annotate for
source |filename| and updates the current execution counts from |current|."""
with open(filename) as f:
source = f.read().split('\n')
out = current
if out == None:
out = [0 if is_asm(l) else None for l in source]
# Lines are of the following formats:
# -- line: Indicates that analysis continues from a different place.
# Ir : Indicates the start of a file.
# => : Indicates a call/jump in the control flow.
# <Count> <Code>: Indicates that the line has been executed that many times.
line = None
for l in data:
l = l.strip() + ' '
if l.startswith('-- line'):
line = int(l.split(' ')[2]) - 1
elif l.strip() == 'Ir':
line = 0
elif line != None and l.strip() and '=>' not in l and 'unidentified lines' not in l:
count = l.split(' ')[0].replace(',', '').replace('.', '0')
instruction = l.split(' ', 1)[1].strip()
if count != '0' or is_asm(instruction):
if out[line] == None:
out[line] = 0
out[line] += int(count)
line += 1
return out
def generate(data):
"""Parses the merged callgrind_annotate output |data| and generates execution
counts for all annotated files."""
out = {}
data = [p.strip() for p in data.split(SECTION_SEPERATOR)]
# Most sections are ignored, but a section with:
# User-annotated source: <file>
# precedes a listing of execution count for that <file>.
for i in range(len(data)):
if 'User-annotated source' in data[i] and i < len(data) - 1:
filename = data[i].split(':', 1)[1].strip()
res = data[i + 1]
if filename not in out:
out[filename] = None
if 'No information' in res:
res = []
else:
res = res.split('\n')
out[filename] = parse(filename, res, out[filename])
return out
def output(data):
"""Takes a dictionary |data| of filenames and execution counts and generates
a LCOV coverage output."""
out = ''
for filename, counts in data.iteritems():
out += 'SF:%s\n' % (os.path.abspath(filename))
for line, count in enumerate(counts):
if count != None:
out += 'DA:%d,%s\n' % (line + 1, count)
out += 'end_of_record\n'
return out
if __name__ == '__main__':
if len(sys.argv) != 3:
print '%s <Callgrind Folder> <Build Folder>' % (__file__)
sys.exit()
cg_folder = sys.argv[1]
build_folder = sys.argv[2]
cg_files = []
for (cwd, _, files) in os.walk(cg_folder):
for f in files:
if f.startswith('callgrind.out'):
cg_files.append(os.path.abspath(os.path.join(cwd, f)))
srcs = []
for (cwd, _, files) in os.walk(build_folder):
for f in files:
fn = os.path.join(cwd, f)
if fn.endswith('.S'):
srcs.append(fn)
annotated = merge(cg_files, srcs)
lcov = generate(annotated)
print output(lcov)

View File

@ -1,60 +0,0 @@
#!/bin/sh
# Copyright (c) 2016, 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.
set -xe
SRC=$PWD
BUILD=$(mktemp -d '/tmp/boringssl.XXXXXX')
BUILD_SRC=$(mktemp -d '/tmp/boringssl-src.XXXXXX')
LCOV=$(mktemp -d '/tmp/boringssl-lcov.XXXXXX')
if [ -n "$1" ]; then
LCOV=$(readlink -f "$1")
mkdir -p "$LCOV"
fi
cd "$BUILD"
cmake "$SRC" -GNinja -DCMAKE_C_FLAGS='-fprofile-arcs -ftest-coverage' \
-DCMAKE_CXX_FLAGS='-fprofile-arcs -ftest-coverage' -DCMAKE_ASM_FLAGS='-Wa,-g'
ninja
cp -r "$SRC/crypto" "$SRC/decrepit" "$SRC/include" "$SRC/ssl" "$SRC/tool" \
"$BUILD_SRC"
cp -r "$BUILD"/* "$BUILD_SRC"
mkdir "$BUILD/callgrind/"
cd "$SRC"
go run "$SRC/util/all_tests.go" -build-dir "$BUILD" -callgrind -num-workers 16
util/generate-asm-lcov.py "$BUILD/callgrind" "$BUILD" > "$BUILD/asm.info"
go run "util/all_tests.go" -build-dir "$BUILD"
cd "$SRC/ssl/test/runner"
go test -shim-path "$BUILD/ssl/test/bssl_shim" -num-workers 1
cd "$LCOV"
lcov -c -d "$BUILD" -b "$BUILD" -o "$BUILD/lcov.info"
lcov -r "$BUILD/lcov.info" "*_test.c" -o "$BUILD/lcov-1.info"
lcov -r "$BUILD/lcov-1.info" "*_test.cc" -o "$BUILD/lcov-2.info"
cat "$BUILD/lcov-2.info" "$BUILD/asm.info" > "$BUILD/final.info"
sed -i "s;$BUILD;$BUILD_SRC;g" "$BUILD/final.info"
sed -i "s;$SRC;$BUILD_SRC;g" "$BUILD/final.info"
genhtml -p "$BUILD_SRC" "$BUILD/final.info"
rm -rf "$BUILD"
rm -rf "$BUILD_SRC"
xdg-open index.html

View File

@ -1,232 +0,0 @@
// 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.
// This program takes a file containing newline-separated symbols, and generates
// boringssl_prefix_symbols.h, boringssl_prefix_symbols_asm.h, and
// boringssl_prefix_symbols_nasm.inc. These header files can be used to build
// BoringSSL with a prefix for all symbols in order to avoid symbol name
// conflicts when linking a project with multiple copies of BoringSSL; see
// BUILDING.md for more details.
// TODO(joshlf): For platforms which support it, use '#pragma redefine_extname'
// instead of a custom macro. This avoids the need for a custom macro, but also
// ensures that our renaming won't conflict with symbols defined and used by our
// consumers (the "HMAC" problem). An example of this approach can be seen in
// IllumOS' fork of OpenSSL:
// https://github.com/joyent/illumos-extra/blob/master/openssl1x/sunw_prefix.h
package main
import (
"bufio"
"flag"
"fmt"
"os"
"path/filepath"
"strings"
)
var out = flag.String("out", ".", "Path to a directory where the outputs will be written")
// Read newline-separated symbols from a file, ignoring any comments started
// with '#'.
func readSymbols(path string) ([]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
var ret []string
for scanner.Scan() {
line := scanner.Text()
if idx := strings.IndexByte(line, '#'); idx >= 0 {
line = line[:idx]
}
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
ret = append(ret, line)
}
if err := scanner.Err(); err != nil {
return nil, err
}
return ret, nil
}
func writeCHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.WriteString(`// 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.
// BORINGSSL_ADD_PREFIX pastes two identifiers into one. It performs one
// iteration of macro expansion on its arguments before pasting.
#define BORINGSSL_ADD_PREFIX(a, b) BORINGSSL_ADD_PREFIX_INNER(a, b)
#define BORINGSSL_ADD_PREFIX_INNER(a, b) a ## _ ## b
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "#define %s BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil {
return err
}
}
return nil
}
func writeASMHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.WriteString(`// 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.
#if !defined(__APPLE__)
#include <boringssl_prefix_symbols.h>
#else
// On iOS and macOS, we need to treat assembly symbols differently from other
// symbols. The linker expects symbols to be prefixed with an underscore.
// Perlasm thus generates symbol with this underscore applied. Our macros must,
// in turn, incorporate it.
#define BORINGSSL_ADD_PREFIX_MAC_ASM(a, b) BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b)
#define BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b) _ ## a ## _ ## b
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "#define _%s BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil {
return err
}
}
_, err = fmt.Fprintf(f, "#endif\n")
return nil
}
func writeNASMHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
// NASM uses a different syntax from the C preprocessor.
if _, err := f.WriteString(`; 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.
; 32-bit Windows adds underscores to C functions, while 64-bit Windows does not.
%ifidn __OUTPUT_FORMAT__, win32
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "%%xdefine _%s _ %%+ BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
return err
}
}
if _, err := fmt.Fprintf(f, "%%else\n"); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "%%xdefine %s BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
return err
}
}
if _, err := fmt.Fprintf(f, "%%endif\n"); err != nil {
return err
}
return nil
}
func main() {
flag.Parse()
if flag.NArg() != 1 {
fmt.Fprintf(os.Stderr, "Usage: %s [-out OUT] SYMBOLS\n", os.Args[0])
os.Exit(1)
}
symbols, err := readSymbols(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading symbols: %s\n", err)
os.Exit(1)
}
if err := writeCHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols.h")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols.h: %s\n", err)
os.Exit(1)
}
if err := writeASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_asm.h")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_asm.h: %s\n", err)
os.Exit(1)
}
if err := writeNASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_nasm.inc")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_nasm.inc: %s\n", err)
os.Exit(1)
}
}

View File

@ -1,262 +0,0 @@
// 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.
// read_symbols scans one or more .a files and, for each object contained in
// the .a files, reads the list of symbols in that object file.
package main
import (
"bytes"
"debug/elf"
"debug/macho"
"debug/pe"
"flag"
"fmt"
"os"
"runtime"
"sort"
"strings"
"boringssl.googlesource.com/boringssl/util/ar"
)
const (
ObjFileFormatELF = "elf"
ObjFileFormatMachO = "macho"
ObjFileFormatPE = "pe"
)
var (
outFlag = flag.String("out", "-", "File to write output symbols")
objFileFormat = flag.String("obj-file-format", defaultObjFileFormat(runtime.GOOS), "Object file format to expect (options are elf, macho, pe)")
)
func defaultObjFileFormat(goos string) string {
switch goos {
case "linux":
return ObjFileFormatELF
case "darwin":
return ObjFileFormatMachO
case "windows":
return ObjFileFormatPE
default:
// By returning a value here rather than panicking, the user can still
// cross-compile from an unsupported platform to a supported platform by
// overriding this default with a flag. If the user doesn't provide the
// flag, we will panic during flag parsing.
return "unsupported"
}
}
func printAndExit(format string, args ...interface{}) {
s := fmt.Sprintf(format, args...)
fmt.Fprintln(os.Stderr, s)
os.Exit(1)
}
func main() {
flag.Parse()
if flag.NArg() < 1 {
printAndExit("Usage: %s [-out OUT] [-obj-file-format FORMAT] ARCHIVE_FILE [ARCHIVE_FILE [...]]", os.Args[0])
}
archiveFiles := flag.Args()
out := os.Stdout
if *outFlag != "-" {
var err error
out, err = os.Create(*outFlag)
if err != nil {
printAndExit("Error opening %q: %s", *outFlag, err)
}
defer out.Close()
}
var symbols []string
// Only add first instance of any symbol; keep track of them in this map.
added := make(map[string]struct{})
for _, archive := range archiveFiles {
f, err := os.Open(archive)
if err != nil {
printAndExit("Error opening %s: %s", archive, err)
}
objectFiles, err := ar.ParseAR(f)
f.Close()
if err != nil {
printAndExit("Error parsing %s: %s", archive, err)
}
for name, contents := range objectFiles {
syms, err := listSymbols(contents)
if err != nil {
printAndExit("Error listing symbols from %q in %q: %s", name, archive, err)
}
for _, s := range syms {
if _, ok := added[s]; !ok {
added[s] = struct{}{}
symbols = append(symbols, s)
}
}
}
}
sort.Strings(symbols)
for _, s := range symbols {
var skipSymbols = []string{
// Inline functions, etc., from the compiler or language
// runtime will naturally end up in the library, to be
// deduplicated against other object files. Such symbols
// should not be prefixed. It is a limitation of this
// symbol-prefixing strategy that we cannot distinguish
// our own inline symbols (which should be prefixed)
// from the system's (which should not), so we blacklist
// known system symbols.
"__local_stdio_printf_options",
"__local_stdio_scanf_options",
"_vscprintf",
"_vscprintf_l",
"_vsscanf_l",
"_xmm",
"sscanf",
"vsnprintf",
// sdallocx is a weak symbol and intended to merge with
// the real one, if present.
"sdallocx",
}
var skip bool
for _, sym := range skipSymbols {
if sym == s {
skip = true
break
}
}
if skip || isCXXSymbol(s) || strings.HasPrefix(s, "__real@") || strings.HasPrefix(s, "__x86.get_pc_thunk.") {
continue
}
if _, err := fmt.Fprintln(out, s); err != nil {
printAndExit("Error writing to %s: %s", *outFlag, err)
}
}
}
func isCXXSymbol(s string) bool {
if *objFileFormat == ObjFileFormatPE {
return strings.HasPrefix(s, "?")
}
return strings.HasPrefix(s, "_Z")
}
// listSymbols lists the exported symbols from an object file.
func listSymbols(contents []byte) ([]string, error) {
switch *objFileFormat {
case ObjFileFormatELF:
return listSymbolsELF(contents)
case ObjFileFormatMachO:
return listSymbolsMachO(contents)
case ObjFileFormatPE:
return listSymbolsPE(contents)
default:
return nil, fmt.Errorf("unsupported object file format %q", *objFileFormat)
}
}
func listSymbolsELF(contents []byte) ([]string, error) {
f, err := elf.NewFile(bytes.NewReader(contents))
if err != nil {
return nil, err
}
syms, err := f.Symbols()
if err != nil {
return nil, err
}
var names []string
for _, sym := range syms {
// Only include exported, defined symbols
if elf.ST_BIND(sym.Info) != elf.STB_LOCAL && sym.Section != elf.SHN_UNDEF {
names = append(names, sym.Name)
}
}
return names, nil
}
func listSymbolsMachO(contents []byte) ([]string, error) {
f, err := macho.NewFile(bytes.NewReader(contents))
if err != nil {
return nil, err
}
if f.Symtab == nil {
return nil, nil
}
var names []string
for _, sym := range f.Symtab.Syms {
// Source: https://opensource.apple.com/source/xnu/xnu-3789.51.2/EXTERNAL_HEADERS/mach-o/nlist.h.auto.html
const (
N_PEXT uint8 = 0x10 // Private external symbol bit
N_EXT uint8 = 0x01 // External symbol bit, set for external symbols
N_TYPE uint8 = 0x0e // mask for the type bits
N_UNDF uint8 = 0x0 // undefined, n_sect == NO_SECT
N_ABS uint8 = 0x2 // absolute, n_sect == NO_SECT
N_SECT uint8 = 0xe // defined in section number n_sect
N_PBUD uint8 = 0xc // prebound undefined (defined in a dylib)
N_INDR uint8 = 0xa // indirect
)
// Only include exported, defined symbols.
if sym.Type&N_EXT != 0 && sym.Type&N_TYPE != N_UNDF {
if len(sym.Name) == 0 || sym.Name[0] != '_' {
return nil, fmt.Errorf("unexpected symbol without underscore prefix: %q", sym.Name)
}
names = append(names, sym.Name[1:])
}
}
return names, nil
}
func listSymbolsPE(contents []byte) ([]string, error) {
f, err := pe.NewFile(bytes.NewReader(contents))
if err != nil {
return nil, err
}
var ret []string
for _, sym := range f.Symbols {
const (
// https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#section-number-values
IMAGE_SYM_UNDEFINED = 0
// https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#storage-class
IMAGE_SYM_CLASS_EXTERNAL = 2
)
if sym.SectionNumber != IMAGE_SYM_UNDEFINED && sym.StorageClass == IMAGE_SYM_CLASS_EXTERNAL {
name := sym.Name
if f.Machine == pe.IMAGE_FILE_MACHINE_I386 {
// On 32-bit Windows, C symbols are decorated by calling
// convention.
// https://msdn.microsoft.com/en-us/library/56h2zst2.aspx#FormatC
if strings.HasPrefix(name, "_") || strings.HasPrefix(name, "@") {
// __cdecl, __stdcall, or __fastcall. Remove the prefix and
// suffix, if present.
name = name[1:]
if idx := strings.LastIndex(name, "@"); idx >= 0 {
name = name[:idx]
}
} else if idx := strings.LastIndex(name, "@@"); idx >= 0 {
// __vectorcall. Remove the suffix.
name = name[:idx]
}
}
ret = append(ret, name)
}
}
return ret, nil
}