From f573be7b33b44c59433a07bf70284e725458c379 Mon Sep 17 00:00:00 2001 From: Robert Sloan Date: Mon, 17 Sep 2018 15:29:11 -0700 Subject: external/boringssl: Sync to 5baee45652d9de70ae957d1aa1e04a2d27101c3b. This includes the following changes: https://boringssl.googlesource.com/boringssl/+log/689019fe40d5ad94df46ffeebcd794ff359a7074..5baee45652d9de70ae957d1aa1e04a2d27101c3b Test: BoringSSL CTS Presubmits Change-Id: I6f92d4fa84a3b9d6f35b291cb0da0782219b2b05 --- BORINGSSL_REVISION | 2 +- linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S | 4 +- linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S | 4 +- src/.gitignore | 1 - src/BUILDING.md | 5 +- src/CMakeLists.txt | 37 + src/crypto/fipsmodule/CMakeLists.txt | 25 +- src/crypto/fipsmodule/cipher/e_aes.c | 37 +- src/crypto/fipsmodule/cipher/internal.h | 4 +- src/crypto/fipsmodule/modes/gcm.c | 75 +- src/crypto/fipsmodule/modes/gcm_test.cc | 3 +- src/crypto/fipsmodule/modes/internal.h | 109 +- src/crypto/mem.c | 21 +- src/crypto/perlasm/ppc-xlate.pl | 4 +- src/go.mod | 1 + src/include/openssl/dh.h | 1 + src/include/openssl/dsa.h | 1 + src/include/openssl/ec_key.h | 1 + src/include/openssl/rsa.h | 1 + src/ssl/d1_both.cc | 9 - src/ssl/dtls_method.cc | 1 - src/ssl/internal.h | 5 - src/ssl/s3_both.cc | 12 - src/ssl/test/runner/chacha20_poly1305.go | 2 +- src/ssl/test/runner/ed25519/ed25519.go | 2 +- src/ssl/test/runner/ed25519/ed25519_test.go | 2 +- src/ssl/test/runner/handshake_client.go | 2 +- src/ssl/test/runner/handshake_server.go | 2 +- src/ssl/test/runner/key_agreement.go | 4 +- src/ssl/test/runner/sign.go | 2 +- src/ssl/test/runner/tls.go | 2 +- src/ssl/tls_method.cc | 1 - src/util/bot/DEPS | 8 +- src/util/bot/go/bootstrap.py | 2 +- src/util/doc.go | 2 +- src/util/fipstools/ar.go | 120 - src/util/fipstools/const.go | 22 - src/util/fipstools/delocate.go | 1649 -------- src/util/fipstools/delocate.peg | 80 - src/util/fipstools/delocate.peg.go | 4017 -------------------- src/util/fipstools/delocate/delocate.go | 1651 ++++++++ src/util/fipstools/delocate/delocate.peg | 80 + src/util/fipstools/delocate/delocate.peg.go | 4017 ++++++++++++++++++++ src/util/fipstools/delocate/delocate_test.go | 86 + .../delocate/testdata/ppc64le-GlobalEntry/in.s | 9 + .../delocate/testdata/ppc64le-GlobalEntry/out.s | 94 + .../delocate/testdata/ppc64le-LoadToR0/in.s | 4 + .../delocate/testdata/ppc64le-LoadToR0/out.s | 104 + .../delocate/testdata/ppc64le-Sample/in.s | 161 + .../delocate/testdata/ppc64le-Sample/out.s | 584 +++ .../delocate/testdata/ppc64le-Sample2/in.s | 226 ++ .../delocate/testdata/ppc64le-Sample2/out.s | 709 ++++ .../delocate/testdata/ppc64le-TOCWithOffset/in.s | 23 + .../delocate/testdata/ppc64le-TOCWithOffset/out.s | 210 + .../fipstools/delocate/testdata/x86_64-BSS/in.s | 33 + .../fipstools/delocate/testdata/x86_64-BSS/out.s | 143 + .../fipstools/delocate/testdata/x86_64-Basic/in.s | 46 + .../fipstools/delocate/testdata/x86_64-Basic/out.s | 133 + .../delocate/testdata/x86_64-GOTRewrite/in.s | 47 + .../delocate/testdata/x86_64-GOTRewrite/out.s | 263 ++ .../delocate/testdata/x86_64-LabelRewrite/in1.s | 43 + .../delocate/testdata/x86_64-LabelRewrite/in2.s | 12 + .../delocate/testdata/x86_64-LabelRewrite/out.s | 167 + .../delocate/testdata/x86_64-Sections/in.s | 36 + .../delocate/testdata/x86_64-Sections/out.s | 125 + src/util/fipstools/delocate_test.go | 86 - src/util/fipstools/fipscommon/ar.go | 120 + src/util/fipstools/fipscommon/const.go | 22 + src/util/fipstools/inject-hash.go | 173 - src/util/fipstools/inject-hash/inject-hash.go | 175 + .../fipstools/testdata/ppc64le-GlobalEntry/in.s | 9 - .../fipstools/testdata/ppc64le-GlobalEntry/out.s | 94 - src/util/fipstools/testdata/ppc64le-LoadToR0/in.s | 4 - src/util/fipstools/testdata/ppc64le-LoadToR0/out.s | 104 - src/util/fipstools/testdata/ppc64le-Sample/in.s | 161 - src/util/fipstools/testdata/ppc64le-Sample/out.s | 584 --- src/util/fipstools/testdata/ppc64le-Sample2/in.s | 226 -- src/util/fipstools/testdata/ppc64le-Sample2/out.s | 709 ---- .../fipstools/testdata/ppc64le-TOCWithOffset/in.s | 23 - .../fipstools/testdata/ppc64le-TOCWithOffset/out.s | 210 - src/util/fipstools/testdata/x86_64-BSS/in.s | 33 - src/util/fipstools/testdata/x86_64-BSS/out.s | 143 - src/util/fipstools/testdata/x86_64-Basic/in.s | 46 - src/util/fipstools/testdata/x86_64-Basic/out.s | 133 - src/util/fipstools/testdata/x86_64-GOTRewrite/in.s | 47 - .../fipstools/testdata/x86_64-GOTRewrite/out.s | 263 -- .../fipstools/testdata/x86_64-LabelRewrite/in1.s | 43 - .../fipstools/testdata/x86_64-LabelRewrite/in2.s | 12 - .../fipstools/testdata/x86_64-LabelRewrite/out.s | 167 - src/util/fipstools/testdata/x86_64-Sections/in.s | 36 - src/util/fipstools/testdata/x86_64-Sections/out.s | 125 - src/util/godeps.go | 203 + 92 files changed, 9742 insertions(+), 9497 deletions(-) create mode 100644 src/go.mod delete mode 100644 src/util/fipstools/ar.go delete mode 100644 src/util/fipstools/const.go delete mode 100644 src/util/fipstools/delocate.go delete mode 100644 src/util/fipstools/delocate.peg delete mode 100644 src/util/fipstools/delocate.peg.go create mode 100644 src/util/fipstools/delocate/delocate.go create mode 100644 src/util/fipstools/delocate/delocate.peg create mode 100644 src/util/fipstools/delocate/delocate.peg.go create mode 100644 src/util/fipstools/delocate/delocate_test.go create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-Sample/in.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-Sample/out.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s create mode 100644 src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-BSS/in.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-BSS/out.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-Basic/in.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-Basic/out.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-Sections/in.s create mode 100644 src/util/fipstools/delocate/testdata/x86_64-Sections/out.s delete mode 100644 src/util/fipstools/delocate_test.go create mode 100644 src/util/fipstools/fipscommon/ar.go create mode 100644 src/util/fipstools/fipscommon/const.go delete mode 100644 src/util/fipstools/inject-hash.go create mode 100644 src/util/fipstools/inject-hash/inject-hash.go delete mode 100644 src/util/fipstools/testdata/ppc64le-GlobalEntry/in.s delete mode 100644 src/util/fipstools/testdata/ppc64le-GlobalEntry/out.s delete mode 100644 src/util/fipstools/testdata/ppc64le-LoadToR0/in.s delete mode 100644 src/util/fipstools/testdata/ppc64le-LoadToR0/out.s delete mode 100644 src/util/fipstools/testdata/ppc64le-Sample/in.s delete mode 100644 src/util/fipstools/testdata/ppc64le-Sample/out.s delete mode 100644 src/util/fipstools/testdata/ppc64le-Sample2/in.s delete mode 100644 src/util/fipstools/testdata/ppc64le-Sample2/out.s delete mode 100644 src/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s delete mode 100644 src/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s delete mode 100644 src/util/fipstools/testdata/x86_64-BSS/in.s delete mode 100644 src/util/fipstools/testdata/x86_64-BSS/out.s delete mode 100644 src/util/fipstools/testdata/x86_64-Basic/in.s delete mode 100644 src/util/fipstools/testdata/x86_64-Basic/out.s delete mode 100644 src/util/fipstools/testdata/x86_64-GOTRewrite/in.s delete mode 100644 src/util/fipstools/testdata/x86_64-GOTRewrite/out.s delete mode 100644 src/util/fipstools/testdata/x86_64-LabelRewrite/in1.s delete mode 100644 src/util/fipstools/testdata/x86_64-LabelRewrite/in2.s delete mode 100644 src/util/fipstools/testdata/x86_64-LabelRewrite/out.s delete mode 100644 src/util/fipstools/testdata/x86_64-Sections/in.s delete mode 100644 src/util/fipstools/testdata/x86_64-Sections/out.s create mode 100644 src/util/godeps.go diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION index 6defbc42..c2e11fae 100644 --- a/BORINGSSL_REVISION +++ b/BORINGSSL_REVISION @@ -1 +1 @@ -689019fe40d5ad94df46ffeebcd794ff359a7074 +5baee45652d9de70ae957d1aa1e04a2d27101c3b diff --git a/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S b/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S index 89c5926b..618bd1c5 100644 --- a/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S +++ b/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S @@ -1,6 +1,6 @@ #if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM)" -#define OPENSSL_NO_ASM" +#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM) +#define OPENSSL_NO_ASM #endif #endif diff --git a/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S b/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S index f6ac4241..f4f9d252 100644 --- a/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S +++ b/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S @@ -1,6 +1,6 @@ #if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM)" -#define OPENSSL_NO_ASM" +#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM) +#define OPENSSL_NO_ASM #endif #endif diff --git a/src/.gitignore b/src/.gitignore index db50b0be..9cb72518 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -17,7 +17,6 @@ util/bot/golang util/bot/gyp util/bot/libcxx util/bot/libcxxabi -util/bot/libFuzzer util/bot/llvm-build util/bot/nasm-win32.exe util/bot/perl-win32 diff --git a/src/BUILDING.md b/src/BUILDING.md index 9bf9cb26..ab9b71d9 100644 --- a/src/BUILDING.md +++ b/src/BUILDING.md @@ -29,8 +29,9 @@ and Clang should work on non-Windows platforms, and maybe on Windows too. To build the tests, you also need a C++ compiler with C++11 support. - * [Go](https://golang.org/dl/) is required. If not found by CMake, the go - executable may be configured explicitly by setting `GO_EXECUTABLE`. + * The most recent stable version of [Go](https://golang.org/dl/) is required. + If not found by CMake, the go executable may be configured explicitly by + setting `GO_EXECUTABLE`. * To build the x86 and x86\_64 assembly, your assembler must support AVX2 instructions and MOVBE. If using GNU binutils, you must have 2.22 or later diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c614a65a..1586d34d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -334,6 +334,43 @@ if(OPENSSL_SMALL) 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/src/crypto/fipsmodule/CMakeLists.txt b/src/crypto/fipsmodule/CMakeLists.txt index 1242aa2f..9868dd87 100644 --- a/src/crypto/fipsmodule/CMakeLists.txt +++ b/src/crypto/fipsmodule/CMakeLists.txt @@ -141,21 +141,12 @@ if(FIPS_DELOCATE) 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 $ -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 $ -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 @@ if(FIPS_DELOCATE) 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 $ - 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 $ + 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/src/crypto/fipsmodule/cipher/e_aes.c b/src/crypto/fipsmodule/cipher/e_aes.c index de2f10f0..734a5174 100644 --- a/src/crypto/fipsmodule/cipher/e_aes.c +++ b/src/crypto/fipsmodule/cipher/e_aes.c @@ -305,13 +305,13 @@ static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, return 1; } -ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, +ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key, block128_f *out_block, const uint8_t *key, size_t key_bytes) { if (hwaes_capable()) { aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key); - if (gcm_ctx != NULL) { - CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt, 1); + if (gcm_key != NULL) { + CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)aes_hw_encrypt, 1); } if (out_block) { *out_block = (block128_f) aes_hw_encrypt; @@ -321,8 +321,8 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, if (bsaes_capable()) { AES_set_encrypt_key(key, key_bytes * 8, aes_key); - if (gcm_ctx != NULL) { - CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0); + if (gcm_key != NULL) { + CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)AES_encrypt, 0); } if (out_block) { *out_block = (block128_f) AES_encrypt; @@ -335,15 +335,15 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, if (out_block) { *out_block = (block128_f) vpaes_encrypt; } - if (gcm_ctx != NULL) { - CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt, 0); + if (gcm_key != NULL) { + CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)vpaes_encrypt, 0); } return NULL; } AES_set_encrypt_key(key, key_bytes * 8, aes_key); - if (gcm_ctx != NULL) { - CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0); + if (gcm_key != NULL) { + CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)AES_encrypt, 0); } if (out_block) { *out_block = (block128_f) AES_encrypt; @@ -358,8 +358,9 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, return 1; } if (key) { - gctx->ctr = - aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len); + OPENSSL_memset(&gctx->gcm, 0, sizeof(gctx->gcm)); + gctx->ctr = aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm.gcm_key, NULL, key, + ctx->key_len); // If we have an iv can set it directly, otherwise use saved IV. if (iv == NULL && gctx->iv_set) { iv = gctx->iv; @@ -879,7 +880,7 @@ struct aead_aes_gcm_ctx { double align; AES_KEY ks; } ks; - GCM128_CONTEXT gcm; + GCM128_KEY gcm_key; ctr128_f ctr; }; @@ -903,7 +904,7 @@ static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx, } gcm_ctx->ctr = - aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len); + aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm_key, NULL, key, key_len); *out_tag_len = tag_len; return 1; } @@ -941,7 +942,6 @@ static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t extra_in_len, const uint8_t *ad, size_t ad_len) { const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state; - GCM128_CONTEXT gcm; if (extra_in_len + ctx->tag_len < ctx->tag_len) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); @@ -958,7 +958,9 @@ static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, const AES_KEY *key = &gcm_ctx->ks.ks; - OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + GCM128_CONTEXT gcm; + OPENSSL_memset(&gcm, 0, sizeof(gcm)); + OPENSSL_memcpy(&gcm.gcm_key, &gcm_ctx->gcm_key, sizeof(gcm.gcm_key)); CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len); if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) { @@ -1002,7 +1004,6 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *ad, size_t ad_len) { const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state; uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN]; - GCM128_CONTEXT gcm; if (nonce_len == 0) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE); @@ -1016,7 +1017,9 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, const AES_KEY *key = &gcm_ctx->ks.ks; - OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm)); + GCM128_CONTEXT gcm; + OPENSSL_memset(&gcm, 0, sizeof(gcm)); + OPENSSL_memcpy(&gcm.gcm_key, &gcm_ctx->gcm_key, sizeof(gcm.gcm_key)); CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len); if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) { diff --git a/src/crypto/fipsmodule/cipher/internal.h b/src/crypto/fipsmodule/cipher/internal.h index 7b5f23f0..7c739fbd 100644 --- a/src/crypto/fipsmodule/cipher/internal.h +++ b/src/crypto/fipsmodule/cipher/internal.h @@ -114,11 +114,11 @@ struct evp_aead_st { // aes_ctr_set_key initialises |*aes_key| using |key_bytes| bytes from |key|, // where |key_bytes| must either be 16, 24 or 32. If not NULL, |*out_block| is -// set to a function that encrypts single blocks. If not NULL, |*gcm_ctx| is +// set to a function that encrypts single blocks. If not NULL, |*gcm_key| is // initialised to do GHASH with the given key. It returns a function for // optimised CTR-mode, or NULL if CTR-mode should be built using // |*out_block|. -ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx, +ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key, block128_f *out_block, const uint8_t *key, size_t key_bytes); diff --git a/src/crypto/fipsmodule/modes/gcm.c b/src/crypto/fipsmodule/modes/gcm.c index 99d0e15e..6eff4792 100644 --- a/src/crypto/fipsmodule/modes/gcm.c +++ b/src/crypto/fipsmodule/modes/gcm.c @@ -243,9 +243,10 @@ void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len); #endif -#define GCM_MUL(ctx, Xi) gcm_gmult_4bit((ctx)->Xi.u, (ctx)->Htable) +#define GCM_MUL(ctx, Xi) gcm_gmult_4bit((ctx)->Xi.u, (ctx)->gcm_key.Htable) #if defined(GHASH_ASM) -#define GHASH(ctx, in, len) gcm_ghash_4bit((ctx)->Xi.u, (ctx)->Htable, in, len) +#define GHASH(ctx, in, len) \ + gcm_ghash_4bit((ctx)->Xi.u, (ctx)->gcm_key.Htable, in, len) // GHASH_CHUNK is "stride parameter" missioned to mitigate cache // trashing effect. In other words idea is to hash data while it's // still in L1 cache after encryption pass... @@ -337,10 +338,11 @@ void gcm_ghash_p8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, #ifdef GCM_FUNCREF_4BIT #undef GCM_MUL -#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)((ctx)->Xi.u, (ctx)->Htable) +#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)((ctx)->Xi.u, (ctx)->gcm_key.Htable) #ifdef GHASH #undef GHASH -#define GHASH(ctx, in, len) (*gcm_ghash_p)((ctx)->Xi.u, (ctx)->Htable, in, len) +#define GHASH(ctx, in, len) \ + (*gcm_ghash_p)((ctx)->Xi.u, (ctx)->gcm_key.Htable, in, len) #endif #endif @@ -417,27 +419,28 @@ void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, #endif } -void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *aes_key, - block128_f block, int block_is_hwaes) { - OPENSSL_memset(ctx, 0, sizeof(*ctx)); - ctx->block = block; +void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const void *aes_key, + block128_f block, int block_is_hwaes) { + OPENSSL_memset(gcm_key, 0, sizeof(*gcm_key)); + gcm_key->block = block; - uint8_t gcm_key[16]; - OPENSSL_memset(gcm_key, 0, sizeof(gcm_key)); - (*block)(gcm_key, gcm_key, aes_key); + uint8_t ghash_key[16]; + OPENSSL_memset(ghash_key, 0, sizeof(ghash_key)); + (*block)(ghash_key, ghash_key, aes_key); int is_avx; - CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, &ctx->H, ctx->Htable, &is_avx, - gcm_key); + CRYPTO_ghash_init(&gcm_key->gmult, &gcm_key->ghash, &gcm_key->H, + gcm_key->Htable, &is_avx, ghash_key); - ctx->use_aesni_gcm_crypt = (is_avx && block_is_hwaes) ? 1 : 0; + gcm_key->use_aesni_gcm_crypt = (is_avx && block_is_hwaes) ? 1 : 0; } void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, const uint8_t *iv, size_t len) { unsigned int ctr; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #endif ctx->Yi.u[0] = 0; @@ -477,7 +480,7 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, ctr = CRYPTO_bswap4(ctx->Yi.d[3]); } - (*ctx->block)(ctx->Yi.c, ctx->EK0.c, key); + (*ctx->gcm_key.block)(ctx->Yi.c, ctx->EK0.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); } @@ -486,10 +489,11 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) { unsigned int n; uint64_t alen = ctx->len.u[0]; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #ifdef GHASH void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; + size_t len) = ctx->gcm_key.ghash; #endif #endif @@ -553,12 +557,13 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, const uint8_t *in, uint8_t *out, size_t len) { unsigned int n, ctr; uint64_t mlen = ctx->len.u[1]; - block128_f block = ctx->block; + block128_f block = ctx->gcm_key.block; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #ifdef GHASH void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; + size_t len) = ctx->gcm_key.ghash; #endif #endif @@ -679,12 +684,13 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, size_t len) { unsigned int n, ctr; uint64_t mlen = ctx->len.u[1]; - block128_f block = ctx->block; + block128_f block = ctx->gcm_key.block; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #ifdef GHASH void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; + size_t len) = ctx->gcm_key.ghash; #endif #endif @@ -813,10 +819,11 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, unsigned int n, ctr; uint64_t mlen = ctx->len.u[1]; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #ifdef GHASH void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; + size_t len) = ctx->gcm_key.ghash; #endif #endif @@ -849,7 +856,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, } #if defined(AESNI_GCM) - if (ctx->use_aesni_gcm_crypt) { + if (ctx->gcm_key.use_aesni_gcm_crypt) { // |aesni_gcm_encrypt| may not process all the input given to it. It may // not process *any* of its input if it is deemed too small. size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); @@ -895,7 +902,7 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, #endif } if (len) { - (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); + (*ctx->gcm_key.block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); while (len--) { @@ -914,10 +921,11 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, unsigned int n, ctr; uint64_t mlen = ctx->len.u[1]; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #ifdef GHASH void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; + size_t len) = ctx->gcm_key.ghash; #endif #endif @@ -952,7 +960,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, } #if defined(AESNI_GCM) - if (ctx->use_aesni_gcm_crypt) { + if (ctx->gcm_key.use_aesni_gcm_crypt) { // |aesni_gcm_decrypt| may not process all the input given to it. It may // not process *any* of its input if it is deemed too small. size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); @@ -1001,7 +1009,7 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, len -= i; } if (len) { - (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); + (*ctx->gcm_key.block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); while (len--) { @@ -1020,7 +1028,8 @@ int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) { uint64_t alen = ctx->len.u[0] << 3; uint64_t clen = ctx->len.u[1] << 3; #ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; + void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = + ctx->gcm_key.gmult; #endif if (ctx->mres || ctx->ares) { diff --git a/src/crypto/fipsmodule/modes/gcm_test.cc b/src/crypto/fipsmodule/modes/gcm_test.cc index 59889453..ab8cc34e 100644 --- a/src/crypto/fipsmodule/modes/gcm_test.cc +++ b/src/crypto/fipsmodule/modes/gcm_test.cc @@ -87,7 +87,8 @@ TEST(GCMTest, TestVectors) { ASSERT_EQ(0, AES_set_encrypt_key(key.data(), key.size() * 8, &aes_key)); GCM128_CONTEXT ctx; - CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f)AES_encrypt, 0); + OPENSSL_memset(&ctx, 0, sizeof(ctx)); + CRYPTO_gcm128_init_key(&ctx.gcm_key, &aes_key, (block128_f)AES_encrypt, 0); CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce.data(), nonce.size()); if (!additional_data.empty()) { CRYPTO_gcm128_aad(&ctx, additional_data.data(), additional_data.size()); diff --git a/src/crypto/fipsmodule/modes/internal.h b/src/crypto/fipsmodule/modes/internal.h index 338bf132..788960b7 100644 --- a/src/crypto/fipsmodule/modes/internal.h +++ b/src/crypto/fipsmodule/modes/internal.h @@ -91,52 +91,6 @@ static inline void store_word_le(void *out, size_t v) { typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16], const void *key); -// GCM definitions -typedef struct { uint64_t hi,lo; } u128; - -// gmult_func multiplies |Xi| by the GCM key and writes the result back to -// |Xi|. -typedef void (*gmult_func)(uint64_t Xi[2], const u128 Htable[16]); - -// ghash_func repeatedly multiplies |Xi| by the GCM key and adds in blocks from -// |inp|. The result is written back to |Xi| and the |len| argument must be a -// multiple of 16. -typedef void (*ghash_func)(uint64_t Xi[2], const u128 Htable[16], - const uint8_t *inp, size_t len); - -// This differs from upstream's |gcm128_context| in that it does not have the -// |key| pointer, in order to make it |memcpy|-friendly. Rather the key is -// passed into each call that needs it. -struct gcm128_context { - // Following 6 names follow names in GCM specification - union { - uint64_t u[2]; - uint32_t d[4]; - uint8_t c[16]; - size_t t[16 / sizeof(size_t)]; - } Yi, EKi, EK0, len, Xi; - - // Note that the order of |Xi|, |H| and |Htable| is fixed by the MOVBE-based, - // x86-64, GHASH assembly. - u128 H; - u128 Htable[16]; - gmult_func gmult; - ghash_func ghash; - - unsigned int mres, ares; - block128_f block; - - // use_aesni_gcm_crypt is true if this context should use the assembly - // functions |aesni_gcm_encrypt| and |aesni_gcm_decrypt| to process data. - unsigned use_aesni_gcm_crypt:1; -}; - -#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) -// crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is -// used. -int crypto_gcm_clmul_enabled(void); -#endif - // CTR. @@ -176,9 +130,59 @@ void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks, // This API differs from the upstream API slightly. The |GCM128_CONTEXT| does // not have a |key| pointer that points to the key as upstream's version does. // Instead, every function takes a |key| parameter. This way |GCM128_CONTEXT| -// can be safely copied. +// can be safely copied. Additionally, |gcm_key| is split into a separate +// struct. -typedef struct gcm128_context GCM128_CONTEXT; +typedef struct { uint64_t hi,lo; } u128; + +// gmult_func multiplies |Xi| by the GCM key and writes the result back to +// |Xi|. +typedef void (*gmult_func)(uint64_t Xi[2], const u128 Htable[16]); + +// ghash_func repeatedly multiplies |Xi| by the GCM key and adds in blocks from +// |inp|. The result is written back to |Xi| and the |len| argument must be a +// multiple of 16. +typedef void (*ghash_func)(uint64_t Xi[2], const u128 Htable[16], + const uint8_t *inp, size_t len); + +typedef struct gcm128_key_st { + // Note the MOVBE-based, x86-64, GHASH assembly requires |H| and |Htable| to + // be the first two elements of this struct. + u128 H; + u128 Htable[16]; + gmult_func gmult; + ghash_func ghash; + + block128_f block; + + // use_aesni_gcm_crypt is true if this context should use the assembly + // functions |aesni_gcm_encrypt| and |aesni_gcm_decrypt| to process data. + unsigned use_aesni_gcm_crypt:1; +} GCM128_KEY; + +// GCM128_CONTEXT contains state for a single GCM operation. The structure +// should be zero-initialized before use. +typedef struct { + // The following 5 names follow names in GCM specification + union { + uint64_t u[2]; + uint32_t d[4]; + uint8_t c[16]; + size_t t[16 / sizeof(size_t)]; + } Yi, EKi, EK0, len, Xi; + + // Note that the order of |Xi| and |gcm_key| is fixed by the MOVBE-based, + // x86-64, GHASH assembly. + GCM128_KEY gcm_key; + + unsigned mres, ares; +} GCM128_CONTEXT; + +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +// crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is +// used. +int crypto_gcm_clmul_enabled(void); +#endif // CRYPTO_ghash_init writes a precomputed table of powers of |gcm_key| to // |out_table| and sets |*out_mult| and |*out_hash| to (potentially hardware @@ -188,10 +192,11 @@ void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, u128 *out_key, u128 out_table[16], int *out_is_avx, const uint8_t *gcm_key); -// CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with -// the given key. |block_is_hwaes| is one if |block| is |aes_hw_encrypt|. -OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, - block128_f block, int block_is_hwaes); +// CRYPTO_gcm128_init_key initialises |gcm_key| to use |block| (typically AES) +// with the given key. |block_is_hwaes| is one if |block| is |aes_hw_encrypt|. +OPENSSL_EXPORT void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const void *key, + block128_f block, + int block_is_hwaes); // CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the // same key that was passed to |CRYPTO_gcm128_init|. diff --git a/src/crypto/mem.c b/src/crypto/mem.c index 5d45baa1..a06061b4 100644 --- a/src/crypto/mem.c +++ b/src/crypto/mem.c @@ -71,6 +71,25 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) #define OPENSSL_MALLOC_PREFIX 8 +#if defined(__GNUC__) || defined(__clang__) +// sdallocx is a sized |free| function. By passing the size (which we happen to +// always know in BoringSSL), the malloc implementation can save work. We cannot +// depend on |sdallocx| being available so we declare a wrapper that falls back +// to |free| as a weak symbol. +// +// This will always be safe, but will only be overridden if the malloc +// implementation is statically linked with BoringSSL. So, if |sdallocx| is +// provided in, say, libc.so, we still won't use it because that's dynamically +// linked. This isn't an ideal result, but its helps in some cases. +void sdallocx(void *ptr, size_t size, int flags); + +__attribute((weak, noinline)) +#else +static +#endif +void sdallocx(void *ptr, size_t size, int flags) { + free(ptr); +} void *OPENSSL_malloc(size_t size) { void *ptr = malloc(size + OPENSSL_MALLOC_PREFIX); @@ -92,7 +111,7 @@ void OPENSSL_free(void *orig_ptr) { size_t size = *(size_t *)ptr; OPENSSL_cleanse(ptr, size + OPENSSL_MALLOC_PREFIX); - free(ptr); + sdallocx(ptr, size + OPENSSL_MALLOC_PREFIX, 0 /* flags */); } void *OPENSSL_realloc(void *orig_ptr, size_t new_size) { diff --git a/src/crypto/perlasm/ppc-xlate.pl b/src/crypto/perlasm/ppc-xlate.pl index 05595f2c..7f01dbde 100644 --- a/src/crypto/perlasm/ppc-xlate.pl +++ b/src/crypto/perlasm/ppc-xlate.pl @@ -257,8 +257,8 @@ my $darn = sub { print <<___; #if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM)" -#define OPENSSL_NO_ASM" +#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM) +#define OPENSSL_NO_ASM #endif #endif diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 00000000..09d36fbf --- /dev/null +++ b/src/go.mod @@ -0,0 +1 @@ +module boringssl.googlesource.com/boringssl diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h index 7188790a..7e103038 100644 --- a/src/include/openssl/dh.h +++ b/src/include/openssl/dh.h @@ -281,6 +281,7 @@ extern "C++" { BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(DH, DH_free) +BORINGSSL_MAKE_UP_REF(DH, DH_up_ref) BSSL_NAMESPACE_END diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h index 70cde7bb..bed93c5d 100644 --- a/src/include/openssl/dsa.h +++ b/src/include/openssl/dsa.h @@ -420,6 +420,7 @@ extern "C++" { BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(DSA, DSA_free) +BORINGSSL_MAKE_UP_REF(DSA, DSA_up_ref) BORINGSSL_MAKE_DELETER(DSA_SIG, DSA_SIG_free) BSSL_NAMESPACE_END diff --git a/src/include/openssl/ec_key.h b/src/include/openssl/ec_key.h index 7e9e4e8f..9bc78875 100644 --- a/src/include/openssl/ec_key.h +++ b/src/include/openssl/ec_key.h @@ -339,6 +339,7 @@ extern "C++" { BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(EC_KEY, EC_KEY_free) +BORINGSSL_MAKE_UP_REF(EC_KEY, EC_KEY_up_ref) BSSL_NAMESPACE_END diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h index 8098c482..dcca9e3f 100644 --- a/src/include/openssl/rsa.h +++ b/src/include/openssl/rsa.h @@ -726,6 +726,7 @@ extern "C++" { BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(RSA, RSA_free) +BORINGSSL_MAKE_UP_REF(RSA, RSA_up_ref) BSSL_NAMESPACE_END diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc index 3f7739ed..d82852d7 100644 --- a/src/ssl/d1_both.cc +++ b/src/ssl/d1_both.cc @@ -601,15 +601,6 @@ bool dtls1_add_change_cipher_spec(SSL *ssl) { return add_outgoing(ssl, true /* ChangeCipherSpec */, Array()); } -bool dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc) { - // The |add_alert| path is only used for warning alerts for now, which DTLS - // never sends. This will be implemented later once closure alerts are - // converted. - assert(false); - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return false; -} - // dtls1_update_mtu updates the current MTU from the BIO, ensuring it is above // the minimum. static void dtls1_update_mtu(SSL *ssl) { diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc index 8d40edf8..d49687f8 100644 --- a/src/ssl/dtls_method.cc +++ b/src/ssl/dtls_method.cc @@ -121,7 +121,6 @@ static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = { dtls1_finish_message, dtls1_add_message, dtls1_add_change_cipher_spec, - dtls1_add_alert, dtls1_flush_flight, dtls1_on_handshake_complete, dtls1_set_read_state, diff --git a/src/ssl/internal.h b/src/ssl/internal.h index 7ba23ef4..0535b8de 100644 --- a/src/ssl/internal.h +++ b/src/ssl/internal.h @@ -1889,9 +1889,6 @@ struct SSL_PROTOCOL_METHOD { // add_change_cipher_spec adds a ChangeCipherSpec record to the pending // flight. It returns true on success and false on error. bool (*add_change_cipher_spec)(SSL *ssl); - // add_alert adds an alert to the pending flight. It returns true on success - // and false on error. - bool (*add_alert)(SSL *ssl, uint8_t level, uint8_t desc); // flush_flight flushes the pending flight to the transport. It returns one on // success and <= 0 on error. int (*flush_flight)(SSL *ssl); @@ -2589,14 +2586,12 @@ bool ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type); bool ssl3_finish_message(SSL *ssl, CBB *cbb, Array *out_msg); bool ssl3_add_message(SSL *ssl, Array msg); bool ssl3_add_change_cipher_spec(SSL *ssl); -bool ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc); int ssl3_flush_flight(SSL *ssl); bool dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type); bool dtls1_finish_message(SSL *ssl, CBB *cbb, Array *out_msg); bool dtls1_add_message(SSL *ssl, Array msg); bool dtls1_add_change_cipher_spec(SSL *ssl); -bool dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc); int dtls1_flush_flight(SSL *ssl); // ssl_add_message_cbb finishes the handshake message in |cbb| and adds it to diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc index c1d4b652..3f09d50b 100644 --- a/src/ssl/s3_both.cc +++ b/src/ssl/s3_both.cc @@ -266,18 +266,6 @@ bool ssl3_add_change_cipher_spec(SSL *ssl) { return true; } -bool ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc) { - uint8_t alert[2] = {level, desc}; - if (!tls_flush_pending_hs_data(ssl) || - !add_record_to_flight(ssl, SSL3_RT_ALERT, alert)) { - return false; - } - - ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, alert); - ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, ((int)level << 8) | desc); - return true; -} - int ssl3_flush_flight(SSL *ssl) { if (!tls_flush_pending_hs_data(ssl)) { return -1; diff --git a/src/ssl/test/runner/chacha20_poly1305.go b/src/ssl/test/runner/chacha20_poly1305.go index 866f7242..446fb557 100644 --- a/src/ssl/test/runner/chacha20_poly1305.go +++ b/src/ssl/test/runner/chacha20_poly1305.go @@ -20,7 +20,7 @@ import ( "encoding/binary" "errors" - "./poly1305" + "boringssl.googlesource.com/boringssl/ssl/test/runner/poly1305" ) // See RFC 7539. diff --git a/src/ssl/test/runner/ed25519/ed25519.go b/src/ssl/test/runner/ed25519/ed25519.go index dfef0ffc..9a27332d 100644 --- a/src/ssl/test/runner/ed25519/ed25519.go +++ b/src/ssl/test/runner/ed25519/ed25519.go @@ -21,7 +21,7 @@ import ( "io" "strconv" - "./internal/edwards25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519/internal/edwards25519" ) const ( diff --git a/src/ssl/test/runner/ed25519/ed25519_test.go b/src/ssl/test/runner/ed25519/ed25519_test.go index 02c98614..b84cfa81 100644 --- a/src/ssl/test/runner/ed25519/ed25519_test.go +++ b/src/ssl/test/runner/ed25519/ed25519_test.go @@ -15,7 +15,7 @@ import ( "strings" "testing" - "./internal/edwards25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519/internal/edwards25519" ) type zeroReader struct{} diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go index 49e947d4..4dfa4699 100644 --- a/src/ssl/test/runner/handshake_client.go +++ b/src/ssl/test/runner/handshake_client.go @@ -19,7 +19,7 @@ import ( "net" "time" - "./ed25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) type clientHandshakeState struct { diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go index ca7a7d37..4950a4fe 100644 --- a/src/ssl/test/runner/handshake_server.go +++ b/src/ssl/test/runner/handshake_server.go @@ -18,7 +18,7 @@ import ( "math/big" "time" - "./ed25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) // serverHandshakeState contains details of a server handshake in progress. diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go index 5a304699..791325cd 100644 --- a/src/ssl/test/runner/key_agreement.go +++ b/src/ssl/test/runner/key_agreement.go @@ -15,8 +15,8 @@ import ( "io" "math/big" - "./curve25519" - "./ed25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) type keyType int diff --git a/src/ssl/test/runner/sign.go b/src/ssl/test/runner/sign.go index ceae05c1..0c963d99 100644 --- a/src/ssl/test/runner/sign.go +++ b/src/ssl/test/runner/sign.go @@ -18,7 +18,7 @@ import ( "fmt" "math/big" - "./ed25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) type signer interface { diff --git a/src/ssl/test/runner/tls.go b/src/ssl/test/runner/tls.go index 225794ba..41931bea 100644 --- a/src/ssl/test/runner/tls.go +++ b/src/ssl/test/runner/tls.go @@ -18,7 +18,7 @@ import ( "strings" "time" - "./ed25519" + "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) // Server returns a new TLS server side connection diff --git a/src/ssl/tls_method.cc b/src/ssl/tls_method.cc index 116f0270..bc9410b3 100644 --- a/src/ssl/tls_method.cc +++ b/src/ssl/tls_method.cc @@ -119,7 +119,6 @@ static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = { ssl3_finish_message, ssl3_add_message, ssl3_add_change_cipher_spec, - ssl3_add_alert, ssl3_flush_flight, ssl3_on_handshake_complete, ssl3_set_read_state, diff --git a/src/util/bot/DEPS b/src/util/bot/DEPS index 5dab2031..5449ab0d 100644 --- a/src/util/bot/DEPS +++ b/src/util/bot/DEPS @@ -16,7 +16,6 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', 'checkout_clang': False, - 'checkout_fuzzer': False, 'checkout_sde': False, 'checkout_nasm': False, 'checkout_libcxx': False, @@ -24,7 +23,7 @@ vars = { deps = { 'boringssl/util/bot/android_ndk': { - 'url': Var('chromium_git') + '/android_ndk.git' + '@' + '5cd86312e794bdf542a3685c6f10cbb96072990b', + 'url': Var('chromium_git') + '/android_ndk.git' + '@' + '4e2cea441bfd43f0863d14f57b1e1844260b9884', 'condition': 'checkout_android', }, @@ -36,11 +35,6 @@ deps = { 'boringssl/util/bot/gyp': Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb', - 'boringssl/util/bot/libFuzzer': { - 'url': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + '658ff786a213703ff0df6ba4a288e9a1e218c074', - 'condition': 'checkout_fuzzer', - }, - # Update the following revisions from # https://chromium.googlesource.com/chromium/buildtools/+/master/DEPS 'boringssl/util/bot/libcxx': { diff --git a/src/util/bot/go/bootstrap.py b/src/util/bot/go/bootstrap.py index eb6eed9c..9dbabe52 100755 --- a/src/util/bot/go/bootstrap.py +++ b/src/util/bot/go/bootstrap.py @@ -45,7 +45,7 @@ WORKSPACE = os.path.join(ROOT, 'go') EXE_SFX = '.exe' if sys.platform == 'win32' else '' # Pinned version of Go toolset to download. -TOOLSET_VERSION = 'go1.10.3' +TOOLSET_VERSION = 'go1.11' # Platform dependent portion of a download URL. See http://golang.org/dl/. TOOLSET_VARIANTS = { diff --git a/src/util/doc.go b/src/util/doc.go index ab21547f..33bcc66b 100644 --- a/src/util/doc.go +++ b/src/util/doc.go @@ -453,7 +453,7 @@ func (config *Config) parseHeader(path string) (*HeaderFile, error) { ok = strings.HasPrefix(name, subject[:l-1]) } if !ok { - return nil, fmt.Errorf("Comment for %q doesn't seem to match line %s:%d\n", name, path, declLineNo) + return nil, fmt.Errorf("comment for %q doesn't seem to match line %s:%d\n", name, path, declLineNo) } } anchor := sanitizeAnchor(name) diff --git a/src/util/fipstools/ar.go b/src/util/fipstools/ar.go deleted file mode 100644 index 51e7aa5d..00000000 --- a/src/util/fipstools/ar.go +++ /dev/null @@ -1,120 +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 main - -import ( - "bytes" - "errors" - "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 = "!\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:] - if i := bytes.IndexByte(filename, '/'); i < 0 { - return nil, errors.New("ar: unterminated filename in table") - } else { - filename = filename[:i] - } - - name = string(filename) - - default: - name = strings.TrimRight(name, "/") - } - - ret[name] = contents - } - - return ret, nil -} diff --git a/src/util/fipstools/const.go b/src/util/fipstools/const.go deleted file mode 100644 index 2e009ac8..00000000 --- a/src/util/fipstools/const.go +++ /dev/null @@ -1,22 +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. */ - -package main - -// 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{ - 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/src/util/fipstools/delocate.go b/src/util/fipstools/delocate.go deleted file mode 100644 index d58e5bec..00000000 --- a/src/util/fipstools/delocate.go +++ /dev/null @@ -1,1649 +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. */ - -// delocate performs several transformations of textual assembly code. See -// crypto/fipsmodule/FIPS.md for an overview. -package main - -import ( - "errors" - "flag" - "fmt" - "io/ioutil" - "os" - "sort" - "strconv" - "strings" -) - -// inputFile represents a textual assembly file. -type inputFile struct { - path string - // index is a unique identifer given to this file. It's used for - // mapping local symbols. - index int - // isArchive indicates that the input should be processed as an ar - // file. - isArchive bool - // contents contains the contents of the file. - contents string - // ast points to the head of the syntax tree. - ast *node32 -} - -type stringWriter interface { - WriteString(string) (int, error) -} - -type processorType int - -const ( - ppc64le processorType = iota + 1 - x86_64 -) - -// delocation holds the state needed during a delocation operation. -type delocation struct { - processor processorType - output stringWriter - - // symbols is the set of symbols defined in the module. - symbols map[string]struct{} - // localEntrySymbols is the set of symbols with .localentry directives. - localEntrySymbols map[string]struct{} - // redirectors maps from out-call symbol name to the name of a - // redirector function for that symbol. E.g. “memcpy” -> - // “bcm_redirector_memcpy”. - redirectors map[string]string - // bssAccessorsNeeded maps from a BSS symbol name to the symbol that - // should be used to reference it. E.g. “P384_data_storage” -> - // “P384_data_storage”. - bssAccessorsNeeded map[string]string - // tocLoaders is a set of symbol names for which TOC helper functions - // are required. (ppc64le only.) - tocLoaders map[string]struct{} - // gotExternalsNeeded is a set of symbol names for which we need - // “delta” symbols: symbols that contain the offset from their location - // to the memory in question. - gotExternalsNeeded map[string]struct{} - - currentInput inputFile -} - -func (d *delocation) contents(node *node32) string { - return d.currentInput.contents[node.begin:node.end] -} - -// writeNode writes out an AST node. -func (d *delocation) writeNode(node *node32) { - if _, err := d.output.WriteString(d.contents(node)); err != nil { - panic(err) - } -} - -func (d *delocation) writeCommentedNode(node *node32) { - line := d.contents(node) - if _, err := d.output.WriteString("# WAS " + strings.TrimSpace(line) + "\n"); err != nil { - panic(err) - } -} - -func locateError(err error, with *node32, in inputFile) error { - posMap := translatePositions([]rune(in.contents), []int{int(with.begin)}) - var line int - for _, pos := range posMap { - line = pos.line - } - - return fmt.Errorf("error while processing %q on line %d: %q", in.contents[with.begin:with.end], line, err) -} - -func (d *delocation) processInput(input inputFile) (err error) { - d.currentInput = input - - var origStatement *node32 - defer func() { - if err := recover(); err != nil { - panic(locateError(fmt.Errorf("%s", err), origStatement, input)) - } - }() - - for statement := input.ast.up; statement != nil; statement = statement.next { - assertNodeType(statement, ruleStatement) - origStatement = statement - - node := skipWS(statement.up) - if node == nil { - d.writeNode(statement) - continue - } - - switch node.pegRule { - case ruleGlobalDirective, ruleComment, ruleLocationDirective: - d.writeNode(statement) - case ruleDirective: - statement, err = d.processDirective(statement, node.up) - case ruleLabelContainingDirective: - statement, err = d.processLabelContainingDirective(statement, node.up) - case ruleLabel: - statement, err = d.processLabel(statement, node.up) - case ruleInstruction: - switch d.processor { - case x86_64: - statement, err = d.processIntelInstruction(statement, node.up) - case ppc64le: - statement, err = d.processPPCInstruction(statement, node.up) - default: - panic("unknown processor") - } - default: - panic(fmt.Sprintf("unknown top-level statement type %q", rul3s[node.pegRule])) - } - - if err != nil { - return locateError(err, origStatement, input) - } - } - - return nil -} - -func (d *delocation) processDirective(statement, directive *node32) (*node32, error) { - assertNodeType(directive, ruleDirectiveName) - directiveName := d.contents(directive) - - var args []string - forEachPath(directive, func(arg *node32) { - // If the argument is a quoted string, use the raw contents. - // (Note that this doesn't unescape the string, but that's not - // needed so far. - if arg.up != nil { - arg = arg.up - assertNodeType(arg, ruleQuotedArg) - if arg.up == nil { - args = append(args, "") - return - } - arg = arg.up - assertNodeType(arg, ruleQuotedText) - } - args = append(args, d.contents(arg)) - }, ruleArgs, ruleArg) - - switch directiveName { - case "comm", "lcomm": - if len(args) < 1 { - return nil, errors.New("comm directive has no arguments") - } - d.bssAccessorsNeeded[args[0]] = args[0] - d.writeNode(statement) - - case "data": - // ASAN and some versions of MSAN are adding a .data section, - // and adding references to symbols within it to the code. We - // will have to work around this in the future. - return nil, errors.New(".data section found in module") - - case "section": - section := args[0] - - if section == ".data.rel.ro" { - // In a normal build, this is an indication of a - // problem but any references from the module to this - // section will result in a relocation and thus will - // break the integrity check. ASAN can generate these - // sections and so we will likely have to work around - // that in the future. - return nil, errors.New(".data.rel.ro section found in module") - } - - sectionType, ok := sectionType(section) - if !ok { - // Unknown sections are permitted in order to be robust - // to different compiler modes. - d.writeNode(statement) - break - } - - switch sectionType { - case ".rodata", ".text": - // Move .rodata to .text so it may be accessed without - // a relocation. GCC with -fmerge-constants will place - // strings into separate sections, so we move all - // sections named like .rodata. Also move .text.startup - // so the self-test function is also in the module. - d.writeCommentedNode(statement) - d.output.WriteString(".text\n") - - case ".data": - // See above about .data - return nil, errors.New(".data section found in module") - - case ".init_array", ".fini_array", ".ctors", ".dtors": - // init_array/ctors/dtors contains function - // pointers to constructor/destructor - // functions. These contain relocations, but - // they're in a different section anyway. - d.writeNode(statement) - break - - case ".debug", ".note", ".toc": - d.writeNode(statement) - break - - case ".bss": - d.writeNode(statement) - return d.handleBSS(statement) - } - - default: - d.writeNode(statement) - } - - return statement, nil -} - -func (d *delocation) processLabelContainingDirective(statement, directive *node32) (*node32, error) { - // The symbols within directives need to be mapped so that local - // symbols in two different .s inputs don't collide. - changed := false - assertNodeType(directive, ruleLabelContainingDirectiveName) - name := d.contents(directive) - - node := directive.next - assertNodeType(node, ruleWS) - - node = node.next - assertNodeType(node, ruleSymbolArgs) - - var args []string - for node = skipWS(node.up); node != nil; node = skipWS(node.next) { - assertNodeType(node, ruleSymbolArg) - arg := node.up - var mapped string - - for term := arg; term != nil; term = term.next { - if term.pegRule != ruleLocalSymbol { - mapped += d.contents(term) - continue - } - - oldSymbol := d.contents(term) - newSymbol := d.mapLocalSymbol(oldSymbol) - if newSymbol != oldSymbol { - changed = true - } - - mapped += newSymbol - } - - args = append(args, mapped) - } - - if !changed { - d.writeNode(statement) - } else { - d.writeCommentedNode(statement) - d.output.WriteString("\t" + name + "\t" + strings.Join(args, ", ") + "\n") - } - - if name == ".localentry" { - d.output.WriteString(localEntryName(args[0]) + ":\n") - } - - return statement, nil -} - -func (d *delocation) processLabel(statement, label *node32) (*node32, error) { - symbol := d.contents(label) - - switch label.pegRule { - case ruleLocalLabel: - d.output.WriteString(symbol + ":\n") - case ruleLocalSymbol: - // symbols need to be mapped so that local symbols from two - // different .s inputs don't collide. - d.output.WriteString(d.mapLocalSymbol(symbol) + ":\n") - case ruleSymbolName: - d.output.WriteString(localTargetName(symbol) + ":\n") - d.writeNode(statement) - default: - return nil, fmt.Errorf("unknown label type %q", rul3s[label.pegRule]) - } - - return statement, nil -} - -// instructionArgs collects all the arguments to an instruction. -func instructionArgs(node *node32) (argNodes []*node32) { - for node = skipWS(node); node != nil; node = skipWS(node.next) { - assertNodeType(node, ruleInstructionArg) - argNodes = append(argNodes, node.up) - } - - return argNodes -} - -/* ppc64le - -[PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st, - 2017 - -(Also useful is “Power ISA Version 2.07 B”. Note that version three of that -document is /not/ good as that's POWER9 specific.) - -ppc64le doesn't have IP-relative addressing and does a lot to work around this. -Rather than reference a PLT and GOT direction, it has a single structure called -the TOC (Table Of Contents). Within the TOC is the contents of .rodata, .data, -.got, .plt, .bss, etc sections [PABI;3.3]. - -A pointer to the TOC is maintained in r2 and the following pattern is used to -load the address of an element into a register: - - addis
, 2, foo@toc@ha - addi
,
, foo@toc@l - -The “addis” instruction shifts a signed constant left 16 bits and adds the -result to its second argument, saving the result in the first argument. The -“addi” instruction does the same, but without shifting. Thus the “@toc@ha" -suffix on a symbol means “the top 16 bits of the TOC offset” and “@toc@l” means -“the bottom 16 bits of the offset”. However, note that both values are signed, -thus offsets in the top half of a 64KB chunk will have an @ha value that's one -greater than expected and a negative @l value. - -The TOC is specific to a “module” (basically an executable or shared object). -This means that there's not a single TOC in a process and that r2 needs to -change as control moves between modules. Thus functions have two entry points: -the “global” entry point and the “local” entry point. Jumps from within the -same module can use the local entry while jumps from other modules must use the -global entry. The global entry establishes the correct value of r2 before -running the function and the local entry skips that code. - -The global entry point for a function is defined by its label. The local entry -is a power-of-two number of bytes from the global entry, set by the -“.localentry” directive. (ppc64le instructions are always 32 bits, so an offset -of 1 or 2 bytes is treated as an offset of zero.) - -In order to help the global entry code set r2 to point to the local TOC, r12 is -set to the address of the global entry point when called [PABI;2.2.1.1]. Thus -the global entry will typically use an addis+addi pair to add a known offset to -r12 and store it in r2. For example: - -foo: - addis 2, 12, .TOC. - foo@ha - addi 2, 2, .TOC. - foo@l - -(It's worth noting that the '@' operator binds very loosely, so the 3rd -arguments parse as (.TOC. - foo)@ha and (.TOC. - foo)@l.) - -When calling a function, the compiler doesn't know whether that function is in -the same module or not. Thus it doesn't know whether r12 needs to be set nor -whether r2 will be clobbered on return. Rather than always assume the worst, -the linker fixes stuff up once it knows that a call is going out of module: - -Firstly, calling, say, memcpy (which we assume to be in a different module) -won't actually jump directly to memcpy, or even a PLT resolution function. -It'll call a synthesised function that: - a) saves r2 in the caller's stack frame - b) loads the address of memcpy@PLT into r12 - c) jumps to r12. - -As this synthesised function loads memcpy@PLT, a call to memcpy from the -compiled code just references “memcpy” directly, not “memcpy@PLT”. - -Since it jumps directly to memcpy@PLT, it can't restore r2 on return. Thus -calls must be followed by a nop. If the call ends up going out-of-module, the -linker will rewrite that nop to load r2 from the stack. - -Speaking of the stack, the stack pointer is kept in r1 and there's a 288-byte -red-zone. The format of the stack frame is defined [PABI;2.2.2] and must be -followed as called functions will write into their parent's stack frame. For -example, the synthesised out-of-module trampolines will save r2 24 bytes into -the caller's frame and all non-leaf functions save the return address 16 bytes -into the caller's frame. - -A final point worth noting: some RISC ISAs have r0 wired to zero: all reads -result in zero and all writes are discarded. POWER does something a little like -that, but r0 is only special in certain argument positions for certain -instructions. You just have to read the manual to know which they are. - - -Delocation is easier than Intel because there's just TOC references, but it's -also harder because there's no IP-relative addressing. - -Jumps are IP-relative however, and have a 24-bit immediate value. So we can -jump to functions that set a register to the needed value. (r3 is the -return-value register and so that's what is generally used here.) */ - -// isPPC64LEAPair recognises an addis+addi pair that's adding the offset of -// source to relative and writing the result to target. -func (d *delocation) isPPC64LEAPair(statement *node32) (target, source, relative string, ok bool) { - instruction := skipWS(statement.up).up - assertNodeType(instruction, ruleInstructionName) - name1 := d.contents(instruction) - args1 := instructionArgs(instruction.next) - - statement = statement.next - instruction = skipWS(statement.up).up - assertNodeType(instruction, ruleInstructionName) - name2 := d.contents(instruction) - args2 := instructionArgs(instruction.next) - - if name1 != "addis" || - len(args1) != 3 || - name2 != "addi" || - len(args2) != 3 { - return "", "", "", false - } - - target = d.contents(args1[0]) - relative = d.contents(args1[1]) - source1 := d.contents(args1[2]) - source2 := d.contents(args2[2]) - - if !strings.HasSuffix(source1, "@ha") || - !strings.HasSuffix(source2, "@l") || - source1[:len(source1)-3] != source2[:len(source2)-2] || - d.contents(args2[0]) != target || - d.contents(args2[1]) != target { - return "", "", "", false - } - - source = source1[:len(source1)-3] - ok = true - return -} - -// establishTOC writes the global entry prelude for a function. The standard -// prelude involves relocations so this version moves the relocation outside -// the integrity-checked area. -func establishTOC(w stringWriter) { - w.WriteString("999:\n") - w.WriteString("\taddis 2, 12, .LBORINGSSL_external_toc-999b@ha\n") - w.WriteString("\taddi 2, 2, .LBORINGSSL_external_toc-999b@l\n") - w.WriteString("\tld 12, 0(2)\n") - w.WriteString("\tadd 2, 2, 12\n") -} - -// loadTOCFuncName returns the name of a synthesized function that sets r3 to -// the value of “symbol+offset”. -func loadTOCFuncName(symbol, offset string) string { - symbol = strings.Replace(symbol, ".", "_dot_", -1) - ret := ".Lbcm_loadtoc_" + symbol - if len(offset) != 0 { - offset = strings.Replace(offset, "+", "_plus_", -1) - offset = strings.Replace(offset, "-", "_minus_", -1) - ret += "_" + offset - } - return ret -} - -func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc { - d.tocLoaders[symbol+"\x00"+offset] = struct{}{} - - return func(k func()) { - w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone. - w.WriteString("\tmflr " + dest + "\n") // Stash the link register. - w.WriteString("\tstd " + dest + ", -8(1)\n") - // The TOC loader will use r3, so stash it if necessary. - if dest != "3" { - w.WriteString("\tstd 3, -16(1)\n") - } - - // Because loadTOCFuncName returns a “.L” name, we don't need a - // nop after this call. - w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n") - - // Cycle registers around. We need r3 -> destReg, -8(1) -> - // lr and, optionally, -16(1) -> r3. - w.WriteString("\tstd 3, -24(1)\n") - w.WriteString("\tld 3, -8(1)\n") - w.WriteString("\tmtlr 3\n") - w.WriteString("\tld " + dest + ", -24(1)\n") - if dest != "3" { - w.WriteString("\tld 3, -16(1)\n") - } - w.WriteString("\taddi 1, 1, 288\n") - - k() - } -} - -func (d *delocation) gatherOffsets(symRef *node32, offsets string) (*node32, string) { - for symRef != nil && symRef.pegRule == ruleOffset { - offset := d.contents(symRef) - if offset[0] != '+' && offset[0] != '-' { - offset = "+" + offset - } - offsets = offsets + offset - symRef = symRef.next - } - return symRef, offsets -} - -func (d *delocation) parseMemRef(memRef *node32) (symbol, offset, section string, didChange, symbolIsLocal bool, nextRef *node32) { - if memRef.pegRule != ruleSymbolRef { - return "", "", "", false, false, memRef - } - - symRef := memRef.up - nextRef = memRef.next - - // (Offset* '+')? - symRef, offset = d.gatherOffsets(symRef, offset) - - // (LocalSymbol / SymbolName) - symbol = d.contents(symRef) - if symRef.pegRule == ruleLocalSymbol { - symbolIsLocal = true - mapped := d.mapLocalSymbol(symbol) - if mapped != symbol { - symbol = mapped - didChange = true - } - } - symRef = symRef.next - - // Offset* - symRef, offset = d.gatherOffsets(symRef, offset) - - // ('@' Section / Offset*)? - if symRef != nil { - assertNodeType(symRef, ruleSection) - section = d.contents(symRef) - symRef = symRef.next - - symRef, offset = d.gatherOffsets(symRef, offset) - } - - if symRef != nil { - panic(fmt.Sprintf("unexpected token in SymbolRef: %q", rul3s[symRef.pegRule])) - } - - return -} - -func (d *delocation) processPPCInstruction(statement, instruction *node32) (*node32, error) { - assertNodeType(instruction, ruleInstructionName) - instructionName := d.contents(instruction) - isBranch := instructionName[0] == 'b' - - argNodes := instructionArgs(instruction.next) - - var wrappers wrapperStack - var args []string - changed := false - -Args: - for i, arg := range argNodes { - fullArg := arg - isIndirect := false - - if arg.pegRule == ruleIndirectionIndicator { - arg = arg.next - isIndirect = true - } - - switch arg.pegRule { - case ruleRegisterOrConstant, ruleLocalLabelRef: - args = append(args, d.contents(fullArg)) - - case ruleTOCRefLow: - return nil, errors.New("Found low TOC reference outside preamble pattern") - - case ruleTOCRefHigh: - target, _, relative, ok := d.isPPC64LEAPair(statement) - if !ok { - return nil, errors.New("Found high TOC reference outside preamble pattern") - } - - if relative != "12" { - return nil, fmt.Errorf("preamble is relative to %q, not r12", relative) - } - - if target != "2" { - return nil, fmt.Errorf("preamble is setting %q, not r2", target) - } - - statement = statement.next - establishTOC(d.output) - instructionName = "" - changed = true - break Args - - case ruleMemoryRef: - symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up) - changed = didChange - - if len(symbol) > 0 { - if _, localEntrySymbol := d.localEntrySymbols[symbol]; localEntrySymbol && isBranch { - symbol = localEntryName(symbol) - changed = true - } else if _, knownSymbol := d.symbols[symbol]; knownSymbol { - symbol = localTargetName(symbol) - changed = true - } else if !symbolIsLocal && !isSynthesized(symbol) && len(section) == 0 { - changed = true - d.redirectors[symbol] = redirectorName(symbol) - symbol = redirectorName(symbol) - // TODO(davidben): This should sanity-check the next - // instruction is a nop and ideally remove it. - wrappers = append(wrappers, func(k func()) { - k() - // Like the linker's PLT stubs, redirector functions - // expect callers to restore r2. - d.output.WriteString("\tld 2, 24(1)\n") - }) - } - } - - switch section { - case "": - - case "tls": - // This section identifier just tells the - // assembler to use r13, the pointer to the - // thread-local data [PABI;3.7.3.3]. - - case "toc@ha": - // Delete toc@ha instructions. Per - // [PABI;3.6.3], the linker is allowed to erase - // toc@ha instructions. We take advantage of - // this by unconditionally erasing the toc@ha - // instructions and doing the full lookup when - // processing toc@l. - // - // Note that any offset here applies before @ha - // and @l. That is, 42+foo@toc@ha is - // #ha(42+foo-.TOC.), not 42+#ha(foo-.TOC.). Any - // corresponding toc@l references are required - // by the ABI to have the same offset. The - // offset will be incorporated in full when - // those are processed. - if instructionName != "addis" || len(argNodes) != 3 || i != 2 || args[1] != "2" { - return nil, errors.New("can't process toc@ha reference") - } - changed = true - instructionName = "" - break Args - - case "toc@l": - // Per [PAB;3.6.3], this instruction must take - // as input a register which was the output of - // a toc@ha computation and compute the actual - // address of some symbol. The toc@ha - // computation was elided, so we ignore that - // input register and compute the address - // directly. - changed = true - - // For all supported toc@l instructions, the - // destination register is the first argument. - destReg := args[0] - - wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg)) - switch instructionName { - case "addi": - // The original instruction was: - // addi destReg, tocHaReg, offset+symbol@toc@l - instructionName = "" - - case "ld", "lhz", "lwz": - // The original instruction was: - // l?? destReg, offset+symbol@toc@l(tocHaReg) - // - // We transform that into the - // equivalent dereference of destReg: - // l?? destReg, 0(destReg) - origInstructionName := instructionName - instructionName = "" - - assertNodeType(memRef, ruleBaseIndexScale) - assertNodeType(memRef.up, ruleRegisterOrConstant) - if memRef.next != nil || memRef.up.next != nil { - return nil, errors.New("expected single register in BaseIndexScale for ld argument") - } - - baseReg := destReg - if baseReg == "0" { - // Register zero is special as the base register for a load. - // Avoid it by spilling and using r3 instead. - baseReg = "3" - wrappers = append(wrappers, func(k func()) { - d.output.WriteString("\taddi 1, 1, -288\n") // Clear the red zone. - d.output.WriteString("\tstd " + baseReg + ", -8(1)\n") - d.output.WriteString("\tmr " + baseReg + ", " + destReg + "\n") - k() - d.output.WriteString("\tld " + baseReg + ", -8(1)\n") - d.output.WriteString("\taddi 1, 1, 288\n") // Clear the red zone. - }) - } - - wrappers = append(wrappers, func(k func()) { - d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + baseReg + ")\n") - }) - default: - return nil, fmt.Errorf("can't process TOC argument to %q", instructionName) - } - - default: - return nil, fmt.Errorf("Unknown section type %q", section) - } - - argStr := "" - if isIndirect { - argStr += "*" - } - argStr += symbol - if len(offset) > 0 { - argStr += offset - } - if len(section) > 0 { - argStr += "@" - argStr += section - } - - for ; memRef != nil; memRef = memRef.next { - argStr += d.contents(memRef) - } - - args = append(args, argStr) - - default: - panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule])) - } - } - - if changed { - d.writeCommentedNode(statement) - - var replacement string - if len(instructionName) > 0 { - replacement = "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n" - } - - wrappers.do(func() { - d.output.WriteString(replacement) - }) - } else { - d.writeNode(statement) - } - - return statement, nil -} - -/* Intel */ - -type instructionType int - -const ( - instrPush instructionType = iota - instrMove - // instrTransformingMove is essentially a move, but it performs some - // transformation of the data during the process. - instrTransformingMove - instrJump - instrConditionalMove - // instrCombine merges the source and destination in some fashion, for example - // a 2-operand bitwise operation. - instrCombine - instrOther -) - -func classifyInstruction(instr string, args []*node32) instructionType { - switch instr { - case "push", "pushq": - if len(args) == 1 { - return instrPush - } - - case "mov", "movq", "vmovq", "movsd", "vmovsd": - if len(args) == 2 { - return instrMove - } - - case "cmovneq", "cmoveq": - if len(args) == 2 { - return instrConditionalMove - } - - case "call", "callq", "jmp", "jo", "jno", "js", "jns", "je", "jz", "jne", "jnz", "jb", "jnae", "jc", "jnb", "jae", "jnc", "jbe", "jna", "ja", "jnbe", "jl", "jnge", "jge", "jnl", "jle", "jng", "jg", "jnle", "jp", "jpe", "jnp", "jpo": - if len(args) == 1 { - return instrJump - } - - case "orq", "andq", "xorq": - if len(args) == 2 { - return instrCombine - } - - case "vpbroadcastq": - if len(args) == 2 { - return instrTransformingMove - } - } - - return instrOther -} - -func push(w stringWriter) wrapperFunc { - return func(k func()) { - w.WriteString("\tpushq %rax\n") - k() - w.WriteString("\txchg %rax, (%rsp)\n") - } -} - -func (d *delocation) loadFromGOT(w stringWriter, destination, symbol, section string, redzoneCleared bool) wrapperFunc { - d.gotExternalsNeeded[symbol+"@"+section] = struct{}{} - - return func(k func()) { - if !redzoneCleared { - w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. - } - w.WriteString("\tpushf\n") - w.WriteString(fmt.Sprintf("\tleaq %s_%s_external(%%rip), %s\n", symbol, section, destination)) - w.WriteString(fmt.Sprintf("\taddq (%s), %s\n", destination, destination)) - w.WriteString(fmt.Sprintf("\tmovq (%s), %s\n", destination, destination)) - w.WriteString("\tpopf\n") - if !redzoneCleared { - w.WriteString("\tleaq\t128(%rsp), %rsp\n") - } - } -} - -func saveFlags(w stringWriter, redzoneCleared bool) wrapperFunc { - return func(k func()) { - if !redzoneCleared { - w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. - defer w.WriteString("\tleaq 128(%rsp), %rsp\n") - } - w.WriteString("\tpushfq\n") - k() - w.WriteString("\tpopfq\n") - } -} - -func saveRegister(w stringWriter, avoidReg string) (wrapperFunc, string) { - reg := "%rax" - if reg == avoidReg { - reg = "%rbx" - } - - return func(k func()) { - w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. - w.WriteString("\tpushq " + reg + "\n") - k() - w.WriteString("\tpopq " + reg + "\n") - w.WriteString("\tleaq 128(%rsp), %rsp\n") - }, reg -} - -func moveTo(w stringWriter, target string, isAVX bool, source string) wrapperFunc { - return func(k func()) { - k() - prefix := "" - if isAVX { - prefix = "v" - } - w.WriteString("\t" + prefix + "movq " + source + ", " + target + "\n") - } -} - -func finalTransform(w stringWriter, transformInstruction, reg string) wrapperFunc { - return func(k func()) { - k() - w.WriteString("\t" + transformInstruction + " " + reg + ", " + reg + "\n") - } -} - -func combineOp(w stringWriter, instructionName, source, dest string) wrapperFunc { - return func(k func()) { - k() - w.WriteString("\t" + instructionName + " " + source + ", " + dest + "\n") - } -} - -func isValidLEATarget(reg string) bool { - return !strings.HasPrefix(reg, "%xmm") && !strings.HasPrefix(reg, "%ymm") && !strings.HasPrefix(reg, "%zmm") -} - -func undoConditionalMove(w stringWriter, instr string) wrapperFunc { - var invertedCondition string - - switch instr { - case "cmoveq": - invertedCondition = "ne" - case "cmovneq": - invertedCondition = "e" - default: - panic(fmt.Sprintf("don't know how to handle conditional move instruction %q", instr)) - } - - return func(k func()) { - w.WriteString("\tj" + invertedCondition + " 999f\n") - k() - w.WriteString("999:\n") - } -} - -func (d *delocation) isRIPRelative(node *node32) bool { - return node != nil && node.pegRule == ruleBaseIndexScale && d.contents(node) == "(%rip)" -} - -func (d *delocation) processIntelInstruction(statement, instruction *node32) (*node32, error) { - assertNodeType(instruction, ruleInstructionName) - instructionName := d.contents(instruction) - - argNodes := instructionArgs(instruction.next) - - var wrappers wrapperStack - var args []string - changed := false - -Args: - for i, arg := range argNodes { - fullArg := arg - isIndirect := false - - if arg.pegRule == ruleIndirectionIndicator { - arg = arg.next - isIndirect = true - } - - switch arg.pegRule { - case ruleRegisterOrConstant, ruleLocalLabelRef: - args = append(args, d.contents(fullArg)) - - case ruleMemoryRef: - symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up) - changed = didChange - - if symbol == "OPENSSL_ia32cap_P" && section == "" { - if instructionName != "leaq" { - return nil, fmt.Errorf("non-leaq instruction %q referenced OPENSSL_ia32cap_P directly", instructionName) - } - - if i != 0 || len(argNodes) != 2 || !d.isRIPRelative(memRef) || len(offset) > 0 { - return nil, fmt.Errorf("invalid OPENSSL_ia32cap_P reference in instruction %q", instructionName) - } - - target := argNodes[1] - assertNodeType(target, ruleRegisterOrConstant) - reg := d.contents(target) - - if !strings.HasPrefix(reg, "%r") { - return nil, fmt.Errorf("tried to load OPENSSL_ia32cap_P into %q, which is not a standard register.", reg) - } - - changed = true - - // Flag-altering instructions (i.e. addq) are going to be used so the - // flags need to be preserved. - wrappers = append(wrappers, saveFlags(d.output, false /* Red Zone not yet cleared */)) - - wrappers = append(wrappers, func(k func()) { - d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + reg + "\n") - d.output.WriteString("\taddq\t(" + reg + "), " + reg + "\n") - }) - - break Args - } - - switch section { - case "": - if _, knownSymbol := d.symbols[symbol]; knownSymbol { - symbol = localTargetName(symbol) - changed = true - } - - case "PLT": - if classifyInstruction(instructionName, argNodes) != instrJump { - return nil, fmt.Errorf("Cannot rewrite PLT reference for non-jump instruction %q", instructionName) - } - - if _, knownSymbol := d.symbols[symbol]; knownSymbol { - symbol = localTargetName(symbol) - changed = true - } else if !symbolIsLocal && !isSynthesized(symbol) { - // Unknown symbol via PLT is an - // out-call from the module, e.g. - // memcpy. - d.redirectors[symbol+"@"+section] = redirectorName(symbol) - symbol = redirectorName(symbol) - } - - changed = true - - case "GOTPCREL": - if len(offset) > 0 { - return nil, errors.New("loading from GOT with offset is unsupported") - } - if i != 0 { - return nil, errors.New("GOT access must be source operand") - } - if !d.isRIPRelative(memRef) { - return nil, errors.New("GOT access must be IP-relative") - } - - useGOT := false - if _, knownSymbol := d.symbols[symbol]; knownSymbol { - symbol = localTargetName(symbol) - changed = true - } else if !isSynthesized(symbol) { - useGOT = true - } - - // Reduce the instruction to movq symbol@GOTPCREL, targetReg. - var targetReg string - var redzoneCleared bool - switch classifyInstruction(instructionName, argNodes) { - case instrPush: - wrappers = append(wrappers, push(d.output)) - targetReg = "%rax" - case instrConditionalMove: - wrappers = append(wrappers, undoConditionalMove(d.output, instructionName)) - fallthrough - case instrMove: - assertNodeType(argNodes[1], ruleRegisterOrConstant) - targetReg = d.contents(argNodes[1]) - case instrTransformingMove: - assertNodeType(argNodes[1], ruleRegisterOrConstant) - targetReg = d.contents(argNodes[1]) - wrappers = append(wrappers, finalTransform(d.output, instructionName, targetReg)) - if isValidLEATarget(targetReg) { - return nil, errors.New("Currently transforming moves are assumed to target XMM registers. Otherwise we'll pop %rax before reading it to do the transform.") - } - case instrCombine: - targetReg = d.contents(argNodes[1]) - if !isValidLEATarget(targetReg) { - return nil, fmt.Errorf("cannot handle combining instructions targeting non-general registers") - } - saveRegWrapper, tempReg := saveRegister(d.output, targetReg) - redzoneCleared = true - wrappers = append(wrappers, saveRegWrapper) - - wrappers = append(wrappers, combineOp(d.output, instructionName, tempReg, targetReg)) - targetReg = tempReg - default: - return nil, fmt.Errorf("Cannot rewrite GOTPCREL reference for instruction %q", instructionName) - } - - if !isValidLEATarget(targetReg) { - // Sometimes the compiler will load from the GOT to an - // XMM register, which is not a valid target of an LEA - // instruction. - saveRegWrapper, tempReg := saveRegister(d.output, "") - wrappers = append(wrappers, saveRegWrapper) - isAVX := strings.HasPrefix(instructionName, "v") - wrappers = append(wrappers, moveTo(d.output, targetReg, isAVX, tempReg)) - targetReg = tempReg - if redzoneCleared { - return nil, fmt.Errorf("internal error: Red Zone was already cleared") - } - redzoneCleared = true - } - - if symbol == "OPENSSL_ia32cap_P" { - // Flag-altering instructions (i.e. addq) are going to be used so the - // flags need to be preserved. - wrappers = append(wrappers, saveFlags(d.output, redzoneCleared)) - wrappers = append(wrappers, func(k func()) { - d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + targetReg + "\n") - d.output.WriteString("\taddq\t(" + targetReg + "), " + targetReg + "\n") - }) - } else if useGOT { - wrappers = append(wrappers, d.loadFromGOT(d.output, targetReg, symbol, section, redzoneCleared)) - } else { - wrappers = append(wrappers, func(k func()) { - d.output.WriteString(fmt.Sprintf("\tleaq\t%s(%%rip), %s\n", symbol, targetReg)) - }) - } - changed = true - break Args - - default: - return nil, fmt.Errorf("Unknown section type %q", section) - } - - if !changed && len(section) > 0 { - panic("section was not handled") - } - section = "" - - argStr := "" - if isIndirect { - argStr += "*" - } - argStr += symbol - argStr += offset - - for ; memRef != nil; memRef = memRef.next { - argStr += d.contents(memRef) - } - - args = append(args, argStr) - - default: - panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule])) - } - } - - if changed { - d.writeCommentedNode(statement) - replacement := "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n" - wrappers.do(func() { - d.output.WriteString(replacement) - }) - } else { - d.writeNode(statement) - } - - return statement, nil -} - -func (d *delocation) handleBSS(statement *node32) (*node32, error) { - lastStatement := statement - for statement = statement.next; statement != nil; lastStatement, statement = statement, statement.next { - node := skipWS(statement.up) - if node == nil { - d.writeNode(statement) - continue - } - - switch node.pegRule { - case ruleGlobalDirective, ruleComment, ruleInstruction, ruleLocationDirective: - d.writeNode(statement) - - case ruleDirective: - directive := node.up - assertNodeType(directive, ruleDirectiveName) - directiveName := d.contents(directive) - if directiveName == "text" || directiveName == "section" || directiveName == "data" { - return lastStatement, nil - } - d.writeNode(statement) - - case ruleLabel: - label := node.up - d.writeNode(statement) - - if label.pegRule != ruleLocalSymbol { - symbol := d.contents(label) - localSymbol := localTargetName(symbol) - d.output.WriteString(fmt.Sprintf("\n%s:\n", localSymbol)) - - d.bssAccessorsNeeded[symbol] = localSymbol - } - - case ruleLabelContainingDirective: - var err error - statement, err = d.processLabelContainingDirective(statement, node.up) - if err != nil { - return nil, err - } - - default: - return nil, fmt.Errorf("unknown BSS statement type %q in %q", rul3s[node.pegRule], d.contents(statement)) - } - } - - return lastStatement, nil -} - -func transform(w stringWriter, inputs []inputFile) error { - // symbols contains all defined symbols. - symbols := make(map[string]struct{}) - // localEntrySymbols contains all symbols with a .localentry directive. - localEntrySymbols := make(map[string]struct{}) - // fileNumbers is the set of IDs seen in .file directives. - fileNumbers := make(map[int]struct{}) - // maxObservedFileNumber contains the largest seen file number in a - // .file directive. Zero is not a valid number. - maxObservedFileNumber := 0 - - for _, input := range inputs { - forEachPath(input.ast.up, func(node *node32) { - symbol := input.contents[node.begin:node.end] - if _, ok := symbols[symbol]; ok { - panic(fmt.Sprintf("Duplicate symbol found: %q in %q", symbol, input.path)) - } - symbols[symbol] = struct{}{} - }, ruleStatement, ruleLabel, ruleSymbolName) - - forEachPath(input.ast.up, func(node *node32) { - node = node.up - assertNodeType(node, ruleLabelContainingDirectiveName) - directive := input.contents[node.begin:node.end] - if directive != ".localentry" { - return - } - // Extract the first argument. - node = skipWS(node.next) - assertNodeType(node, ruleSymbolArgs) - node = node.up - assertNodeType(node, ruleSymbolArg) - symbol := input.contents[node.begin:node.end] - if _, ok := localEntrySymbols[symbol]; ok { - panic(fmt.Sprintf("Duplicate .localentry directive found: %q in %q", symbol, input.path)) - } - localEntrySymbols[symbol] = struct{}{} - }, ruleStatement, ruleLabelContainingDirective) - - forEachPath(input.ast.up, func(node *node32) { - assertNodeType(node, ruleLocationDirective) - directive := input.contents[node.begin:node.end] - if !strings.HasPrefix(directive, ".file") { - return - } - parts := strings.Fields(directive) - if len(parts) == 2 { - // This is a .file directive with just a - // filename. Clang appears to generate just one - // of these at the beginning of the output for - // the compilation unit. Ignore it. - return - } - fileNo, err := strconv.Atoi(parts[1]) - if err != nil { - panic(fmt.Sprintf("Failed to parse file number from .file: %q", directive)) - } - - if _, ok := fileNumbers[fileNo]; ok { - panic(fmt.Sprintf("Duplicate file number %d observed", fileNo)) - } - fileNumbers[fileNo] = struct{}{} - - if fileNo > maxObservedFileNumber { - maxObservedFileNumber = fileNo - } - }, ruleStatement, ruleLocationDirective) - } - - processor := x86_64 - if len(inputs) > 0 { - processor = detectProcessor(inputs[0]) - } - - d := &delocation{ - symbols: symbols, - localEntrySymbols: localEntrySymbols, - processor: processor, - output: w, - redirectors: make(map[string]string), - bssAccessorsNeeded: make(map[string]string), - tocLoaders: make(map[string]struct{}), - gotExternalsNeeded: make(map[string]struct{}), - } - - w.WriteString(".text\n") - w.WriteString(fmt.Sprintf(".file %d \"inserted_by_delocate.c\"\n", maxObservedFileNumber+1)) - w.WriteString(fmt.Sprintf(".loc %d 1 0\n", maxObservedFileNumber+1)) - w.WriteString("BORINGSSL_bcm_text_start:\n") - - for _, input := range inputs { - if err := d.processInput(input); err != nil { - return err - } - } - - w.WriteString(".text\n") - w.WriteString(fmt.Sprintf(".loc %d 2 0\n", maxObservedFileNumber+1)) - w.WriteString("BORINGSSL_bcm_text_end:\n") - - // Emit redirector functions. Each is a single jump instruction. - var redirectorNames []string - for name := range d.redirectors { - redirectorNames = append(redirectorNames, name) - } - sort.Strings(redirectorNames) - - for _, name := range redirectorNames { - redirector := d.redirectors[name] - if d.processor == ppc64le { - w.WriteString(".section \".toc\", \"aw\"\n") - w.WriteString(".Lredirector_toc_" + name + ":\n") - w.WriteString(".quad " + name + "\n") - w.WriteString(".text\n") - w.WriteString(".type " + redirector + ", @function\n") - w.WriteString(redirector + ":\n") - // |name| will clobber r2, so save it. This is matched by a restore in - // redirector calls. - w.WriteString("\tstd 2, 24(1)\n") - // Load and call |name|'s global entry point. - w.WriteString("\taddis 12, 2, .Lredirector_toc_" + name + "@toc@ha\n") - w.WriteString("\tld 12, .Lredirector_toc_" + name + "@toc@l(12)\n") - w.WriteString("\tmtctr 12\n") - w.WriteString("\tbctr\n") - } else { - w.WriteString(".type " + redirector + ", @function\n") - w.WriteString(redirector + ":\n") - w.WriteString("\tjmp\t" + name + "\n") - } - } - - var accessorNames []string - for accessor := range d.bssAccessorsNeeded { - accessorNames = append(accessorNames, accessor) - } - sort.Strings(accessorNames) - - // Emit BSS accessor functions. Each is a single LEA followed by RET. - for _, name := range accessorNames { - funcName := accessorName(name) - w.WriteString(".type " + funcName + ", @function\n") - w.WriteString(funcName + ":\n") - target := d.bssAccessorsNeeded[name] - - if d.processor == ppc64le { - w.WriteString("\taddis 3, 2, " + target + "@toc@ha\n") - w.WriteString("\taddi 3, 3, " + target + "@toc@l\n") - w.WriteString("\tblr\n") - } else { - w.WriteString("\tleaq\t" + target + "(%rip), %rax\n\tret\n") - } - } - - if d.processor == ppc64le { - loadTOCNames := sortedSet(d.tocLoaders) - for _, symbolAndOffset := range loadTOCNames { - parts := strings.SplitN(symbolAndOffset, "\x00", 2) - symbol, offset := parts[0], parts[1] - - funcName := loadTOCFuncName(symbol, offset) - ref := symbol + offset - - w.WriteString(".type " + funcName[2:] + ", @function\n") - w.WriteString(funcName[2:] + ":\n") - w.WriteString(funcName + ":\n") - w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n") - w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n") - w.WriteString("\tblr\n") - } - - w.WriteString(".LBORINGSSL_external_toc:\n") - w.WriteString(".quad .TOC.-.LBORINGSSL_external_toc\n") - } else { - externalNames := sortedSet(d.gotExternalsNeeded) - for _, name := range externalNames { - parts := strings.SplitN(name, "@", 2) - symbol, section := parts[0], parts[1] - w.WriteString(".type " + symbol + "_" + section + "_external, @object\n") - w.WriteString(".size " + symbol + "_" + section + "_external, 8\n") - w.WriteString(symbol + "_" + section + "_external:\n") - // Ideally this would be .quad foo@GOTPCREL, but clang's - // assembler cannot emit a 64-bit GOTPCREL relocation. Instead, - // we manually sign-extend the value, knowing that the GOT is - // always at the end, thus foo@GOTPCREL has a positive value. - w.WriteString("\t.long " + symbol + "@" + section + "\n") - w.WriteString("\t.long 0\n") - } - - w.WriteString(".type OPENSSL_ia32cap_get, @function\n") - w.WriteString("OPENSSL_ia32cap_get:\n") - w.WriteString("\tleaq OPENSSL_ia32cap_P(%rip), %rax\n") - w.WriteString("\tret\n") - - w.WriteString(".extern OPENSSL_ia32cap_P\n") - w.WriteString(".type OPENSSL_ia32cap_addr_delta, @object\n") - w.WriteString(".size OPENSSL_ia32cap_addr_delta, 8\n") - w.WriteString("OPENSSL_ia32cap_addr_delta:\n") - w.WriteString(".quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta\n") - } - - 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 { - w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n") - } - - return nil -} - -func parseInputs(inputs []inputFile) error { - for i, input := range inputs { - var contents string - - if input.isArchive { - arFile, err := os.Open(input.path) - if err != nil { - return err - } - defer arFile.Close() - - ar, err := ParseAR(arFile) - if err != nil { - return err - } - - if len(ar) != 1 { - return fmt.Errorf("expected one file in archive, but found %d", len(ar)) - } - - for _, c := range ar { - contents = string(c) - } - } else { - inBytes, err := ioutil.ReadFile(input.path) - if err != nil { - return err - } - - contents = string(inBytes) - } - - asm := Asm{Buffer: contents, Pretty: true} - asm.Init() - if err := asm.Parse(); err != nil { - return fmt.Errorf("error while parsing %q: %s", input.path, err) - } - ast := asm.AST() - - inputs[i].contents = contents - inputs[i].ast = ast - } - - return nil -} - -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") - - flag.Parse() - - if len(*outFile) == 0 { - fmt.Fprintf(os.Stderr, "Must give argument to -o.\n") - os.Exit(1) - } - - var inputs []inputFile - if len(*arInput) > 0 { - inputs = append(inputs, inputFile{ - path: *arInput, - index: 0, - isArchive: true, - }) - } - - for i, path := range flag.Args() { - if len(path) == 0 { - continue - } - - inputs = append(inputs, inputFile{ - path: path, - index: i + 1, - }) - } - - if err := parseInputs(inputs); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } - - out, err := os.OpenFile(*outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) - if err != nil { - panic(err) - } - defer out.Close() - - if err := transform(out, inputs); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } -} - -func forEachPath(node *node32, cb func(*node32), rules ...pegRule) { - if node == nil { - return - } - - if len(rules) == 0 { - cb(node) - return - } - - rule := rules[0] - childRules := rules[1:] - - for ; node != nil; node = node.next { - if node.pegRule != rule { - continue - } - - if len(childRules) == 0 { - cb(node) - } else { - forEachPath(node.up, cb, childRules...) - } - } -} - -func skipNodes(node *node32, ruleToSkip pegRule) *node32 { - for ; node != nil && node.pegRule == ruleToSkip; node = node.next { - } - return node -} - -func skipWS(node *node32) *node32 { - return skipNodes(node, ruleWS) -} - -func assertNodeType(node *node32, expected pegRule) { - if rule := node.pegRule; rule != expected { - panic(fmt.Sprintf("node was %q, but wanted %q", rul3s[rule], rul3s[expected])) - } -} - -type wrapperFunc func(func()) - -type wrapperStack []wrapperFunc - -func (w *wrapperStack) do(baseCase func()) { - if len(*w) == 0 { - baseCase() - return - } - - wrapper := (*w)[0] - *w = (*w)[1:] - wrapper(func() { w.do(baseCase) }) -} - -// localTargetName returns the name of the local target label for a global -// symbol named name. -func localTargetName(name string) string { - return ".L" + name + "_local_target" -} - -func localEntryName(name string) string { - return ".L" + name + "_local_entry" -} - -func isSynthesized(symbol string) bool { - return strings.HasSuffix(symbol, "_bss_get") || - symbol == "OPENSSL_ia32cap_get" || - strings.HasPrefix(symbol, "BORINGSSL_bcm_text_") -} - -func redirectorName(symbol string) string { - return "bcm_redirector_" + symbol -} - -// sectionType returns the type of a section. I.e. a section called “.text.foo” -// is a “.text” section. -func sectionType(section string) (string, bool) { - if len(section) == 0 || section[0] != '.' { - return "", false - } - - i := strings.Index(section[1:], ".") - if i != -1 { - section = section[:i+1] - } - - if strings.HasPrefix(section, ".debug_") { - return ".debug", true - } - - return section, true -} - -// accessorName returns the name of the accessor function for a BSS symbol -// named name. -func accessorName(name string) string { - return name + "_bss_get" -} - -func (d *delocation) mapLocalSymbol(symbol string) string { - if d.currentInput.index == 0 { - return symbol - } - return symbol + "_BCM_" + strconv.Itoa(d.currentInput.index) -} - -func detectProcessor(input inputFile) processorType { - for statement := input.ast.up; statement != nil; statement = statement.next { - node := skipNodes(statement.up, ruleWS) - if node == nil || node.pegRule != ruleInstruction { - continue - } - - instruction := node.up - instructionName := input.contents[instruction.begin:instruction.end] - - switch instructionName { - case "movq", "call", "leaq": - return x86_64 - case "addis", "addi", "mflr": - return ppc64le - } - } - - panic("processed entire input and didn't recognise any instructions.") -} - -func sortedSet(m map[string]struct{}) []string { - ret := make([]string, 0, len(m)) - for key := range m { - ret = append(ret, key) - } - sort.Strings(ret) - return ret -} diff --git a/src/util/fipstools/delocate.peg b/src/util/fipstools/delocate.peg deleted file mode 100644 index 3dcead2d..00000000 --- a/src/util/fipstools/delocate.peg +++ /dev/null @@ -1,80 +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. */ - -# This is a rough parser for x86-64 and ppc64le assembly designed to work with -# https://github.com/pointlander/peg. delocate.go has a go:generate line for -# rebuilding delocate.peg.go from this file. - -package main - -type Asm Peg {} - -AsmFile <- Statement* !. -Statement <- WS? (Label / ((GlobalDirective / - LocationDirective / - LabelContainingDirective / - Instruction / - Directive / - Comment / ) WS? ((Comment? '\n') / ';'))) -GlobalDirective <- (".global" / ".globl") WS SymbolName -Directive <- '.' DirectiveName (WS Args)? -DirectiveName <- [[A-Z0-9_]]+ -LocationDirective <- (".file" / ".loc") WS [^#\n]+ -Args <- Arg ((WS? ',' WS?) Arg)* -Arg <- QuotedArg / [[0-9a-z%+\-*_@.]]* -QuotedArg <- '"' QuotedText '"' -QuotedText <- (EscapedChar / [^"])* -LabelContainingDirective <- LabelContainingDirectiveName WS SymbolArgs -LabelContainingDirectiveName <- ".long" / ".set" / ".8byte" / ".4byte" / ".quad" / ".tc" / ".localentry" / ".size" / ".type" -SymbolArgs <- SymbolArg ((WS? ',' WS?) SymbolArg)* -SymbolArg <- Offset / - SymbolType / - (Offset / LocalSymbol / SymbolName / Dot) WS? Operator WS? (Offset / LocalSymbol / SymbolName) / - LocalSymbol TCMarker? / - SymbolName Offset / - SymbolName TCMarker? -SymbolType <- '@function' / '@object' -Dot <- '.' -TCMarker <- '[TC]' -EscapedChar <- '\\' . -WS <- [ \t]+ -Comment <- '#' [^\n]* -Label <- (LocalSymbol / LocalLabel / SymbolName) ':' -SymbolName <- [[A-Z._]][[A-Z.0-9$_]]* -LocalSymbol <- '.L' [[A-Z.0-9$_]]+ -LocalLabel <- [0-9][0-9$]* -LocalLabelRef <- [0-9][0-9$]*[bf] -Instruction <- InstructionName (WS InstructionArg ((WS? ',' WS?) InstructionArg)*)? (WS? '{' InstructionArg '}')* -InstructionName <- [[A-Z]][[A-Z0-9]]* [.+\-]? -InstructionArg <- IndirectionIndicator? (RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / MemoryRef) -TOCRefHigh <- '.TOC.-' ('0b' / ('.L' [a-zA-Z_0-9]+)) "@ha" -TOCRefLow <- '.TOC.-' ('0b' / ('.L' [a-zA-Z_0-9]+)) "@l" -IndirectionIndicator <- '*' -RegisterOrConstant <- (('%'[[A-Z]][[A-Z0-9]]*) / ('$'? ((Offset Offset) / Offset))) ![fb:(+\-] -# Compilers only output a very limited number of expression forms. Rather than -# implement a full expression parser, this enumerate those forms plus a few -# that appear in our hand-written assembly. -MemoryRef <- (SymbolRef BaseIndexScale / - SymbolRef / - Offset* BaseIndexScale / - SegmentRegister Offset BaseIndexScale / - SegmentRegister BaseIndexScale / - SegmentRegister Offset / - BaseIndexScale) -SymbolRef <- (Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)? -BaseIndexScale <- '(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)? )? ')' -Operator <- [+\-] -Offset <- '+'? '-'? (("0b" [01]+) / ("0x" [[0-9A-F]]+) / [0-9]+) -Section <- [[A-Z@]]+ -SegmentRegister <- '%' [c-gs] 's:' diff --git a/src/util/fipstools/delocate.peg.go b/src/util/fipstools/delocate.peg.go deleted file mode 100644 index f0ad78f6..00000000 --- a/src/util/fipstools/delocate.peg.go +++ /dev/null @@ -1,4017 +0,0 @@ -package main - -//go:generate peg delocate.peg - -import ( - "fmt" - "math" - "sort" - "strconv" -) - -const endSymbol rune = 1114112 - -/* The rule types inferred from the grammar are below. */ -type pegRule uint8 - -const ( - ruleUnknown pegRule = iota - ruleAsmFile - ruleStatement - ruleGlobalDirective - ruleDirective - ruleDirectiveName - ruleLocationDirective - ruleArgs - ruleArg - ruleQuotedArg - ruleQuotedText - ruleLabelContainingDirective - ruleLabelContainingDirectiveName - ruleSymbolArgs - ruleSymbolArg - ruleSymbolType - ruleDot - ruleTCMarker - ruleEscapedChar - ruleWS - ruleComment - ruleLabel - ruleSymbolName - ruleLocalSymbol - ruleLocalLabel - ruleLocalLabelRef - ruleInstruction - ruleInstructionName - ruleInstructionArg - ruleTOCRefHigh - ruleTOCRefLow - ruleIndirectionIndicator - ruleRegisterOrConstant - ruleMemoryRef - ruleSymbolRef - ruleBaseIndexScale - ruleOperator - ruleOffset - ruleSection - ruleSegmentRegister -) - -var rul3s = [...]string{ - "Unknown", - "AsmFile", - "Statement", - "GlobalDirective", - "Directive", - "DirectiveName", - "LocationDirective", - "Args", - "Arg", - "QuotedArg", - "QuotedText", - "LabelContainingDirective", - "LabelContainingDirectiveName", - "SymbolArgs", - "SymbolArg", - "SymbolType", - "Dot", - "TCMarker", - "EscapedChar", - "WS", - "Comment", - "Label", - "SymbolName", - "LocalSymbol", - "LocalLabel", - "LocalLabelRef", - "Instruction", - "InstructionName", - "InstructionArg", - "TOCRefHigh", - "TOCRefLow", - "IndirectionIndicator", - "RegisterOrConstant", - "MemoryRef", - "SymbolRef", - "BaseIndexScale", - "Operator", - "Offset", - "Section", - "SegmentRegister", -} - -type token32 struct { - pegRule - begin, end uint32 -} - -func (t *token32) String() string { - return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v", rul3s[t.pegRule], t.begin, t.end) -} - -type node32 struct { - token32 - up, next *node32 -} - -func (node *node32) print(pretty bool, buffer string) { - var print func(node *node32, depth int) - print = func(node *node32, depth int) { - for node != nil { - for c := 0; c < depth; c++ { - fmt.Printf(" ") - } - rule := rul3s[node.pegRule] - quote := strconv.Quote(string(([]rune(buffer)[node.begin:node.end]))) - if !pretty { - fmt.Printf("%v %v\n", rule, quote) - } else { - fmt.Printf("\x1B[34m%v\x1B[m %v\n", rule, quote) - } - if node.up != nil { - print(node.up, depth+1) - } - node = node.next - } - } - print(node, 0) -} - -func (node *node32) Print(buffer string) { - node.print(false, buffer) -} - -func (node *node32) PrettyPrint(buffer string) { - node.print(true, buffer) -} - -type tokens32 struct { - tree []token32 -} - -func (t *tokens32) Trim(length uint32) { - t.tree = t.tree[:length] -} - -func (t *tokens32) Print() { - for _, token := range t.tree { - fmt.Println(token.String()) - } -} - -func (t *tokens32) AST() *node32 { - type element struct { - node *node32 - down *element - } - tokens := t.Tokens() - var stack *element - for _, token := range tokens { - if token.begin == token.end { - continue - } - node := &node32{token32: token} - for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { - stack.node.next = node.up - node.up = stack.node - stack = stack.down - } - stack = &element{node: node, down: stack} - } - if stack != nil { - return stack.node - } - return nil -} - -func (t *tokens32) PrintSyntaxTree(buffer string) { - t.AST().Print(buffer) -} - -func (t *tokens32) PrettyPrintSyntaxTree(buffer string) { - t.AST().PrettyPrint(buffer) -} - -func (t *tokens32) Add(rule pegRule, begin, end, index uint32) { - if tree := t.tree; int(index) >= len(tree) { - expanded := make([]token32, 2*len(tree)) - copy(expanded, tree) - t.tree = expanded - } - t.tree[index] = token32{ - pegRule: rule, - begin: begin, - end: end, - } -} - -func (t *tokens32) Tokens() []token32 { - return t.tree -} - -type Asm struct { - Buffer string - buffer []rune - rules [40]func() bool - parse func(rule ...int) error - reset func() - Pretty bool - tokens32 -} - -func (p *Asm) Parse(rule ...int) error { - return p.parse(rule...) -} - -func (p *Asm) Reset() { - p.reset() -} - -type textPosition struct { - line, symbol int -} - -type textPositionMap map[int]textPosition - -func translatePositions(buffer []rune, positions []int) textPositionMap { - length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 - sort.Ints(positions) - -search: - for i, c := range buffer { - if c == '\n' { - line, symbol = line+1, 0 - } else { - symbol++ - } - if i == positions[j] { - translations[positions[j]] = textPosition{line, symbol} - for j++; j < length; j++ { - if i != positions[j] { - continue search - } - } - break search - } - } - - return translations -} - -type parseError struct { - p *Asm - max token32 -} - -func (e *parseError) Error() string { - tokens, error := []token32{e.max}, "\n" - positions, p := make([]int, 2*len(tokens)), 0 - for _, token := range tokens { - positions[p], p = int(token.begin), p+1 - positions[p], p = int(token.end), p+1 - } - translations := translatePositions(e.p.buffer, positions) - format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" - if e.p.Pretty { - format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" - } - for _, token := range tokens { - begin, end := int(token.begin), int(token.end) - error += fmt.Sprintf(format, - rul3s[token.pegRule], - translations[begin].line, translations[begin].symbol, - translations[end].line, translations[end].symbol, - strconv.Quote(string(e.p.buffer[begin:end]))) - } - - return error -} - -func (p *Asm) PrintSyntaxTree() { - if p.Pretty { - p.tokens32.PrettyPrintSyntaxTree(p.Buffer) - } else { - p.tokens32.PrintSyntaxTree(p.Buffer) - } -} - -func (p *Asm) Init() { - var ( - max token32 - position, tokenIndex uint32 - buffer []rune - ) - p.reset = func() { - max = token32{} - position, tokenIndex = 0, 0 - - p.buffer = []rune(p.Buffer) - if len(p.buffer) == 0 || p.buffer[len(p.buffer)-1] != endSymbol { - p.buffer = append(p.buffer, endSymbol) - } - buffer = p.buffer - } - p.reset() - - _rules := p.rules - tree := tokens32{tree: make([]token32, math.MaxInt16)} - p.parse = func(rule ...int) error { - r := 1 - if len(rule) > 0 { - r = rule[0] - } - matches := p.rules[r]() - p.tokens32 = tree - if matches { - p.Trim(tokenIndex) - return nil - } - return &parseError{p, max} - } - - add := func(rule pegRule, begin uint32) { - tree.Add(rule, begin, position, tokenIndex) - tokenIndex++ - if begin != position && position > max.end { - max = token32{rule, begin, position} - } - } - - matchDot := func() bool { - if buffer[position] != endSymbol { - position++ - return true - } - return false - } - - /*matchChar := func(c byte) bool { - if buffer[position] == c { - position++ - return true - } - return false - }*/ - - /*matchRange := func(lower byte, upper byte) bool { - if c := buffer[position]; c >= lower && c <= upper { - position++ - return true - } - return false - }*/ - - _rules = [...]func() bool{ - nil, - /* 0 AsmFile <- <(Statement* !.)> */ - func() bool { - position0, tokenIndex0 := position, tokenIndex - { - position1 := position - l2: - { - position3, tokenIndex3 := position, tokenIndex - if !_rules[ruleStatement]() { - goto l3 - } - goto l2 - l3: - position, tokenIndex = position3, tokenIndex3 - } - { - position4, tokenIndex4 := position, tokenIndex - if !matchDot() { - goto l4 - } - goto l0 - l4: - position, tokenIndex = position4, tokenIndex4 - } - add(ruleAsmFile, position1) - } - return true - l0: - position, tokenIndex = position0, tokenIndex0 - return false - }, - /* 1 Statement <- <(WS? (Label / ((GlobalDirective / LocationDirective / LabelContainingDirective / Instruction / Directive / Comment / ) WS? ((Comment? '\n') / ';'))))> */ - func() bool { - position5, tokenIndex5 := position, tokenIndex - { - position6 := position - { - position7, tokenIndex7 := position, tokenIndex - if !_rules[ruleWS]() { - goto l7 - } - goto l8 - l7: - position, tokenIndex = position7, tokenIndex7 - } - l8: - { - position9, tokenIndex9 := position, tokenIndex - if !_rules[ruleLabel]() { - goto l10 - } - goto l9 - l10: - position, tokenIndex = position9, tokenIndex9 - { - position11, tokenIndex11 := position, tokenIndex - if !_rules[ruleGlobalDirective]() { - goto l12 - } - goto l11 - l12: - position, tokenIndex = position11, tokenIndex11 - if !_rules[ruleLocationDirective]() { - goto l13 - } - goto l11 - l13: - position, tokenIndex = position11, tokenIndex11 - if !_rules[ruleLabelContainingDirective]() { - goto l14 - } - goto l11 - l14: - position, tokenIndex = position11, tokenIndex11 - if !_rules[ruleInstruction]() { - goto l15 - } - goto l11 - l15: - position, tokenIndex = position11, tokenIndex11 - if !_rules[ruleDirective]() { - goto l16 - } - goto l11 - l16: - position, tokenIndex = position11, tokenIndex11 - if !_rules[ruleComment]() { - goto l17 - } - goto l11 - l17: - position, tokenIndex = position11, tokenIndex11 - } - l11: - { - position18, tokenIndex18 := position, tokenIndex - if !_rules[ruleWS]() { - goto l18 - } - goto l19 - l18: - position, tokenIndex = position18, tokenIndex18 - } - l19: - { - position20, tokenIndex20 := position, tokenIndex - { - position22, tokenIndex22 := position, tokenIndex - if !_rules[ruleComment]() { - goto l22 - } - goto l23 - l22: - position, tokenIndex = position22, tokenIndex22 - } - l23: - if buffer[position] != rune('\n') { - goto l21 - } - position++ - goto l20 - l21: - position, tokenIndex = position20, tokenIndex20 - if buffer[position] != rune(';') { - goto l5 - } - position++ - } - l20: - } - l9: - add(ruleStatement, position6) - } - return true - l5: - position, tokenIndex = position5, tokenIndex5 - return false - }, - /* 2 GlobalDirective <- <((('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('a' / 'A') ('l' / 'L')) / ('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('l' / 'L'))) WS SymbolName)> */ - func() bool { - position24, tokenIndex24 := position, tokenIndex - { - position25 := position - { - position26, tokenIndex26 := position, tokenIndex - if buffer[position] != rune('.') { - goto l27 - } - position++ - { - position28, tokenIndex28 := position, tokenIndex - if buffer[position] != rune('g') { - goto l29 - } - position++ - goto l28 - l29: - position, tokenIndex = position28, tokenIndex28 - if buffer[position] != rune('G') { - goto l27 - } - position++ - } - l28: - { - position30, tokenIndex30 := position, tokenIndex - if buffer[position] != rune('l') { - goto l31 - } - position++ - goto l30 - l31: - position, tokenIndex = position30, tokenIndex30 - if buffer[position] != rune('L') { - goto l27 - } - position++ - } - l30: - { - position32, tokenIndex32 := position, tokenIndex - if buffer[position] != rune('o') { - goto l33 - } - position++ - goto l32 - l33: - position, tokenIndex = position32, tokenIndex32 - if buffer[position] != rune('O') { - goto l27 - } - position++ - } - l32: - { - position34, tokenIndex34 := position, tokenIndex - if buffer[position] != rune('b') { - goto l35 - } - position++ - goto l34 - l35: - position, tokenIndex = position34, tokenIndex34 - if buffer[position] != rune('B') { - goto l27 - } - position++ - } - l34: - { - position36, tokenIndex36 := position, tokenIndex - if buffer[position] != rune('a') { - goto l37 - } - position++ - goto l36 - l37: - position, tokenIndex = position36, tokenIndex36 - if buffer[position] != rune('A') { - goto l27 - } - position++ - } - l36: - { - position38, tokenIndex38 := position, tokenIndex - if buffer[position] != rune('l') { - goto l39 - } - position++ - goto l38 - l39: - position, tokenIndex = position38, tokenIndex38 - if buffer[position] != rune('L') { - goto l27 - } - position++ - } - l38: - goto l26 - l27: - position, tokenIndex = position26, tokenIndex26 - if buffer[position] != rune('.') { - goto l24 - } - position++ - { - position40, tokenIndex40 := position, tokenIndex - if buffer[position] != rune('g') { - goto l41 - } - position++ - goto l40 - l41: - position, tokenIndex = position40, tokenIndex40 - if buffer[position] != rune('G') { - goto l24 - } - position++ - } - l40: - { - position42, tokenIndex42 := position, tokenIndex - if buffer[position] != rune('l') { - goto l43 - } - position++ - goto l42 - l43: - position, tokenIndex = position42, tokenIndex42 - if buffer[position] != rune('L') { - goto l24 - } - position++ - } - l42: - { - position44, tokenIndex44 := position, tokenIndex - if buffer[position] != rune('o') { - goto l45 - } - position++ - goto l44 - l45: - position, tokenIndex = position44, tokenIndex44 - if buffer[position] != rune('O') { - goto l24 - } - position++ - } - l44: - { - position46, tokenIndex46 := position, tokenIndex - if buffer[position] != rune('b') { - goto l47 - } - position++ - goto l46 - l47: - position, tokenIndex = position46, tokenIndex46 - if buffer[position] != rune('B') { - goto l24 - } - position++ - } - l46: - { - position48, tokenIndex48 := position, tokenIndex - if buffer[position] != rune('l') { - goto l49 - } - position++ - goto l48 - l49: - position, tokenIndex = position48, tokenIndex48 - if buffer[position] != rune('L') { - goto l24 - } - position++ - } - l48: - } - l26: - if !_rules[ruleWS]() { - goto l24 - } - if !_rules[ruleSymbolName]() { - goto l24 - } - add(ruleGlobalDirective, position25) - } - return true - l24: - position, tokenIndex = position24, tokenIndex24 - return false - }, - /* 3 Directive <- <('.' DirectiveName (WS Args)?)> */ - func() bool { - position50, tokenIndex50 := position, tokenIndex - { - position51 := position - if buffer[position] != rune('.') { - goto l50 - } - position++ - if !_rules[ruleDirectiveName]() { - goto l50 - } - { - position52, tokenIndex52 := position, tokenIndex - if !_rules[ruleWS]() { - goto l52 - } - if !_rules[ruleArgs]() { - goto l52 - } - goto l53 - l52: - position, tokenIndex = position52, tokenIndex52 - } - l53: - add(ruleDirective, position51) - } - return true - l50: - position, tokenIndex = position50, tokenIndex50 - return false - }, - /* 4 DirectiveName <- <([a-z] / [A-Z] / ([0-9] / [0-9]) / '_')+> */ - func() bool { - position54, tokenIndex54 := position, tokenIndex - { - position55 := position - { - position58, tokenIndex58 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l59 - } - position++ - goto l58 - l59: - position, tokenIndex = position58, tokenIndex58 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l60 - } - position++ - goto l58 - l60: - position, tokenIndex = position58, tokenIndex58 - { - position62, tokenIndex62 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l63 - } - position++ - goto l62 - l63: - position, tokenIndex = position62, tokenIndex62 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l61 - } - position++ - } - l62: - goto l58 - l61: - position, tokenIndex = position58, tokenIndex58 - if buffer[position] != rune('_') { - goto l54 - } - position++ - } - l58: - l56: - { - position57, tokenIndex57 := position, tokenIndex - { - position64, tokenIndex64 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l65 - } - position++ - goto l64 - l65: - position, tokenIndex = position64, tokenIndex64 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l66 - } - position++ - goto l64 - l66: - position, tokenIndex = position64, tokenIndex64 - { - position68, tokenIndex68 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l69 - } - position++ - goto l68 - l69: - position, tokenIndex = position68, tokenIndex68 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l67 - } - position++ - } - l68: - goto l64 - l67: - position, tokenIndex = position64, tokenIndex64 - if buffer[position] != rune('_') { - goto l57 - } - position++ - } - l64: - goto l56 - l57: - position, tokenIndex = position57, tokenIndex57 - } - add(ruleDirectiveName, position55) - } - return true - l54: - position, tokenIndex = position54, tokenIndex54 - return false - }, - /* 5 LocationDirective <- <((('.' ('f' / 'F') ('i' / 'I') ('l' / 'L') ('e' / 'E')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C'))) WS (!('#' / '\n') .)+)> */ - func() bool { - position70, tokenIndex70 := position, tokenIndex - { - position71 := position - { - position72, tokenIndex72 := position, tokenIndex - if buffer[position] != rune('.') { - goto l73 - } - position++ - { - position74, tokenIndex74 := position, tokenIndex - if buffer[position] != rune('f') { - goto l75 - } - position++ - goto l74 - l75: - position, tokenIndex = position74, tokenIndex74 - if buffer[position] != rune('F') { - goto l73 - } - position++ - } - l74: - { - position76, tokenIndex76 := position, tokenIndex - if buffer[position] != rune('i') { - goto l77 - } - position++ - goto l76 - l77: - position, tokenIndex = position76, tokenIndex76 - if buffer[position] != rune('I') { - goto l73 - } - position++ - } - l76: - { - position78, tokenIndex78 := position, tokenIndex - if buffer[position] != rune('l') { - goto l79 - } - position++ - goto l78 - l79: - position, tokenIndex = position78, tokenIndex78 - if buffer[position] != rune('L') { - goto l73 - } - position++ - } - l78: - { - position80, tokenIndex80 := position, tokenIndex - if buffer[position] != rune('e') { - goto l81 - } - position++ - goto l80 - l81: - position, tokenIndex = position80, tokenIndex80 - if buffer[position] != rune('E') { - goto l73 - } - position++ - } - l80: - goto l72 - l73: - position, tokenIndex = position72, tokenIndex72 - if buffer[position] != rune('.') { - goto l70 - } - position++ - { - position82, tokenIndex82 := position, tokenIndex - if buffer[position] != rune('l') { - goto l83 - } - position++ - goto l82 - l83: - position, tokenIndex = position82, tokenIndex82 - if buffer[position] != rune('L') { - goto l70 - } - position++ - } - l82: - { - position84, tokenIndex84 := position, tokenIndex - if buffer[position] != rune('o') { - goto l85 - } - position++ - goto l84 - l85: - position, tokenIndex = position84, tokenIndex84 - if buffer[position] != rune('O') { - goto l70 - } - position++ - } - l84: - { - position86, tokenIndex86 := position, tokenIndex - if buffer[position] != rune('c') { - goto l87 - } - position++ - goto l86 - l87: - position, tokenIndex = position86, tokenIndex86 - if buffer[position] != rune('C') { - goto l70 - } - position++ - } - l86: - } - l72: - if !_rules[ruleWS]() { - goto l70 - } - { - position90, tokenIndex90 := position, tokenIndex - { - position91, tokenIndex91 := position, tokenIndex - if buffer[position] != rune('#') { - goto l92 - } - position++ - goto l91 - l92: - position, tokenIndex = position91, tokenIndex91 - if buffer[position] != rune('\n') { - goto l90 - } - position++ - } - l91: - goto l70 - l90: - position, tokenIndex = position90, tokenIndex90 - } - if !matchDot() { - goto l70 - } - l88: - { - position89, tokenIndex89 := position, tokenIndex - { - position93, tokenIndex93 := position, tokenIndex - { - position94, tokenIndex94 := position, tokenIndex - if buffer[position] != rune('#') { - goto l95 - } - position++ - goto l94 - l95: - position, tokenIndex = position94, tokenIndex94 - if buffer[position] != rune('\n') { - goto l93 - } - position++ - } - l94: - goto l89 - l93: - position, tokenIndex = position93, tokenIndex93 - } - if !matchDot() { - goto l89 - } - goto l88 - l89: - position, tokenIndex = position89, tokenIndex89 - } - add(ruleLocationDirective, position71) - } - return true - l70: - position, tokenIndex = position70, tokenIndex70 - return false - }, - /* 6 Args <- <(Arg (WS? ',' WS? Arg)*)> */ - func() bool { - position96, tokenIndex96 := position, tokenIndex - { - position97 := position - if !_rules[ruleArg]() { - goto l96 - } - l98: - { - position99, tokenIndex99 := position, tokenIndex - { - position100, tokenIndex100 := position, tokenIndex - if !_rules[ruleWS]() { - goto l100 - } - goto l101 - l100: - position, tokenIndex = position100, tokenIndex100 - } - l101: - if buffer[position] != rune(',') { - goto l99 - } - position++ - { - position102, tokenIndex102 := position, tokenIndex - if !_rules[ruleWS]() { - goto l102 - } - goto l103 - l102: - position, tokenIndex = position102, tokenIndex102 - } - l103: - if !_rules[ruleArg]() { - goto l99 - } - goto l98 - l99: - position, tokenIndex = position99, tokenIndex99 - } - add(ruleArgs, position97) - } - return true - l96: - position, tokenIndex = position96, tokenIndex96 - return false - }, - /* 7 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '*' / '_' / '@' / '.')*)> */ - func() bool { - { - position105 := position - { - position106, tokenIndex106 := position, tokenIndex - if !_rules[ruleQuotedArg]() { - goto l107 - } - goto l106 - l107: - position, tokenIndex = position106, tokenIndex106 - l108: - { - position109, tokenIndex109 := position, tokenIndex - { - position110, tokenIndex110 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l111 - } - position++ - goto l110 - l111: - position, tokenIndex = position110, tokenIndex110 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l112 - } - position++ - goto l110 - l112: - position, tokenIndex = position110, tokenIndex110 - { - position114, tokenIndex114 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l115 - } - position++ - goto l114 - l115: - position, tokenIndex = position114, tokenIndex114 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l113 - } - position++ - } - l114: - goto l110 - l113: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('%') { - goto l116 - } - position++ - goto l110 - l116: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('+') { - goto l117 - } - position++ - goto l110 - l117: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('-') { - goto l118 - } - position++ - goto l110 - l118: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('*') { - goto l119 - } - position++ - goto l110 - l119: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('_') { - goto l120 - } - position++ - goto l110 - l120: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('@') { - goto l121 - } - position++ - goto l110 - l121: - position, tokenIndex = position110, tokenIndex110 - if buffer[position] != rune('.') { - goto l109 - } - position++ - } - l110: - goto l108 - l109: - position, tokenIndex = position109, tokenIndex109 - } - } - l106: - add(ruleArg, position105) - } - return true - }, - /* 8 QuotedArg <- <('"' QuotedText '"')> */ - func() bool { - position122, tokenIndex122 := position, tokenIndex - { - position123 := position - if buffer[position] != rune('"') { - goto l122 - } - position++ - if !_rules[ruleQuotedText]() { - goto l122 - } - if buffer[position] != rune('"') { - goto l122 - } - position++ - add(ruleQuotedArg, position123) - } - return true - l122: - position, tokenIndex = position122, tokenIndex122 - return false - }, - /* 9 QuotedText <- <(EscapedChar / (!'"' .))*> */ - func() bool { - { - position125 := position - l126: - { - position127, tokenIndex127 := position, tokenIndex - { - position128, tokenIndex128 := position, tokenIndex - if !_rules[ruleEscapedChar]() { - goto l129 - } - goto l128 - l129: - position, tokenIndex = position128, tokenIndex128 - { - position130, tokenIndex130 := position, tokenIndex - if buffer[position] != rune('"') { - goto l130 - } - position++ - goto l127 - l130: - position, tokenIndex = position130, tokenIndex130 - } - if !matchDot() { - goto l127 - } - } - l128: - goto l126 - l127: - position, tokenIndex = position127, tokenIndex127 - } - add(ruleQuotedText, position125) - } - return true - }, - /* 10 LabelContainingDirective <- <(LabelContainingDirectiveName WS SymbolArgs)> */ - func() bool { - position131, tokenIndex131 := position, tokenIndex - { - position132 := position - if !_rules[ruleLabelContainingDirectiveName]() { - goto l131 - } - if !_rules[ruleWS]() { - goto l131 - } - if !_rules[ruleSymbolArgs]() { - goto l131 - } - add(ruleLabelContainingDirective, position132) - } - return true - l131: - position, tokenIndex = position131, tokenIndex131 - return false - }, - /* 11 LabelContainingDirectiveName <- <(('.' ('l' / 'L') ('o' / 'O') ('n' / 'N') ('g' / 'G')) / ('.' ('s' / 'S') ('e' / 'E') ('t' / 'T')) / ('.' '8' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '4' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' ('q' / 'Q') ('u' / 'U') ('a' / 'A') ('d' / 'D')) / ('.' ('t' / 'T') ('c' / 'C')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') ('a' / 'A') ('l' / 'L') ('e' / 'E') ('n' / 'N') ('t' / 'T') ('r' / 'R') ('y' / 'Y')) / ('.' ('s' / 'S') ('i' / 'I') ('z' / 'Z') ('e' / 'E')) / ('.' ('t' / 'T') ('y' / 'Y') ('p' / 'P') ('e' / 'E')))> */ - func() bool { - position133, tokenIndex133 := position, tokenIndex - { - position134 := position - { - position135, tokenIndex135 := position, tokenIndex - if buffer[position] != rune('.') { - goto l136 - } - position++ - { - position137, tokenIndex137 := position, tokenIndex - if buffer[position] != rune('l') { - goto l138 - } - position++ - goto l137 - l138: - position, tokenIndex = position137, tokenIndex137 - if buffer[position] != rune('L') { - goto l136 - } - position++ - } - l137: - { - position139, tokenIndex139 := position, tokenIndex - if buffer[position] != rune('o') { - goto l140 - } - position++ - goto l139 - l140: - position, tokenIndex = position139, tokenIndex139 - if buffer[position] != rune('O') { - goto l136 - } - position++ - } - l139: - { - position141, tokenIndex141 := position, tokenIndex - if buffer[position] != rune('n') { - goto l142 - } - position++ - goto l141 - l142: - position, tokenIndex = position141, tokenIndex141 - if buffer[position] != rune('N') { - goto l136 - } - position++ - } - l141: - { - position143, tokenIndex143 := position, tokenIndex - if buffer[position] != rune('g') { - goto l144 - } - position++ - goto l143 - l144: - position, tokenIndex = position143, tokenIndex143 - if buffer[position] != rune('G') { - goto l136 - } - position++ - } - l143: - goto l135 - l136: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l145 - } - position++ - { - position146, tokenIndex146 := position, tokenIndex - if buffer[position] != rune('s') { - goto l147 - } - position++ - goto l146 - l147: - position, tokenIndex = position146, tokenIndex146 - if buffer[position] != rune('S') { - goto l145 - } - position++ - } - l146: - { - position148, tokenIndex148 := position, tokenIndex - if buffer[position] != rune('e') { - goto l149 - } - position++ - goto l148 - l149: - position, tokenIndex = position148, tokenIndex148 - if buffer[position] != rune('E') { - goto l145 - } - position++ - } - l148: - { - position150, tokenIndex150 := position, tokenIndex - if buffer[position] != rune('t') { - goto l151 - } - position++ - goto l150 - l151: - position, tokenIndex = position150, tokenIndex150 - if buffer[position] != rune('T') { - goto l145 - } - position++ - } - l150: - goto l135 - l145: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l152 - } - position++ - if buffer[position] != rune('8') { - goto l152 - } - position++ - { - position153, tokenIndex153 := position, tokenIndex - if buffer[position] != rune('b') { - goto l154 - } - position++ - goto l153 - l154: - position, tokenIndex = position153, tokenIndex153 - if buffer[position] != rune('B') { - goto l152 - } - position++ - } - l153: - { - position155, tokenIndex155 := position, tokenIndex - if buffer[position] != rune('y') { - goto l156 - } - position++ - goto l155 - l156: - position, tokenIndex = position155, tokenIndex155 - if buffer[position] != rune('Y') { - goto l152 - } - position++ - } - l155: - { - position157, tokenIndex157 := position, tokenIndex - if buffer[position] != rune('t') { - goto l158 - } - position++ - goto l157 - l158: - position, tokenIndex = position157, tokenIndex157 - if buffer[position] != rune('T') { - goto l152 - } - position++ - } - l157: - { - position159, tokenIndex159 := position, tokenIndex - if buffer[position] != rune('e') { - goto l160 - } - position++ - goto l159 - l160: - position, tokenIndex = position159, tokenIndex159 - if buffer[position] != rune('E') { - goto l152 - } - position++ - } - l159: - goto l135 - l152: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l161 - } - position++ - if buffer[position] != rune('4') { - goto l161 - } - position++ - { - position162, tokenIndex162 := position, tokenIndex - if buffer[position] != rune('b') { - goto l163 - } - position++ - goto l162 - l163: - position, tokenIndex = position162, tokenIndex162 - if buffer[position] != rune('B') { - goto l161 - } - position++ - } - l162: - { - position164, tokenIndex164 := position, tokenIndex - if buffer[position] != rune('y') { - goto l165 - } - position++ - goto l164 - l165: - position, tokenIndex = position164, tokenIndex164 - if buffer[position] != rune('Y') { - goto l161 - } - position++ - } - l164: - { - position166, tokenIndex166 := position, tokenIndex - if buffer[position] != rune('t') { - goto l167 - } - position++ - goto l166 - l167: - position, tokenIndex = position166, tokenIndex166 - if buffer[position] != rune('T') { - goto l161 - } - position++ - } - l166: - { - position168, tokenIndex168 := position, tokenIndex - if buffer[position] != rune('e') { - goto l169 - } - position++ - goto l168 - l169: - position, tokenIndex = position168, tokenIndex168 - if buffer[position] != rune('E') { - goto l161 - } - position++ - } - l168: - goto l135 - l161: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l170 - } - position++ - { - position171, tokenIndex171 := position, tokenIndex - if buffer[position] != rune('q') { - goto l172 - } - position++ - goto l171 - l172: - position, tokenIndex = position171, tokenIndex171 - if buffer[position] != rune('Q') { - goto l170 - } - position++ - } - l171: - { - position173, tokenIndex173 := position, tokenIndex - if buffer[position] != rune('u') { - goto l174 - } - position++ - goto l173 - l174: - position, tokenIndex = position173, tokenIndex173 - if buffer[position] != rune('U') { - goto l170 - } - position++ - } - l173: - { - position175, tokenIndex175 := position, tokenIndex - if buffer[position] != rune('a') { - goto l176 - } - position++ - goto l175 - l176: - position, tokenIndex = position175, tokenIndex175 - if buffer[position] != rune('A') { - goto l170 - } - position++ - } - l175: - { - position177, tokenIndex177 := position, tokenIndex - if buffer[position] != rune('d') { - goto l178 - } - position++ - goto l177 - l178: - position, tokenIndex = position177, tokenIndex177 - if buffer[position] != rune('D') { - goto l170 - } - position++ - } - l177: - goto l135 - l170: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l179 - } - position++ - { - position180, tokenIndex180 := position, tokenIndex - if buffer[position] != rune('t') { - goto l181 - } - position++ - goto l180 - l181: - position, tokenIndex = position180, tokenIndex180 - if buffer[position] != rune('T') { - goto l179 - } - position++ - } - l180: - { - position182, tokenIndex182 := position, tokenIndex - if buffer[position] != rune('c') { - goto l183 - } - position++ - goto l182 - l183: - position, tokenIndex = position182, tokenIndex182 - if buffer[position] != rune('C') { - goto l179 - } - position++ - } - l182: - goto l135 - l179: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l184 - } - position++ - { - position185, tokenIndex185 := position, tokenIndex - if buffer[position] != rune('l') { - goto l186 - } - position++ - goto l185 - l186: - position, tokenIndex = position185, tokenIndex185 - if buffer[position] != rune('L') { - goto l184 - } - position++ - } - l185: - { - position187, tokenIndex187 := position, tokenIndex - if buffer[position] != rune('o') { - goto l188 - } - position++ - goto l187 - l188: - position, tokenIndex = position187, tokenIndex187 - if buffer[position] != rune('O') { - goto l184 - } - position++ - } - l187: - { - position189, tokenIndex189 := position, tokenIndex - if buffer[position] != rune('c') { - goto l190 - } - position++ - goto l189 - l190: - position, tokenIndex = position189, tokenIndex189 - if buffer[position] != rune('C') { - goto l184 - } - position++ - } - l189: - { - position191, tokenIndex191 := position, tokenIndex - if buffer[position] != rune('a') { - goto l192 - } - position++ - goto l191 - l192: - position, tokenIndex = position191, tokenIndex191 - if buffer[position] != rune('A') { - goto l184 - } - position++ - } - l191: - { - position193, tokenIndex193 := position, tokenIndex - if buffer[position] != rune('l') { - goto l194 - } - position++ - goto l193 - l194: - position, tokenIndex = position193, tokenIndex193 - if buffer[position] != rune('L') { - goto l184 - } - position++ - } - l193: - { - position195, tokenIndex195 := position, tokenIndex - if buffer[position] != rune('e') { - goto l196 - } - position++ - goto l195 - l196: - position, tokenIndex = position195, tokenIndex195 - if buffer[position] != rune('E') { - goto l184 - } - position++ - } - l195: - { - position197, tokenIndex197 := position, tokenIndex - if buffer[position] != rune('n') { - goto l198 - } - position++ - goto l197 - l198: - position, tokenIndex = position197, tokenIndex197 - if buffer[position] != rune('N') { - goto l184 - } - position++ - } - l197: - { - position199, tokenIndex199 := position, tokenIndex - if buffer[position] != rune('t') { - goto l200 - } - position++ - goto l199 - l200: - position, tokenIndex = position199, tokenIndex199 - if buffer[position] != rune('T') { - goto l184 - } - position++ - } - l199: - { - position201, tokenIndex201 := position, tokenIndex - if buffer[position] != rune('r') { - goto l202 - } - position++ - goto l201 - l202: - position, tokenIndex = position201, tokenIndex201 - if buffer[position] != rune('R') { - goto l184 - } - position++ - } - l201: - { - position203, tokenIndex203 := position, tokenIndex - if buffer[position] != rune('y') { - goto l204 - } - position++ - goto l203 - l204: - position, tokenIndex = position203, tokenIndex203 - if buffer[position] != rune('Y') { - goto l184 - } - position++ - } - l203: - goto l135 - l184: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l205 - } - position++ - { - position206, tokenIndex206 := position, tokenIndex - if buffer[position] != rune('s') { - goto l207 - } - position++ - goto l206 - l207: - position, tokenIndex = position206, tokenIndex206 - if buffer[position] != rune('S') { - goto l205 - } - position++ - } - l206: - { - position208, tokenIndex208 := position, tokenIndex - if buffer[position] != rune('i') { - goto l209 - } - position++ - goto l208 - l209: - position, tokenIndex = position208, tokenIndex208 - if buffer[position] != rune('I') { - goto l205 - } - position++ - } - l208: - { - position210, tokenIndex210 := position, tokenIndex - if buffer[position] != rune('z') { - goto l211 - } - position++ - goto l210 - l211: - position, tokenIndex = position210, tokenIndex210 - if buffer[position] != rune('Z') { - goto l205 - } - position++ - } - l210: - { - position212, tokenIndex212 := position, tokenIndex - if buffer[position] != rune('e') { - goto l213 - } - position++ - goto l212 - l213: - position, tokenIndex = position212, tokenIndex212 - if buffer[position] != rune('E') { - goto l205 - } - position++ - } - l212: - goto l135 - l205: - position, tokenIndex = position135, tokenIndex135 - if buffer[position] != rune('.') { - goto l133 - } - position++ - { - position214, tokenIndex214 := position, tokenIndex - if buffer[position] != rune('t') { - goto l215 - } - position++ - goto l214 - l215: - position, tokenIndex = position214, tokenIndex214 - if buffer[position] != rune('T') { - goto l133 - } - position++ - } - l214: - { - position216, tokenIndex216 := position, tokenIndex - if buffer[position] != rune('y') { - goto l217 - } - position++ - goto l216 - l217: - position, tokenIndex = position216, tokenIndex216 - if buffer[position] != rune('Y') { - goto l133 - } - position++ - } - l216: - { - position218, tokenIndex218 := position, tokenIndex - if buffer[position] != rune('p') { - goto l219 - } - position++ - goto l218 - l219: - position, tokenIndex = position218, tokenIndex218 - if buffer[position] != rune('P') { - goto l133 - } - position++ - } - l218: - { - position220, tokenIndex220 := position, tokenIndex - if buffer[position] != rune('e') { - goto l221 - } - position++ - goto l220 - l221: - position, tokenIndex = position220, tokenIndex220 - if buffer[position] != rune('E') { - goto l133 - } - position++ - } - l220: - } - l135: - add(ruleLabelContainingDirectiveName, position134) - } - return true - l133: - position, tokenIndex = position133, tokenIndex133 - return false - }, - /* 12 SymbolArgs <- <(SymbolArg (WS? ',' WS? SymbolArg)*)> */ - func() bool { - position222, tokenIndex222 := position, tokenIndex - { - position223 := position - if !_rules[ruleSymbolArg]() { - goto l222 - } - l224: - { - position225, tokenIndex225 := position, tokenIndex - { - position226, tokenIndex226 := position, tokenIndex - if !_rules[ruleWS]() { - goto l226 - } - goto l227 - l226: - position, tokenIndex = position226, tokenIndex226 - } - l227: - if buffer[position] != rune(',') { - goto l225 - } - position++ - { - position228, tokenIndex228 := position, tokenIndex - if !_rules[ruleWS]() { - goto l228 - } - goto l229 - l228: - position, tokenIndex = position228, tokenIndex228 - } - l229: - if !_rules[ruleSymbolArg]() { - goto l225 - } - goto l224 - l225: - position, tokenIndex = position225, tokenIndex225 - } - add(ruleSymbolArgs, position223) - } - return true - l222: - position, tokenIndex = position222, tokenIndex222 - return false - }, - /* 13 SymbolArg <- <(Offset / SymbolType / ((Offset / LocalSymbol / SymbolName / Dot) WS? Operator WS? (Offset / LocalSymbol / SymbolName)) / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?))> */ - func() bool { - position230, tokenIndex230 := position, tokenIndex - { - position231 := position - { - position232, tokenIndex232 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l233 - } - goto l232 - l233: - position, tokenIndex = position232, tokenIndex232 - if !_rules[ruleSymbolType]() { - goto l234 - } - goto l232 - l234: - position, tokenIndex = position232, tokenIndex232 - { - position236, tokenIndex236 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l237 - } - goto l236 - l237: - position, tokenIndex = position236, tokenIndex236 - if !_rules[ruleLocalSymbol]() { - goto l238 - } - goto l236 - l238: - position, tokenIndex = position236, tokenIndex236 - if !_rules[ruleSymbolName]() { - goto l239 - } - goto l236 - l239: - position, tokenIndex = position236, tokenIndex236 - if !_rules[ruleDot]() { - goto l235 - } - } - l236: - { - position240, tokenIndex240 := position, tokenIndex - if !_rules[ruleWS]() { - goto l240 - } - goto l241 - l240: - position, tokenIndex = position240, tokenIndex240 - } - l241: - if !_rules[ruleOperator]() { - goto l235 - } - { - position242, tokenIndex242 := position, tokenIndex - if !_rules[ruleWS]() { - goto l242 - } - goto l243 - l242: - position, tokenIndex = position242, tokenIndex242 - } - l243: - { - position244, tokenIndex244 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l245 - } - goto l244 - l245: - position, tokenIndex = position244, tokenIndex244 - if !_rules[ruleLocalSymbol]() { - goto l246 - } - goto l244 - l246: - position, tokenIndex = position244, tokenIndex244 - if !_rules[ruleSymbolName]() { - goto l235 - } - } - l244: - goto l232 - l235: - position, tokenIndex = position232, tokenIndex232 - if !_rules[ruleLocalSymbol]() { - goto l247 - } - { - position248, tokenIndex248 := position, tokenIndex - if !_rules[ruleTCMarker]() { - goto l248 - } - goto l249 - l248: - position, tokenIndex = position248, tokenIndex248 - } - l249: - goto l232 - l247: - position, tokenIndex = position232, tokenIndex232 - if !_rules[ruleSymbolName]() { - goto l250 - } - if !_rules[ruleOffset]() { - goto l250 - } - goto l232 - l250: - position, tokenIndex = position232, tokenIndex232 - if !_rules[ruleSymbolName]() { - goto l230 - } - { - position251, tokenIndex251 := position, tokenIndex - if !_rules[ruleTCMarker]() { - goto l251 - } - goto l252 - l251: - position, tokenIndex = position251, tokenIndex251 - } - l252: - } - l232: - add(ruleSymbolArg, position231) - } - return true - l230: - position, tokenIndex = position230, tokenIndex230 - return false - }, - /* 14 SymbolType <- <(('@' 'f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('@' 'o' 'b' 'j' 'e' 'c' 't'))> */ - func() bool { - position253, tokenIndex253 := position, tokenIndex - { - position254 := position - { - position255, tokenIndex255 := position, tokenIndex - if buffer[position] != rune('@') { - goto l256 - } - position++ - if buffer[position] != rune('f') { - goto l256 - } - position++ - if buffer[position] != rune('u') { - goto l256 - } - position++ - if buffer[position] != rune('n') { - goto l256 - } - position++ - if buffer[position] != rune('c') { - goto l256 - } - position++ - if buffer[position] != rune('t') { - goto l256 - } - position++ - if buffer[position] != rune('i') { - goto l256 - } - position++ - if buffer[position] != rune('o') { - goto l256 - } - position++ - if buffer[position] != rune('n') { - goto l256 - } - position++ - goto l255 - l256: - position, tokenIndex = position255, tokenIndex255 - if buffer[position] != rune('@') { - goto l253 - } - position++ - if buffer[position] != rune('o') { - goto l253 - } - position++ - if buffer[position] != rune('b') { - goto l253 - } - position++ - if buffer[position] != rune('j') { - goto l253 - } - position++ - if buffer[position] != rune('e') { - goto l253 - } - position++ - if buffer[position] != rune('c') { - goto l253 - } - position++ - if buffer[position] != rune('t') { - goto l253 - } - position++ - } - l255: - add(ruleSymbolType, position254) - } - return true - l253: - position, tokenIndex = position253, tokenIndex253 - return false - }, - /* 15 Dot <- <'.'> */ - func() bool { - position257, tokenIndex257 := position, tokenIndex - { - position258 := position - if buffer[position] != rune('.') { - goto l257 - } - position++ - add(ruleDot, position258) - } - return true - l257: - position, tokenIndex = position257, tokenIndex257 - return false - }, - /* 16 TCMarker <- <('[' 'T' 'C' ']')> */ - func() bool { - position259, tokenIndex259 := position, tokenIndex - { - position260 := position - if buffer[position] != rune('[') { - goto l259 - } - position++ - if buffer[position] != rune('T') { - goto l259 - } - position++ - if buffer[position] != rune('C') { - goto l259 - } - position++ - if buffer[position] != rune(']') { - goto l259 - } - position++ - add(ruleTCMarker, position260) - } - return true - l259: - position, tokenIndex = position259, tokenIndex259 - return false - }, - /* 17 EscapedChar <- <('\\' .)> */ - func() bool { - position261, tokenIndex261 := position, tokenIndex - { - position262 := position - if buffer[position] != rune('\\') { - goto l261 - } - position++ - if !matchDot() { - goto l261 - } - add(ruleEscapedChar, position262) - } - return true - l261: - position, tokenIndex = position261, tokenIndex261 - return false - }, - /* 18 WS <- <(' ' / '\t')+> */ - func() bool { - position263, tokenIndex263 := position, tokenIndex - { - position264 := position - { - position267, tokenIndex267 := position, tokenIndex - if buffer[position] != rune(' ') { - goto l268 - } - position++ - goto l267 - l268: - position, tokenIndex = position267, tokenIndex267 - if buffer[position] != rune('\t') { - goto l263 - } - position++ - } - l267: - l265: - { - position266, tokenIndex266 := position, tokenIndex - { - position269, tokenIndex269 := position, tokenIndex - if buffer[position] != rune(' ') { - goto l270 - } - position++ - goto l269 - l270: - position, tokenIndex = position269, tokenIndex269 - if buffer[position] != rune('\t') { - goto l266 - } - position++ - } - l269: - goto l265 - l266: - position, tokenIndex = position266, tokenIndex266 - } - add(ruleWS, position264) - } - return true - l263: - position, tokenIndex = position263, tokenIndex263 - return false - }, - /* 19 Comment <- <('#' (!'\n' .)*)> */ - func() bool { - position271, tokenIndex271 := position, tokenIndex - { - position272 := position - if buffer[position] != rune('#') { - goto l271 - } - position++ - l273: - { - position274, tokenIndex274 := position, tokenIndex - { - position275, tokenIndex275 := position, tokenIndex - if buffer[position] != rune('\n') { - goto l275 - } - position++ - goto l274 - l275: - position, tokenIndex = position275, tokenIndex275 - } - if !matchDot() { - goto l274 - } - goto l273 - l274: - position, tokenIndex = position274, tokenIndex274 - } - add(ruleComment, position272) - } - return true - l271: - position, tokenIndex = position271, tokenIndex271 - return false - }, - /* 20 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */ - func() bool { - position276, tokenIndex276 := position, tokenIndex - { - position277 := position - { - position278, tokenIndex278 := position, tokenIndex - if !_rules[ruleLocalSymbol]() { - goto l279 - } - goto l278 - l279: - position, tokenIndex = position278, tokenIndex278 - if !_rules[ruleLocalLabel]() { - goto l280 - } - goto l278 - l280: - position, tokenIndex = position278, tokenIndex278 - if !_rules[ruleSymbolName]() { - goto l276 - } - } - l278: - if buffer[position] != rune(':') { - goto l276 - } - position++ - add(ruleLabel, position277) - } - return true - l276: - position, tokenIndex = position276, tokenIndex276 - return false - }, - /* 21 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */ - func() bool { - position281, tokenIndex281 := position, tokenIndex - { - position282 := position - { - position283, tokenIndex283 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l284 - } - position++ - goto l283 - l284: - position, tokenIndex = position283, tokenIndex283 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l285 - } - position++ - goto l283 - l285: - position, tokenIndex = position283, tokenIndex283 - if buffer[position] != rune('.') { - goto l286 - } - position++ - goto l283 - l286: - position, tokenIndex = position283, tokenIndex283 - if buffer[position] != rune('_') { - goto l281 - } - position++ - } - l283: - l287: - { - position288, tokenIndex288 := position, tokenIndex - { - position289, tokenIndex289 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l290 - } - position++ - goto l289 - l290: - position, tokenIndex = position289, tokenIndex289 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l291 - } - position++ - goto l289 - l291: - position, tokenIndex = position289, tokenIndex289 - if buffer[position] != rune('.') { - goto l292 - } - position++ - goto l289 - l292: - position, tokenIndex = position289, tokenIndex289 - { - position294, tokenIndex294 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l295 - } - position++ - goto l294 - l295: - position, tokenIndex = position294, tokenIndex294 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l293 - } - position++ - } - l294: - goto l289 - l293: - position, tokenIndex = position289, tokenIndex289 - if buffer[position] != rune('$') { - goto l296 - } - position++ - goto l289 - l296: - position, tokenIndex = position289, tokenIndex289 - if buffer[position] != rune('_') { - goto l288 - } - position++ - } - l289: - goto l287 - l288: - position, tokenIndex = position288, tokenIndex288 - } - add(ruleSymbolName, position282) - } - return true - l281: - position, tokenIndex = position281, tokenIndex281 - return false - }, - /* 22 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */ - func() bool { - position297, tokenIndex297 := position, tokenIndex - { - position298 := position - if buffer[position] != rune('.') { - goto l297 - } - position++ - if buffer[position] != rune('L') { - goto l297 - } - position++ - { - position301, tokenIndex301 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l302 - } - position++ - goto l301 - l302: - position, tokenIndex = position301, tokenIndex301 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l303 - } - position++ - goto l301 - l303: - position, tokenIndex = position301, tokenIndex301 - if buffer[position] != rune('.') { - goto l304 - } - position++ - goto l301 - l304: - position, tokenIndex = position301, tokenIndex301 - { - position306, tokenIndex306 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l307 - } - position++ - goto l306 - l307: - position, tokenIndex = position306, tokenIndex306 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l305 - } - position++ - } - l306: - goto l301 - l305: - position, tokenIndex = position301, tokenIndex301 - if buffer[position] != rune('$') { - goto l308 - } - position++ - goto l301 - l308: - position, tokenIndex = position301, tokenIndex301 - if buffer[position] != rune('_') { - goto l297 - } - position++ - } - l301: - l299: - { - position300, tokenIndex300 := position, tokenIndex - { - position309, tokenIndex309 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l310 - } - position++ - goto l309 - l310: - position, tokenIndex = position309, tokenIndex309 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l311 - } - position++ - goto l309 - l311: - position, tokenIndex = position309, tokenIndex309 - if buffer[position] != rune('.') { - goto l312 - } - position++ - goto l309 - l312: - position, tokenIndex = position309, tokenIndex309 - { - position314, tokenIndex314 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l315 - } - position++ - goto l314 - l315: - position, tokenIndex = position314, tokenIndex314 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l313 - } - position++ - } - l314: - goto l309 - l313: - position, tokenIndex = position309, tokenIndex309 - if buffer[position] != rune('$') { - goto l316 - } - position++ - goto l309 - l316: - position, tokenIndex = position309, tokenIndex309 - if buffer[position] != rune('_') { - goto l300 - } - position++ - } - l309: - goto l299 - l300: - position, tokenIndex = position300, tokenIndex300 - } - add(ruleLocalSymbol, position298) - } - return true - l297: - position, tokenIndex = position297, tokenIndex297 - return false - }, - /* 23 LocalLabel <- <([0-9] ([0-9] / '$')*)> */ - func() bool { - position317, tokenIndex317 := position, tokenIndex - { - position318 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l317 - } - position++ - l319: - { - position320, tokenIndex320 := position, tokenIndex - { - position321, tokenIndex321 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l322 - } - position++ - goto l321 - l322: - position, tokenIndex = position321, tokenIndex321 - if buffer[position] != rune('$') { - goto l320 - } - position++ - } - l321: - goto l319 - l320: - position, tokenIndex = position320, tokenIndex320 - } - add(ruleLocalLabel, position318) - } - return true - l317: - position, tokenIndex = position317, tokenIndex317 - return false - }, - /* 24 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */ - func() bool { - position323, tokenIndex323 := position, tokenIndex - { - position324 := position - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l323 - } - position++ - l325: - { - position326, tokenIndex326 := position, tokenIndex - { - position327, tokenIndex327 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l328 - } - position++ - goto l327 - l328: - position, tokenIndex = position327, tokenIndex327 - if buffer[position] != rune('$') { - goto l326 - } - position++ - } - l327: - goto l325 - l326: - position, tokenIndex = position326, tokenIndex326 - } - { - position329, tokenIndex329 := position, tokenIndex - if buffer[position] != rune('b') { - goto l330 - } - position++ - goto l329 - l330: - position, tokenIndex = position329, tokenIndex329 - if buffer[position] != rune('f') { - goto l323 - } - position++ - } - l329: - add(ruleLocalLabelRef, position324) - } - return true - l323: - position, tokenIndex = position323, tokenIndex323 - return false - }, - /* 25 Instruction <- <(InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)? (WS? '{' InstructionArg '}')*)> */ - func() bool { - position331, tokenIndex331 := position, tokenIndex - { - position332 := position - if !_rules[ruleInstructionName]() { - goto l331 - } - { - position333, tokenIndex333 := position, tokenIndex - if !_rules[ruleWS]() { - goto l333 - } - if !_rules[ruleInstructionArg]() { - goto l333 - } - l335: - { - position336, tokenIndex336 := position, tokenIndex - { - position337, tokenIndex337 := position, tokenIndex - if !_rules[ruleWS]() { - goto l337 - } - goto l338 - l337: - position, tokenIndex = position337, tokenIndex337 - } - l338: - if buffer[position] != rune(',') { - goto l336 - } - position++ - { - position339, tokenIndex339 := position, tokenIndex - if !_rules[ruleWS]() { - goto l339 - } - goto l340 - l339: - position, tokenIndex = position339, tokenIndex339 - } - l340: - if !_rules[ruleInstructionArg]() { - goto l336 - } - goto l335 - l336: - position, tokenIndex = position336, tokenIndex336 - } - goto l334 - l333: - position, tokenIndex = position333, tokenIndex333 - } - l334: - l341: - { - position342, tokenIndex342 := position, tokenIndex - { - position343, tokenIndex343 := position, tokenIndex - if !_rules[ruleWS]() { - goto l343 - } - goto l344 - l343: - position, tokenIndex = position343, tokenIndex343 - } - l344: - if buffer[position] != rune('{') { - goto l342 - } - position++ - if !_rules[ruleInstructionArg]() { - goto l342 - } - if buffer[position] != rune('}') { - goto l342 - } - position++ - goto l341 - l342: - position, tokenIndex = position342, tokenIndex342 - } - add(ruleInstruction, position332) - } - return true - l331: - position, tokenIndex = position331, tokenIndex331 - return false - }, - /* 26 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */ - func() bool { - position345, tokenIndex345 := position, tokenIndex - { - position346 := position - { - position347, tokenIndex347 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l348 - } - position++ - goto l347 - l348: - position, tokenIndex = position347, tokenIndex347 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l345 - } - position++ - } - l347: - l349: - { - position350, tokenIndex350 := position, tokenIndex - { - position351, tokenIndex351 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l352 - } - position++ - goto l351 - l352: - position, tokenIndex = position351, tokenIndex351 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l353 - } - position++ - goto l351 - l353: - position, tokenIndex = position351, tokenIndex351 - { - position354, tokenIndex354 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l355 - } - position++ - goto l354 - l355: - position, tokenIndex = position354, tokenIndex354 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l350 - } - position++ - } - l354: - } - l351: - goto l349 - l350: - position, tokenIndex = position350, tokenIndex350 - } - { - position356, tokenIndex356 := position, tokenIndex - { - position358, tokenIndex358 := position, tokenIndex - if buffer[position] != rune('.') { - goto l359 - } - position++ - goto l358 - l359: - position, tokenIndex = position358, tokenIndex358 - if buffer[position] != rune('+') { - goto l360 - } - position++ - goto l358 - l360: - position, tokenIndex = position358, tokenIndex358 - if buffer[position] != rune('-') { - goto l356 - } - position++ - } - l358: - goto l357 - l356: - position, tokenIndex = position356, tokenIndex356 - } - l357: - add(ruleInstructionName, position346) - } - return true - l345: - position, tokenIndex = position345, tokenIndex345 - return false - }, - /* 27 InstructionArg <- <(IndirectionIndicator? (RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / MemoryRef))> */ - func() bool { - position361, tokenIndex361 := position, tokenIndex - { - position362 := position - { - position363, tokenIndex363 := position, tokenIndex - if !_rules[ruleIndirectionIndicator]() { - goto l363 - } - goto l364 - l363: - position, tokenIndex = position363, tokenIndex363 - } - l364: - { - position365, tokenIndex365 := position, tokenIndex - if !_rules[ruleRegisterOrConstant]() { - goto l366 - } - goto l365 - l366: - position, tokenIndex = position365, tokenIndex365 - if !_rules[ruleLocalLabelRef]() { - goto l367 - } - goto l365 - l367: - position, tokenIndex = position365, tokenIndex365 - if !_rules[ruleTOCRefHigh]() { - goto l368 - } - goto l365 - l368: - position, tokenIndex = position365, tokenIndex365 - if !_rules[ruleTOCRefLow]() { - goto l369 - } - goto l365 - l369: - position, tokenIndex = position365, tokenIndex365 - if !_rules[ruleMemoryRef]() { - goto l361 - } - } - l365: - add(ruleInstructionArg, position362) - } - return true - l361: - position, tokenIndex = position361, tokenIndex361 - return false - }, - /* 28 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ - func() bool { - position370, tokenIndex370 := position, tokenIndex - { - position371 := position - if buffer[position] != rune('.') { - goto l370 - } - position++ - if buffer[position] != rune('T') { - goto l370 - } - position++ - if buffer[position] != rune('O') { - goto l370 - } - position++ - if buffer[position] != rune('C') { - goto l370 - } - position++ - if buffer[position] != rune('.') { - goto l370 - } - position++ - if buffer[position] != rune('-') { - goto l370 - } - position++ - { - position372, tokenIndex372 := position, tokenIndex - if buffer[position] != rune('0') { - goto l373 - } - position++ - if buffer[position] != rune('b') { - goto l373 - } - position++ - goto l372 - l373: - position, tokenIndex = position372, tokenIndex372 - if buffer[position] != rune('.') { - goto l370 - } - position++ - if buffer[position] != rune('L') { - goto l370 - } - position++ - { - position376, tokenIndex376 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l377 - } - position++ - goto l376 - l377: - position, tokenIndex = position376, tokenIndex376 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l378 - } - position++ - goto l376 - l378: - position, tokenIndex = position376, tokenIndex376 - if buffer[position] != rune('_') { - goto l379 - } - position++ - goto l376 - l379: - position, tokenIndex = position376, tokenIndex376 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l370 - } - position++ - } - l376: - l374: - { - position375, tokenIndex375 := position, tokenIndex - { - position380, tokenIndex380 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l381 - } - position++ - goto l380 - l381: - position, tokenIndex = position380, tokenIndex380 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l382 - } - position++ - goto l380 - l382: - position, tokenIndex = position380, tokenIndex380 - if buffer[position] != rune('_') { - goto l383 - } - position++ - goto l380 - l383: - position, tokenIndex = position380, tokenIndex380 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l375 - } - position++ - } - l380: - goto l374 - l375: - position, tokenIndex = position375, tokenIndex375 - } - } - l372: - if buffer[position] != rune('@') { - goto l370 - } - position++ - { - position384, tokenIndex384 := position, tokenIndex - if buffer[position] != rune('h') { - goto l385 - } - position++ - goto l384 - l385: - position, tokenIndex = position384, tokenIndex384 - if buffer[position] != rune('H') { - goto l370 - } - position++ - } - l384: - { - position386, tokenIndex386 := position, tokenIndex - if buffer[position] != rune('a') { - goto l387 - } - position++ - goto l386 - l387: - position, tokenIndex = position386, tokenIndex386 - if buffer[position] != rune('A') { - goto l370 - } - position++ - } - l386: - add(ruleTOCRefHigh, position371) - } - return true - l370: - position, tokenIndex = position370, tokenIndex370 - return false - }, - /* 29 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ - func() bool { - position388, tokenIndex388 := position, tokenIndex - { - position389 := position - if buffer[position] != rune('.') { - goto l388 - } - position++ - if buffer[position] != rune('T') { - goto l388 - } - position++ - if buffer[position] != rune('O') { - goto l388 - } - position++ - if buffer[position] != rune('C') { - goto l388 - } - position++ - if buffer[position] != rune('.') { - goto l388 - } - position++ - if buffer[position] != rune('-') { - goto l388 - } - position++ - { - position390, tokenIndex390 := position, tokenIndex - if buffer[position] != rune('0') { - goto l391 - } - position++ - if buffer[position] != rune('b') { - goto l391 - } - position++ - goto l390 - l391: - position, tokenIndex = position390, tokenIndex390 - if buffer[position] != rune('.') { - goto l388 - } - position++ - if buffer[position] != rune('L') { - goto l388 - } - position++ - { - position394, tokenIndex394 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l395 - } - position++ - goto l394 - l395: - position, tokenIndex = position394, tokenIndex394 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l396 - } - position++ - goto l394 - l396: - position, tokenIndex = position394, tokenIndex394 - if buffer[position] != rune('_') { - goto l397 - } - position++ - goto l394 - l397: - position, tokenIndex = position394, tokenIndex394 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l388 - } - position++ - } - l394: - l392: - { - position393, tokenIndex393 := position, tokenIndex - { - position398, tokenIndex398 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l399 - } - position++ - goto l398 - l399: - position, tokenIndex = position398, tokenIndex398 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l400 - } - position++ - goto l398 - l400: - position, tokenIndex = position398, tokenIndex398 - if buffer[position] != rune('_') { - goto l401 - } - position++ - goto l398 - l401: - position, tokenIndex = position398, tokenIndex398 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l393 - } - position++ - } - l398: - goto l392 - l393: - position, tokenIndex = position393, tokenIndex393 - } - } - l390: - if buffer[position] != rune('@') { - goto l388 - } - position++ - { - position402, tokenIndex402 := position, tokenIndex - if buffer[position] != rune('l') { - goto l403 - } - position++ - goto l402 - l403: - position, tokenIndex = position402, tokenIndex402 - if buffer[position] != rune('L') { - goto l388 - } - position++ - } - l402: - add(ruleTOCRefLow, position389) - } - return true - l388: - position, tokenIndex = position388, tokenIndex388 - return false - }, - /* 30 IndirectionIndicator <- <'*'> */ - func() bool { - position404, tokenIndex404 := position, tokenIndex - { - position405 := position - if buffer[position] != rune('*') { - goto l404 - } - position++ - add(ruleIndirectionIndicator, position405) - } - return true - l404: - position, tokenIndex = position404, tokenIndex404 - return false - }, - /* 31 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset))) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ - func() bool { - position406, tokenIndex406 := position, tokenIndex - { - position407 := position - { - position408, tokenIndex408 := position, tokenIndex - if buffer[position] != rune('%') { - goto l409 - } - position++ - { - position410, tokenIndex410 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l411 - } - position++ - goto l410 - l411: - position, tokenIndex = position410, tokenIndex410 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l409 - } - position++ - } - l410: - l412: - { - position413, tokenIndex413 := position, tokenIndex - { - position414, tokenIndex414 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l415 - } - position++ - goto l414 - l415: - position, tokenIndex = position414, tokenIndex414 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l416 - } - position++ - goto l414 - l416: - position, tokenIndex = position414, tokenIndex414 - { - position417, tokenIndex417 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l418 - } - position++ - goto l417 - l418: - position, tokenIndex = position417, tokenIndex417 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l413 - } - position++ - } - l417: - } - l414: - goto l412 - l413: - position, tokenIndex = position413, tokenIndex413 - } - goto l408 - l409: - position, tokenIndex = position408, tokenIndex408 - { - position419, tokenIndex419 := position, tokenIndex - if buffer[position] != rune('$') { - goto l419 - } - position++ - goto l420 - l419: - position, tokenIndex = position419, tokenIndex419 - } - l420: - { - position421, tokenIndex421 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l422 - } - if !_rules[ruleOffset]() { - goto l422 - } - goto l421 - l422: - position, tokenIndex = position421, tokenIndex421 - if !_rules[ruleOffset]() { - goto l406 - } - } - l421: - } - l408: - { - position423, tokenIndex423 := position, tokenIndex - { - position424, tokenIndex424 := position, tokenIndex - if buffer[position] != rune('f') { - goto l425 - } - position++ - goto l424 - l425: - position, tokenIndex = position424, tokenIndex424 - if buffer[position] != rune('b') { - goto l426 - } - position++ - goto l424 - l426: - position, tokenIndex = position424, tokenIndex424 - if buffer[position] != rune(':') { - goto l427 - } - position++ - goto l424 - l427: - position, tokenIndex = position424, tokenIndex424 - if buffer[position] != rune('(') { - goto l428 - } - position++ - goto l424 - l428: - position, tokenIndex = position424, tokenIndex424 - if buffer[position] != rune('+') { - goto l429 - } - position++ - goto l424 - l429: - position, tokenIndex = position424, tokenIndex424 - if buffer[position] != rune('-') { - goto l423 - } - position++ - } - l424: - goto l406 - l423: - position, tokenIndex = position423, tokenIndex423 - } - add(ruleRegisterOrConstant, position407) - } - return true - l406: - position, tokenIndex = position406, tokenIndex406 - return false - }, - /* 32 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / BaseIndexScale)> */ - func() bool { - position430, tokenIndex430 := position, tokenIndex - { - position431 := position - { - position432, tokenIndex432 := position, tokenIndex - if !_rules[ruleSymbolRef]() { - goto l433 - } - if !_rules[ruleBaseIndexScale]() { - goto l433 - } - goto l432 - l433: - position, tokenIndex = position432, tokenIndex432 - if !_rules[ruleSymbolRef]() { - goto l434 - } - goto l432 - l434: - position, tokenIndex = position432, tokenIndex432 - l436: - { - position437, tokenIndex437 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l437 - } - goto l436 - l437: - position, tokenIndex = position437, tokenIndex437 - } - if !_rules[ruleBaseIndexScale]() { - goto l435 - } - goto l432 - l435: - position, tokenIndex = position432, tokenIndex432 - if !_rules[ruleSegmentRegister]() { - goto l438 - } - if !_rules[ruleOffset]() { - goto l438 - } - if !_rules[ruleBaseIndexScale]() { - goto l438 - } - goto l432 - l438: - position, tokenIndex = position432, tokenIndex432 - if !_rules[ruleSegmentRegister]() { - goto l439 - } - if !_rules[ruleBaseIndexScale]() { - goto l439 - } - goto l432 - l439: - position, tokenIndex = position432, tokenIndex432 - if !_rules[ruleSegmentRegister]() { - goto l440 - } - if !_rules[ruleOffset]() { - goto l440 - } - goto l432 - l440: - position, tokenIndex = position432, tokenIndex432 - if !_rules[ruleBaseIndexScale]() { - goto l430 - } - } - l432: - add(ruleMemoryRef, position431) - } - return true - l430: - position, tokenIndex = position430, tokenIndex430 - return false - }, - /* 33 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ - func() bool { - position441, tokenIndex441 := position, tokenIndex - { - position442 := position - { - position443, tokenIndex443 := position, tokenIndex - l445: - { - position446, tokenIndex446 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l446 - } - goto l445 - l446: - position, tokenIndex = position446, tokenIndex446 - } - if buffer[position] != rune('+') { - goto l443 - } - position++ - goto l444 - l443: - position, tokenIndex = position443, tokenIndex443 - } - l444: - { - position447, tokenIndex447 := position, tokenIndex - if !_rules[ruleLocalSymbol]() { - goto l448 - } - goto l447 - l448: - position, tokenIndex = position447, tokenIndex447 - if !_rules[ruleSymbolName]() { - goto l441 - } - } - l447: - l449: - { - position450, tokenIndex450 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l450 - } - goto l449 - l450: - position, tokenIndex = position450, tokenIndex450 - } - { - position451, tokenIndex451 := position, tokenIndex - if buffer[position] != rune('@') { - goto l451 - } - position++ - if !_rules[ruleSection]() { - goto l451 - } - l453: - { - position454, tokenIndex454 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l454 - } - goto l453 - l454: - position, tokenIndex = position454, tokenIndex454 - } - goto l452 - l451: - position, tokenIndex = position451, tokenIndex451 - } - l452: - add(ruleSymbolRef, position442) - } - return true - l441: - position, tokenIndex = position441, tokenIndex441 - return false - }, - /* 34 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ - func() bool { - position455, tokenIndex455 := position, tokenIndex - { - position456 := position - if buffer[position] != rune('(') { - goto l455 - } - position++ - { - position457, tokenIndex457 := position, tokenIndex - if !_rules[ruleRegisterOrConstant]() { - goto l457 - } - goto l458 - l457: - position, tokenIndex = position457, tokenIndex457 - } - l458: - { - position459, tokenIndex459 := position, tokenIndex - if !_rules[ruleWS]() { - goto l459 - } - goto l460 - l459: - position, tokenIndex = position459, tokenIndex459 - } - l460: - { - position461, tokenIndex461 := position, tokenIndex - if buffer[position] != rune(',') { - goto l461 - } - position++ - { - position463, tokenIndex463 := position, tokenIndex - if !_rules[ruleWS]() { - goto l463 - } - goto l464 - l463: - position, tokenIndex = position463, tokenIndex463 - } - l464: - if !_rules[ruleRegisterOrConstant]() { - goto l461 - } - { - position465, tokenIndex465 := position, tokenIndex - if !_rules[ruleWS]() { - goto l465 - } - goto l466 - l465: - position, tokenIndex = position465, tokenIndex465 - } - l466: - { - position467, tokenIndex467 := position, tokenIndex - if buffer[position] != rune(',') { - goto l467 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l467 - } - position++ - l469: - { - position470, tokenIndex470 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l470 - } - position++ - goto l469 - l470: - position, tokenIndex = position470, tokenIndex470 - } - goto l468 - l467: - position, tokenIndex = position467, tokenIndex467 - } - l468: - goto l462 - l461: - position, tokenIndex = position461, tokenIndex461 - } - l462: - if buffer[position] != rune(')') { - goto l455 - } - position++ - add(ruleBaseIndexScale, position456) - } - return true - l455: - position, tokenIndex = position455, tokenIndex455 - return false - }, - /* 35 Operator <- <('+' / '-')> */ - func() bool { - position471, tokenIndex471 := position, tokenIndex - { - position472 := position - { - position473, tokenIndex473 := position, tokenIndex - if buffer[position] != rune('+') { - goto l474 - } - position++ - goto l473 - l474: - position, tokenIndex = position473, tokenIndex473 - if buffer[position] != rune('-') { - goto l471 - } - position++ - } - l473: - add(ruleOperator, position472) - } - return true - l471: - position, tokenIndex = position471, tokenIndex471 - return false - }, - /* 36 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ - func() bool { - position475, tokenIndex475 := position, tokenIndex - { - position476 := position - { - position477, tokenIndex477 := position, tokenIndex - if buffer[position] != rune('+') { - goto l477 - } - position++ - goto l478 - l477: - position, tokenIndex = position477, tokenIndex477 - } - l478: - { - position479, tokenIndex479 := position, tokenIndex - if buffer[position] != rune('-') { - goto l479 - } - position++ - goto l480 - l479: - position, tokenIndex = position479, tokenIndex479 - } - l480: - { - position481, tokenIndex481 := position, tokenIndex - if buffer[position] != rune('0') { - goto l482 - } - position++ - { - position483, tokenIndex483 := position, tokenIndex - if buffer[position] != rune('b') { - goto l484 - } - position++ - goto l483 - l484: - position, tokenIndex = position483, tokenIndex483 - if buffer[position] != rune('B') { - goto l482 - } - position++ - } - l483: - { - position487, tokenIndex487 := position, tokenIndex - if buffer[position] != rune('0') { - goto l488 - } - position++ - goto l487 - l488: - position, tokenIndex = position487, tokenIndex487 - if buffer[position] != rune('1') { - goto l482 - } - position++ - } - l487: - l485: - { - position486, tokenIndex486 := position, tokenIndex - { - position489, tokenIndex489 := position, tokenIndex - if buffer[position] != rune('0') { - goto l490 - } - position++ - goto l489 - l490: - position, tokenIndex = position489, tokenIndex489 - if buffer[position] != rune('1') { - goto l486 - } - position++ - } - l489: - goto l485 - l486: - position, tokenIndex = position486, tokenIndex486 - } - goto l481 - l482: - position, tokenIndex = position481, tokenIndex481 - if buffer[position] != rune('0') { - goto l491 - } - position++ - { - position492, tokenIndex492 := position, tokenIndex - if buffer[position] != rune('x') { - goto l493 - } - position++ - goto l492 - l493: - position, tokenIndex = position492, tokenIndex492 - if buffer[position] != rune('X') { - goto l491 - } - position++ - } - l492: - { - position496, tokenIndex496 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l497 - } - position++ - goto l496 - l497: - position, tokenIndex = position496, tokenIndex496 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l498 - } - position++ - goto l496 - l498: - position, tokenIndex = position496, tokenIndex496 - { - position499, tokenIndex499 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l500 - } - position++ - goto l499 - l500: - position, tokenIndex = position499, tokenIndex499 - if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l491 - } - position++ - } - l499: - } - l496: - l494: - { - position495, tokenIndex495 := position, tokenIndex - { - position501, tokenIndex501 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l502 - } - position++ - goto l501 - l502: - position, tokenIndex = position501, tokenIndex501 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l503 - } - position++ - goto l501 - l503: - position, tokenIndex = position501, tokenIndex501 - { - position504, tokenIndex504 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l505 - } - position++ - goto l504 - l505: - position, tokenIndex = position504, tokenIndex504 - if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l495 - } - position++ - } - l504: - } - l501: - goto l494 - l495: - position, tokenIndex = position495, tokenIndex495 - } - goto l481 - l491: - position, tokenIndex = position481, tokenIndex481 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l475 - } - position++ - l506: - { - position507, tokenIndex507 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l507 - } - position++ - goto l506 - l507: - position, tokenIndex = position507, tokenIndex507 - } - } - l481: - add(ruleOffset, position476) - } - return true - l475: - position, tokenIndex = position475, tokenIndex475 - return false - }, - /* 37 Section <- <([a-z] / [A-Z] / '@')+> */ - func() bool { - position508, tokenIndex508 := position, tokenIndex - { - position509 := position - { - position512, tokenIndex512 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l513 - } - position++ - goto l512 - l513: - position, tokenIndex = position512, tokenIndex512 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l514 - } - position++ - goto l512 - l514: - position, tokenIndex = position512, tokenIndex512 - if buffer[position] != rune('@') { - goto l508 - } - position++ - } - l512: - l510: - { - position511, tokenIndex511 := position, tokenIndex - { - position515, tokenIndex515 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l516 - } - position++ - goto l515 - l516: - position, tokenIndex = position515, tokenIndex515 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l517 - } - position++ - goto l515 - l517: - position, tokenIndex = position515, tokenIndex515 - if buffer[position] != rune('@') { - goto l511 - } - position++ - } - l515: - goto l510 - l511: - position, tokenIndex = position511, tokenIndex511 - } - add(ruleSection, position509) - } - return true - l508: - position, tokenIndex = position508, tokenIndex508 - return false - }, - /* 38 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ - func() bool { - position518, tokenIndex518 := position, tokenIndex - { - position519 := position - if buffer[position] != rune('%') { - goto l518 - } - position++ - { - position520, tokenIndex520 := position, tokenIndex - if c := buffer[position]; c < rune('c') || c > rune('g') { - goto l521 - } - position++ - goto l520 - l521: - position, tokenIndex = position520, tokenIndex520 - if buffer[position] != rune('s') { - goto l518 - } - position++ - } - l520: - if buffer[position] != rune('s') { - goto l518 - } - position++ - if buffer[position] != rune(':') { - goto l518 - } - position++ - add(ruleSegmentRegister, position519) - } - return true - l518: - position, tokenIndex = position518, tokenIndex518 - return false - }, - } - p.rules = _rules -} diff --git a/src/util/fipstools/delocate/delocate.go b/src/util/fipstools/delocate/delocate.go new file mode 100644 index 00000000..a8c4fd0e --- /dev/null +++ b/src/util/fipstools/delocate/delocate.go @@ -0,0 +1,1651 @@ +// 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. */ + +// delocate performs several transformations of textual assembly code. See +// crypto/fipsmodule/FIPS.md for an overview. +package main + +import ( + "errors" + "flag" + "fmt" + "io/ioutil" + "os" + "sort" + "strconv" + "strings" + + "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon" +) + +// inputFile represents a textual assembly file. +type inputFile struct { + path string + // index is a unique identifer given to this file. It's used for + // mapping local symbols. + index int + // isArchive indicates that the input should be processed as an ar + // file. + isArchive bool + // contents contains the contents of the file. + contents string + // ast points to the head of the syntax tree. + ast *node32 +} + +type stringWriter interface { + WriteString(string) (int, error) +} + +type processorType int + +const ( + ppc64le processorType = iota + 1 + x86_64 +) + +// delocation holds the state needed during a delocation operation. +type delocation struct { + processor processorType + output stringWriter + + // symbols is the set of symbols defined in the module. + symbols map[string]struct{} + // localEntrySymbols is the set of symbols with .localentry directives. + localEntrySymbols map[string]struct{} + // redirectors maps from out-call symbol name to the name of a + // redirector function for that symbol. E.g. “memcpy” -> + // “bcm_redirector_memcpy”. + redirectors map[string]string + // bssAccessorsNeeded maps from a BSS symbol name to the symbol that + // should be used to reference it. E.g. “P384_data_storage” -> + // “P384_data_storage”. + bssAccessorsNeeded map[string]string + // tocLoaders is a set of symbol names for which TOC helper functions + // are required. (ppc64le only.) + tocLoaders map[string]struct{} + // gotExternalsNeeded is a set of symbol names for which we need + // “delta” symbols: symbols that contain the offset from their location + // to the memory in question. + gotExternalsNeeded map[string]struct{} + + currentInput inputFile +} + +func (d *delocation) contents(node *node32) string { + return d.currentInput.contents[node.begin:node.end] +} + +// writeNode writes out an AST node. +func (d *delocation) writeNode(node *node32) { + if _, err := d.output.WriteString(d.contents(node)); err != nil { + panic(err) + } +} + +func (d *delocation) writeCommentedNode(node *node32) { + line := d.contents(node) + if _, err := d.output.WriteString("# WAS " + strings.TrimSpace(line) + "\n"); err != nil { + panic(err) + } +} + +func locateError(err error, with *node32, in inputFile) error { + posMap := translatePositions([]rune(in.contents), []int{int(with.begin)}) + var line int + for _, pos := range posMap { + line = pos.line + } + + return fmt.Errorf("error while processing %q on line %d: %q", in.contents[with.begin:with.end], line, err) +} + +func (d *delocation) processInput(input inputFile) (err error) { + d.currentInput = input + + var origStatement *node32 + defer func() { + if err := recover(); err != nil { + panic(locateError(fmt.Errorf("%s", err), origStatement, input)) + } + }() + + for statement := input.ast.up; statement != nil; statement = statement.next { + assertNodeType(statement, ruleStatement) + origStatement = statement + + node := skipWS(statement.up) + if node == nil { + d.writeNode(statement) + continue + } + + switch node.pegRule { + case ruleGlobalDirective, ruleComment, ruleLocationDirective: + d.writeNode(statement) + case ruleDirective: + statement, err = d.processDirective(statement, node.up) + case ruleLabelContainingDirective: + statement, err = d.processLabelContainingDirective(statement, node.up) + case ruleLabel: + statement, err = d.processLabel(statement, node.up) + case ruleInstruction: + switch d.processor { + case x86_64: + statement, err = d.processIntelInstruction(statement, node.up) + case ppc64le: + statement, err = d.processPPCInstruction(statement, node.up) + default: + panic("unknown processor") + } + default: + panic(fmt.Sprintf("unknown top-level statement type %q", rul3s[node.pegRule])) + } + + if err != nil { + return locateError(err, origStatement, input) + } + } + + return nil +} + +func (d *delocation) processDirective(statement, directive *node32) (*node32, error) { + assertNodeType(directive, ruleDirectiveName) + directiveName := d.contents(directive) + + var args []string + forEachPath(directive, func(arg *node32) { + // If the argument is a quoted string, use the raw contents. + // (Note that this doesn't unescape the string, but that's not + // needed so far. + if arg.up != nil { + arg = arg.up + assertNodeType(arg, ruleQuotedArg) + if arg.up == nil { + args = append(args, "") + return + } + arg = arg.up + assertNodeType(arg, ruleQuotedText) + } + args = append(args, d.contents(arg)) + }, ruleArgs, ruleArg) + + switch directiveName { + case "comm", "lcomm": + if len(args) < 1 { + return nil, errors.New("comm directive has no arguments") + } + d.bssAccessorsNeeded[args[0]] = args[0] + d.writeNode(statement) + + case "data": + // ASAN and some versions of MSAN are adding a .data section, + // and adding references to symbols within it to the code. We + // will have to work around this in the future. + return nil, errors.New(".data section found in module") + + case "section": + section := args[0] + + if section == ".data.rel.ro" { + // In a normal build, this is an indication of a + // problem but any references from the module to this + // section will result in a relocation and thus will + // break the integrity check. ASAN can generate these + // sections and so we will likely have to work around + // that in the future. + return nil, errors.New(".data.rel.ro section found in module") + } + + sectionType, ok := sectionType(section) + if !ok { + // Unknown sections are permitted in order to be robust + // to different compiler modes. + d.writeNode(statement) + break + } + + switch sectionType { + case ".rodata", ".text": + // Move .rodata to .text so it may be accessed without + // a relocation. GCC with -fmerge-constants will place + // strings into separate sections, so we move all + // sections named like .rodata. Also move .text.startup + // so the self-test function is also in the module. + d.writeCommentedNode(statement) + d.output.WriteString(".text\n") + + case ".data": + // See above about .data + return nil, errors.New(".data section found in module") + + case ".init_array", ".fini_array", ".ctors", ".dtors": + // init_array/ctors/dtors contains function + // pointers to constructor/destructor + // functions. These contain relocations, but + // they're in a different section anyway. + d.writeNode(statement) + break + + case ".debug", ".note", ".toc": + d.writeNode(statement) + break + + case ".bss": + d.writeNode(statement) + return d.handleBSS(statement) + } + + default: + d.writeNode(statement) + } + + return statement, nil +} + +func (d *delocation) processLabelContainingDirective(statement, directive *node32) (*node32, error) { + // The symbols within directives need to be mapped so that local + // symbols in two different .s inputs don't collide. + changed := false + assertNodeType(directive, ruleLabelContainingDirectiveName) + name := d.contents(directive) + + node := directive.next + assertNodeType(node, ruleWS) + + node = node.next + assertNodeType(node, ruleSymbolArgs) + + var args []string + for node = skipWS(node.up); node != nil; node = skipWS(node.next) { + assertNodeType(node, ruleSymbolArg) + arg := node.up + var mapped string + + for term := arg; term != nil; term = term.next { + if term.pegRule != ruleLocalSymbol { + mapped += d.contents(term) + continue + } + + oldSymbol := d.contents(term) + newSymbol := d.mapLocalSymbol(oldSymbol) + if newSymbol != oldSymbol { + changed = true + } + + mapped += newSymbol + } + + args = append(args, mapped) + } + + if !changed { + d.writeNode(statement) + } else { + d.writeCommentedNode(statement) + d.output.WriteString("\t" + name + "\t" + strings.Join(args, ", ") + "\n") + } + + if name == ".localentry" { + d.output.WriteString(localEntryName(args[0]) + ":\n") + } + + return statement, nil +} + +func (d *delocation) processLabel(statement, label *node32) (*node32, error) { + symbol := d.contents(label) + + switch label.pegRule { + case ruleLocalLabel: + d.output.WriteString(symbol + ":\n") + case ruleLocalSymbol: + // symbols need to be mapped so that local symbols from two + // different .s inputs don't collide. + d.output.WriteString(d.mapLocalSymbol(symbol) + ":\n") + case ruleSymbolName: + d.output.WriteString(localTargetName(symbol) + ":\n") + d.writeNode(statement) + default: + return nil, fmt.Errorf("unknown label type %q", rul3s[label.pegRule]) + } + + return statement, nil +} + +// instructionArgs collects all the arguments to an instruction. +func instructionArgs(node *node32) (argNodes []*node32) { + for node = skipWS(node); node != nil; node = skipWS(node.next) { + assertNodeType(node, ruleInstructionArg) + argNodes = append(argNodes, node.up) + } + + return argNodes +} + +/* ppc64le + +[PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st, + 2017 + +(Also useful is “Power ISA Version 2.07 B”. Note that version three of that +document is /not/ good as that's POWER9 specific.) + +ppc64le doesn't have IP-relative addressing and does a lot to work around this. +Rather than reference a PLT and GOT direction, it has a single structure called +the TOC (Table Of Contents). Within the TOC is the contents of .rodata, .data, +.got, .plt, .bss, etc sections [PABI;3.3]. + +A pointer to the TOC is maintained in r2 and the following pattern is used to +load the address of an element into a register: + + addis
, 2, foo@toc@ha + addi
,
, foo@toc@l + +The “addis” instruction shifts a signed constant left 16 bits and adds the +result to its second argument, saving the result in the first argument. The +“addi” instruction does the same, but without shifting. Thus the “@toc@ha" +suffix on a symbol means “the top 16 bits of the TOC offset” and “@toc@l” means +“the bottom 16 bits of the offset”. However, note that both values are signed, +thus offsets in the top half of a 64KB chunk will have an @ha value that's one +greater than expected and a negative @l value. + +The TOC is specific to a “module” (basically an executable or shared object). +This means that there's not a single TOC in a process and that r2 needs to +change as control moves between modules. Thus functions have two entry points: +the “global” entry point and the “local” entry point. Jumps from within the +same module can use the local entry while jumps from other modules must use the +global entry. The global entry establishes the correct value of r2 before +running the function and the local entry skips that code. + +The global entry point for a function is defined by its label. The local entry +is a power-of-two number of bytes from the global entry, set by the +“.localentry” directive. (ppc64le instructions are always 32 bits, so an offset +of 1 or 2 bytes is treated as an offset of zero.) + +In order to help the global entry code set r2 to point to the local TOC, r12 is +set to the address of the global entry point when called [PABI;2.2.1.1]. Thus +the global entry will typically use an addis+addi pair to add a known offset to +r12 and store it in r2. For example: + +foo: + addis 2, 12, .TOC. - foo@ha + addi 2, 2, .TOC. - foo@l + +(It's worth noting that the '@' operator binds very loosely, so the 3rd +arguments parse as (.TOC. - foo)@ha and (.TOC. - foo)@l.) + +When calling a function, the compiler doesn't know whether that function is in +the same module or not. Thus it doesn't know whether r12 needs to be set nor +whether r2 will be clobbered on return. Rather than always assume the worst, +the linker fixes stuff up once it knows that a call is going out of module: + +Firstly, calling, say, memcpy (which we assume to be in a different module) +won't actually jump directly to memcpy, or even a PLT resolution function. +It'll call a synthesised function that: + a) saves r2 in the caller's stack frame + b) loads the address of memcpy@PLT into r12 + c) jumps to r12. + +As this synthesised function loads memcpy@PLT, a call to memcpy from the +compiled code just references “memcpy” directly, not “memcpy@PLT”. + +Since it jumps directly to memcpy@PLT, it can't restore r2 on return. Thus +calls must be followed by a nop. If the call ends up going out-of-module, the +linker will rewrite that nop to load r2 from the stack. + +Speaking of the stack, the stack pointer is kept in r1 and there's a 288-byte +red-zone. The format of the stack frame is defined [PABI;2.2.2] and must be +followed as called functions will write into their parent's stack frame. For +example, the synthesised out-of-module trampolines will save r2 24 bytes into +the caller's frame and all non-leaf functions save the return address 16 bytes +into the caller's frame. + +A final point worth noting: some RISC ISAs have r0 wired to zero: all reads +result in zero and all writes are discarded. POWER does something a little like +that, but r0 is only special in certain argument positions for certain +instructions. You just have to read the manual to know which they are. + + +Delocation is easier than Intel because there's just TOC references, but it's +also harder because there's no IP-relative addressing. + +Jumps are IP-relative however, and have a 24-bit immediate value. So we can +jump to functions that set a register to the needed value. (r3 is the +return-value register and so that's what is generally used here.) */ + +// isPPC64LEAPair recognises an addis+addi pair that's adding the offset of +// source to relative and writing the result to target. +func (d *delocation) isPPC64LEAPair(statement *node32) (target, source, relative string, ok bool) { + instruction := skipWS(statement.up).up + assertNodeType(instruction, ruleInstructionName) + name1 := d.contents(instruction) + args1 := instructionArgs(instruction.next) + + statement = statement.next + instruction = skipWS(statement.up).up + assertNodeType(instruction, ruleInstructionName) + name2 := d.contents(instruction) + args2 := instructionArgs(instruction.next) + + if name1 != "addis" || + len(args1) != 3 || + name2 != "addi" || + len(args2) != 3 { + return "", "", "", false + } + + target = d.contents(args1[0]) + relative = d.contents(args1[1]) + source1 := d.contents(args1[2]) + source2 := d.contents(args2[2]) + + if !strings.HasSuffix(source1, "@ha") || + !strings.HasSuffix(source2, "@l") || + source1[:len(source1)-3] != source2[:len(source2)-2] || + d.contents(args2[0]) != target || + d.contents(args2[1]) != target { + return "", "", "", false + } + + source = source1[:len(source1)-3] + ok = true + return +} + +// establishTOC writes the global entry prelude for a function. The standard +// prelude involves relocations so this version moves the relocation outside +// the integrity-checked area. +func establishTOC(w stringWriter) { + w.WriteString("999:\n") + w.WriteString("\taddis 2, 12, .LBORINGSSL_external_toc-999b@ha\n") + w.WriteString("\taddi 2, 2, .LBORINGSSL_external_toc-999b@l\n") + w.WriteString("\tld 12, 0(2)\n") + w.WriteString("\tadd 2, 2, 12\n") +} + +// loadTOCFuncName returns the name of a synthesized function that sets r3 to +// the value of “symbol+offset”. +func loadTOCFuncName(symbol, offset string) string { + symbol = strings.Replace(symbol, ".", "_dot_", -1) + ret := ".Lbcm_loadtoc_" + symbol + if len(offset) != 0 { + offset = strings.Replace(offset, "+", "_plus_", -1) + offset = strings.Replace(offset, "-", "_minus_", -1) + ret += "_" + offset + } + return ret +} + +func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc { + d.tocLoaders[symbol+"\x00"+offset] = struct{}{} + + return func(k func()) { + w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone. + w.WriteString("\tmflr " + dest + "\n") // Stash the link register. + w.WriteString("\tstd " + dest + ", -8(1)\n") + // The TOC loader will use r3, so stash it if necessary. + if dest != "3" { + w.WriteString("\tstd 3, -16(1)\n") + } + + // Because loadTOCFuncName returns a “.L” name, we don't need a + // nop after this call. + w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n") + + // Cycle registers around. We need r3 -> destReg, -8(1) -> + // lr and, optionally, -16(1) -> r3. + w.WriteString("\tstd 3, -24(1)\n") + w.WriteString("\tld 3, -8(1)\n") + w.WriteString("\tmtlr 3\n") + w.WriteString("\tld " + dest + ", -24(1)\n") + if dest != "3" { + w.WriteString("\tld 3, -16(1)\n") + } + w.WriteString("\taddi 1, 1, 288\n") + + k() + } +} + +func (d *delocation) gatherOffsets(symRef *node32, offsets string) (*node32, string) { + for symRef != nil && symRef.pegRule == ruleOffset { + offset := d.contents(symRef) + if offset[0] != '+' && offset[0] != '-' { + offset = "+" + offset + } + offsets = offsets + offset + symRef = symRef.next + } + return symRef, offsets +} + +func (d *delocation) parseMemRef(memRef *node32) (symbol, offset, section string, didChange, symbolIsLocal bool, nextRef *node32) { + if memRef.pegRule != ruleSymbolRef { + return "", "", "", false, false, memRef + } + + symRef := memRef.up + nextRef = memRef.next + + // (Offset* '+')? + symRef, offset = d.gatherOffsets(symRef, offset) + + // (LocalSymbol / SymbolName) + symbol = d.contents(symRef) + if symRef.pegRule == ruleLocalSymbol { + symbolIsLocal = true + mapped := d.mapLocalSymbol(symbol) + if mapped != symbol { + symbol = mapped + didChange = true + } + } + symRef = symRef.next + + // Offset* + symRef, offset = d.gatherOffsets(symRef, offset) + + // ('@' Section / Offset*)? + if symRef != nil { + assertNodeType(symRef, ruleSection) + section = d.contents(symRef) + symRef = symRef.next + + symRef, offset = d.gatherOffsets(symRef, offset) + } + + if symRef != nil { + panic(fmt.Sprintf("unexpected token in SymbolRef: %q", rul3s[symRef.pegRule])) + } + + return +} + +func (d *delocation) processPPCInstruction(statement, instruction *node32) (*node32, error) { + assertNodeType(instruction, ruleInstructionName) + instructionName := d.contents(instruction) + isBranch := instructionName[0] == 'b' + + argNodes := instructionArgs(instruction.next) + + var wrappers wrapperStack + var args []string + changed := false + +Args: + for i, arg := range argNodes { + fullArg := arg + isIndirect := false + + if arg.pegRule == ruleIndirectionIndicator { + arg = arg.next + isIndirect = true + } + + switch arg.pegRule { + case ruleRegisterOrConstant, ruleLocalLabelRef: + args = append(args, d.contents(fullArg)) + + case ruleTOCRefLow: + return nil, errors.New("Found low TOC reference outside preamble pattern") + + case ruleTOCRefHigh: + target, _, relative, ok := d.isPPC64LEAPair(statement) + if !ok { + return nil, errors.New("Found high TOC reference outside preamble pattern") + } + + if relative != "12" { + return nil, fmt.Errorf("preamble is relative to %q, not r12", relative) + } + + if target != "2" { + return nil, fmt.Errorf("preamble is setting %q, not r2", target) + } + + statement = statement.next + establishTOC(d.output) + instructionName = "" + changed = true + break Args + + case ruleMemoryRef: + symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up) + changed = didChange + + if len(symbol) > 0 { + if _, localEntrySymbol := d.localEntrySymbols[symbol]; localEntrySymbol && isBranch { + symbol = localEntryName(symbol) + changed = true + } else if _, knownSymbol := d.symbols[symbol]; knownSymbol { + symbol = localTargetName(symbol) + changed = true + } else if !symbolIsLocal && !isSynthesized(symbol) && len(section) == 0 { + changed = true + d.redirectors[symbol] = redirectorName(symbol) + symbol = redirectorName(symbol) + // TODO(davidben): This should sanity-check the next + // instruction is a nop and ideally remove it. + wrappers = append(wrappers, func(k func()) { + k() + // Like the linker's PLT stubs, redirector functions + // expect callers to restore r2. + d.output.WriteString("\tld 2, 24(1)\n") + }) + } + } + + switch section { + case "": + + case "tls": + // This section identifier just tells the + // assembler to use r13, the pointer to the + // thread-local data [PABI;3.7.3.3]. + + case "toc@ha": + // Delete toc@ha instructions. Per + // [PABI;3.6.3], the linker is allowed to erase + // toc@ha instructions. We take advantage of + // this by unconditionally erasing the toc@ha + // instructions and doing the full lookup when + // processing toc@l. + // + // Note that any offset here applies before @ha + // and @l. That is, 42+foo@toc@ha is + // #ha(42+foo-.TOC.), not 42+#ha(foo-.TOC.). Any + // corresponding toc@l references are required + // by the ABI to have the same offset. The + // offset will be incorporated in full when + // those are processed. + if instructionName != "addis" || len(argNodes) != 3 || i != 2 || args[1] != "2" { + return nil, errors.New("can't process toc@ha reference") + } + changed = true + instructionName = "" + break Args + + case "toc@l": + // Per [PAB;3.6.3], this instruction must take + // as input a register which was the output of + // a toc@ha computation and compute the actual + // address of some symbol. The toc@ha + // computation was elided, so we ignore that + // input register and compute the address + // directly. + changed = true + + // For all supported toc@l instructions, the + // destination register is the first argument. + destReg := args[0] + + wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg)) + switch instructionName { + case "addi": + // The original instruction was: + // addi destReg, tocHaReg, offset+symbol@toc@l + instructionName = "" + + case "ld", "lhz", "lwz": + // The original instruction was: + // l?? destReg, offset+symbol@toc@l(tocHaReg) + // + // We transform that into the + // equivalent dereference of destReg: + // l?? destReg, 0(destReg) + origInstructionName := instructionName + instructionName = "" + + assertNodeType(memRef, ruleBaseIndexScale) + assertNodeType(memRef.up, ruleRegisterOrConstant) + if memRef.next != nil || memRef.up.next != nil { + return nil, errors.New("expected single register in BaseIndexScale for ld argument") + } + + baseReg := destReg + if baseReg == "0" { + // Register zero is special as the base register for a load. + // Avoid it by spilling and using r3 instead. + baseReg = "3" + wrappers = append(wrappers, func(k func()) { + d.output.WriteString("\taddi 1, 1, -288\n") // Clear the red zone. + d.output.WriteString("\tstd " + baseReg + ", -8(1)\n") + d.output.WriteString("\tmr " + baseReg + ", " + destReg + "\n") + k() + d.output.WriteString("\tld " + baseReg + ", -8(1)\n") + d.output.WriteString("\taddi 1, 1, 288\n") // Clear the red zone. + }) + } + + wrappers = append(wrappers, func(k func()) { + d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + baseReg + ")\n") + }) + default: + return nil, fmt.Errorf("can't process TOC argument to %q", instructionName) + } + + default: + return nil, fmt.Errorf("Unknown section type %q", section) + } + + argStr := "" + if isIndirect { + argStr += "*" + } + argStr += symbol + if len(offset) > 0 { + argStr += offset + } + if len(section) > 0 { + argStr += "@" + argStr += section + } + + for ; memRef != nil; memRef = memRef.next { + argStr += d.contents(memRef) + } + + args = append(args, argStr) + + default: + panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule])) + } + } + + if changed { + d.writeCommentedNode(statement) + + var replacement string + if len(instructionName) > 0 { + replacement = "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n" + } + + wrappers.do(func() { + d.output.WriteString(replacement) + }) + } else { + d.writeNode(statement) + } + + return statement, nil +} + +/* Intel */ + +type instructionType int + +const ( + instrPush instructionType = iota + instrMove + // instrTransformingMove is essentially a move, but it performs some + // transformation of the data during the process. + instrTransformingMove + instrJump + instrConditionalMove + // instrCombine merges the source and destination in some fashion, for example + // a 2-operand bitwise operation. + instrCombine + instrOther +) + +func classifyInstruction(instr string, args []*node32) instructionType { + switch instr { + case "push", "pushq": + if len(args) == 1 { + return instrPush + } + + case "mov", "movq", "vmovq", "movsd", "vmovsd": + if len(args) == 2 { + return instrMove + } + + case "cmovneq", "cmoveq": + if len(args) == 2 { + return instrConditionalMove + } + + case "call", "callq", "jmp", "jo", "jno", "js", "jns", "je", "jz", "jne", "jnz", "jb", "jnae", "jc", "jnb", "jae", "jnc", "jbe", "jna", "ja", "jnbe", "jl", "jnge", "jge", "jnl", "jle", "jng", "jg", "jnle", "jp", "jpe", "jnp", "jpo": + if len(args) == 1 { + return instrJump + } + + case "orq", "andq", "xorq": + if len(args) == 2 { + return instrCombine + } + + case "vpbroadcastq": + if len(args) == 2 { + return instrTransformingMove + } + } + + return instrOther +} + +func push(w stringWriter) wrapperFunc { + return func(k func()) { + w.WriteString("\tpushq %rax\n") + k() + w.WriteString("\txchg %rax, (%rsp)\n") + } +} + +func (d *delocation) loadFromGOT(w stringWriter, destination, symbol, section string, redzoneCleared bool) wrapperFunc { + d.gotExternalsNeeded[symbol+"@"+section] = struct{}{} + + return func(k func()) { + if !redzoneCleared { + w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. + } + w.WriteString("\tpushf\n") + w.WriteString(fmt.Sprintf("\tleaq %s_%s_external(%%rip), %s\n", symbol, section, destination)) + w.WriteString(fmt.Sprintf("\taddq (%s), %s\n", destination, destination)) + w.WriteString(fmt.Sprintf("\tmovq (%s), %s\n", destination, destination)) + w.WriteString("\tpopf\n") + if !redzoneCleared { + w.WriteString("\tleaq\t128(%rsp), %rsp\n") + } + } +} + +func saveFlags(w stringWriter, redzoneCleared bool) wrapperFunc { + return func(k func()) { + if !redzoneCleared { + w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. + defer w.WriteString("\tleaq 128(%rsp), %rsp\n") + } + w.WriteString("\tpushfq\n") + k() + w.WriteString("\tpopfq\n") + } +} + +func saveRegister(w stringWriter, avoidReg string) (wrapperFunc, string) { + reg := "%rax" + if reg == avoidReg { + reg = "%rbx" + } + + return func(k func()) { + w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone. + w.WriteString("\tpushq " + reg + "\n") + k() + w.WriteString("\tpopq " + reg + "\n") + w.WriteString("\tleaq 128(%rsp), %rsp\n") + }, reg +} + +func moveTo(w stringWriter, target string, isAVX bool, source string) wrapperFunc { + return func(k func()) { + k() + prefix := "" + if isAVX { + prefix = "v" + } + w.WriteString("\t" + prefix + "movq " + source + ", " + target + "\n") + } +} + +func finalTransform(w stringWriter, transformInstruction, reg string) wrapperFunc { + return func(k func()) { + k() + w.WriteString("\t" + transformInstruction + " " + reg + ", " + reg + "\n") + } +} + +func combineOp(w stringWriter, instructionName, source, dest string) wrapperFunc { + return func(k func()) { + k() + w.WriteString("\t" + instructionName + " " + source + ", " + dest + "\n") + } +} + +func isValidLEATarget(reg string) bool { + return !strings.HasPrefix(reg, "%xmm") && !strings.HasPrefix(reg, "%ymm") && !strings.HasPrefix(reg, "%zmm") +} + +func undoConditionalMove(w stringWriter, instr string) wrapperFunc { + var invertedCondition string + + switch instr { + case "cmoveq": + invertedCondition = "ne" + case "cmovneq": + invertedCondition = "e" + default: + panic(fmt.Sprintf("don't know how to handle conditional move instruction %q", instr)) + } + + return func(k func()) { + w.WriteString("\tj" + invertedCondition + " 999f\n") + k() + w.WriteString("999:\n") + } +} + +func (d *delocation) isRIPRelative(node *node32) bool { + return node != nil && node.pegRule == ruleBaseIndexScale && d.contents(node) == "(%rip)" +} + +func (d *delocation) processIntelInstruction(statement, instruction *node32) (*node32, error) { + assertNodeType(instruction, ruleInstructionName) + instructionName := d.contents(instruction) + + argNodes := instructionArgs(instruction.next) + + var wrappers wrapperStack + var args []string + changed := false + +Args: + for i, arg := range argNodes { + fullArg := arg + isIndirect := false + + if arg.pegRule == ruleIndirectionIndicator { + arg = arg.next + isIndirect = true + } + + switch arg.pegRule { + case ruleRegisterOrConstant, ruleLocalLabelRef: + args = append(args, d.contents(fullArg)) + + case ruleMemoryRef: + symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up) + changed = didChange + + if symbol == "OPENSSL_ia32cap_P" && section == "" { + if instructionName != "leaq" { + return nil, fmt.Errorf("non-leaq instruction %q referenced OPENSSL_ia32cap_P directly", instructionName) + } + + if i != 0 || len(argNodes) != 2 || !d.isRIPRelative(memRef) || len(offset) > 0 { + return nil, fmt.Errorf("invalid OPENSSL_ia32cap_P reference in instruction %q", instructionName) + } + + target := argNodes[1] + assertNodeType(target, ruleRegisterOrConstant) + reg := d.contents(target) + + if !strings.HasPrefix(reg, "%r") { + return nil, fmt.Errorf("tried to load OPENSSL_ia32cap_P into %q, which is not a standard register.", reg) + } + + changed = true + + // Flag-altering instructions (i.e. addq) are going to be used so the + // flags need to be preserved. + wrappers = append(wrappers, saveFlags(d.output, false /* Red Zone not yet cleared */)) + + wrappers = append(wrappers, func(k func()) { + d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + reg + "\n") + d.output.WriteString("\taddq\t(" + reg + "), " + reg + "\n") + }) + + break Args + } + + switch section { + case "": + if _, knownSymbol := d.symbols[symbol]; knownSymbol { + symbol = localTargetName(symbol) + changed = true + } + + case "PLT": + if classifyInstruction(instructionName, argNodes) != instrJump { + return nil, fmt.Errorf("Cannot rewrite PLT reference for non-jump instruction %q", instructionName) + } + + if _, knownSymbol := d.symbols[symbol]; knownSymbol { + symbol = localTargetName(symbol) + changed = true + } else if !symbolIsLocal && !isSynthesized(symbol) { + // Unknown symbol via PLT is an + // out-call from the module, e.g. + // memcpy. + d.redirectors[symbol+"@"+section] = redirectorName(symbol) + symbol = redirectorName(symbol) + } + + changed = true + + case "GOTPCREL": + if len(offset) > 0 { + return nil, errors.New("loading from GOT with offset is unsupported") + } + if i != 0 { + return nil, errors.New("GOT access must be source operand") + } + if !d.isRIPRelative(memRef) { + return nil, errors.New("GOT access must be IP-relative") + } + + useGOT := false + if _, knownSymbol := d.symbols[symbol]; knownSymbol { + symbol = localTargetName(symbol) + changed = true + } else if !isSynthesized(symbol) { + useGOT = true + } + + // Reduce the instruction to movq symbol@GOTPCREL, targetReg. + var targetReg string + var redzoneCleared bool + switch classifyInstruction(instructionName, argNodes) { + case instrPush: + wrappers = append(wrappers, push(d.output)) + targetReg = "%rax" + case instrConditionalMove: + wrappers = append(wrappers, undoConditionalMove(d.output, instructionName)) + fallthrough + case instrMove: + assertNodeType(argNodes[1], ruleRegisterOrConstant) + targetReg = d.contents(argNodes[1]) + case instrTransformingMove: + assertNodeType(argNodes[1], ruleRegisterOrConstant) + targetReg = d.contents(argNodes[1]) + wrappers = append(wrappers, finalTransform(d.output, instructionName, targetReg)) + if isValidLEATarget(targetReg) { + return nil, errors.New("Currently transforming moves are assumed to target XMM registers. Otherwise we'll pop %rax before reading it to do the transform.") + } + case instrCombine: + targetReg = d.contents(argNodes[1]) + if !isValidLEATarget(targetReg) { + return nil, fmt.Errorf("cannot handle combining instructions targeting non-general registers") + } + saveRegWrapper, tempReg := saveRegister(d.output, targetReg) + redzoneCleared = true + wrappers = append(wrappers, saveRegWrapper) + + wrappers = append(wrappers, combineOp(d.output, instructionName, tempReg, targetReg)) + targetReg = tempReg + default: + return nil, fmt.Errorf("Cannot rewrite GOTPCREL reference for instruction %q", instructionName) + } + + if !isValidLEATarget(targetReg) { + // Sometimes the compiler will load from the GOT to an + // XMM register, which is not a valid target of an LEA + // instruction. + saveRegWrapper, tempReg := saveRegister(d.output, "") + wrappers = append(wrappers, saveRegWrapper) + isAVX := strings.HasPrefix(instructionName, "v") + wrappers = append(wrappers, moveTo(d.output, targetReg, isAVX, tempReg)) + targetReg = tempReg + if redzoneCleared { + return nil, fmt.Errorf("internal error: Red Zone was already cleared") + } + redzoneCleared = true + } + + if symbol == "OPENSSL_ia32cap_P" { + // Flag-altering instructions (i.e. addq) are going to be used so the + // flags need to be preserved. + wrappers = append(wrappers, saveFlags(d.output, redzoneCleared)) + wrappers = append(wrappers, func(k func()) { + d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + targetReg + "\n") + d.output.WriteString("\taddq\t(" + targetReg + "), " + targetReg + "\n") + }) + } else if useGOT { + wrappers = append(wrappers, d.loadFromGOT(d.output, targetReg, symbol, section, redzoneCleared)) + } else { + wrappers = append(wrappers, func(k func()) { + d.output.WriteString(fmt.Sprintf("\tleaq\t%s(%%rip), %s\n", symbol, targetReg)) + }) + } + changed = true + break Args + + default: + return nil, fmt.Errorf("Unknown section type %q", section) + } + + if !changed && len(section) > 0 { + panic("section was not handled") + } + section = "" + + argStr := "" + if isIndirect { + argStr += "*" + } + argStr += symbol + argStr += offset + + for ; memRef != nil; memRef = memRef.next { + argStr += d.contents(memRef) + } + + args = append(args, argStr) + + default: + panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule])) + } + } + + if changed { + d.writeCommentedNode(statement) + replacement := "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n" + wrappers.do(func() { + d.output.WriteString(replacement) + }) + } else { + d.writeNode(statement) + } + + return statement, nil +} + +func (d *delocation) handleBSS(statement *node32) (*node32, error) { + lastStatement := statement + for statement = statement.next; statement != nil; lastStatement, statement = statement, statement.next { + node := skipWS(statement.up) + if node == nil { + d.writeNode(statement) + continue + } + + switch node.pegRule { + case ruleGlobalDirective, ruleComment, ruleInstruction, ruleLocationDirective: + d.writeNode(statement) + + case ruleDirective: + directive := node.up + assertNodeType(directive, ruleDirectiveName) + directiveName := d.contents(directive) + if directiveName == "text" || directiveName == "section" || directiveName == "data" { + return lastStatement, nil + } + d.writeNode(statement) + + case ruleLabel: + label := node.up + d.writeNode(statement) + + if label.pegRule != ruleLocalSymbol { + symbol := d.contents(label) + localSymbol := localTargetName(symbol) + d.output.WriteString(fmt.Sprintf("\n%s:\n", localSymbol)) + + d.bssAccessorsNeeded[symbol] = localSymbol + } + + case ruleLabelContainingDirective: + var err error + statement, err = d.processLabelContainingDirective(statement, node.up) + if err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unknown BSS statement type %q in %q", rul3s[node.pegRule], d.contents(statement)) + } + } + + return lastStatement, nil +} + +func transform(w stringWriter, inputs []inputFile) error { + // symbols contains all defined symbols. + symbols := make(map[string]struct{}) + // localEntrySymbols contains all symbols with a .localentry directive. + localEntrySymbols := make(map[string]struct{}) + // fileNumbers is the set of IDs seen in .file directives. + fileNumbers := make(map[int]struct{}) + // maxObservedFileNumber contains the largest seen file number in a + // .file directive. Zero is not a valid number. + maxObservedFileNumber := 0 + + for _, input := range inputs { + forEachPath(input.ast.up, func(node *node32) { + symbol := input.contents[node.begin:node.end] + if _, ok := symbols[symbol]; ok { + panic(fmt.Sprintf("Duplicate symbol found: %q in %q", symbol, input.path)) + } + symbols[symbol] = struct{}{} + }, ruleStatement, ruleLabel, ruleSymbolName) + + forEachPath(input.ast.up, func(node *node32) { + node = node.up + assertNodeType(node, ruleLabelContainingDirectiveName) + directive := input.contents[node.begin:node.end] + if directive != ".localentry" { + return + } + // Extract the first argument. + node = skipWS(node.next) + assertNodeType(node, ruleSymbolArgs) + node = node.up + assertNodeType(node, ruleSymbolArg) + symbol := input.contents[node.begin:node.end] + if _, ok := localEntrySymbols[symbol]; ok { + panic(fmt.Sprintf("Duplicate .localentry directive found: %q in %q", symbol, input.path)) + } + localEntrySymbols[symbol] = struct{}{} + }, ruleStatement, ruleLabelContainingDirective) + + forEachPath(input.ast.up, func(node *node32) { + assertNodeType(node, ruleLocationDirective) + directive := input.contents[node.begin:node.end] + if !strings.HasPrefix(directive, ".file") { + return + } + parts := strings.Fields(directive) + if len(parts) == 2 { + // This is a .file directive with just a + // filename. Clang appears to generate just one + // of these at the beginning of the output for + // the compilation unit. Ignore it. + return + } + fileNo, err := strconv.Atoi(parts[1]) + if err != nil { + panic(fmt.Sprintf("Failed to parse file number from .file: %q", directive)) + } + + if _, ok := fileNumbers[fileNo]; ok { + panic(fmt.Sprintf("Duplicate file number %d observed", fileNo)) + } + fileNumbers[fileNo] = struct{}{} + + if fileNo > maxObservedFileNumber { + maxObservedFileNumber = fileNo + } + }, ruleStatement, ruleLocationDirective) + } + + processor := x86_64 + if len(inputs) > 0 { + processor = detectProcessor(inputs[0]) + } + + d := &delocation{ + symbols: symbols, + localEntrySymbols: localEntrySymbols, + processor: processor, + output: w, + redirectors: make(map[string]string), + bssAccessorsNeeded: make(map[string]string), + tocLoaders: make(map[string]struct{}), + gotExternalsNeeded: make(map[string]struct{}), + } + + w.WriteString(".text\n") + w.WriteString(fmt.Sprintf(".file %d \"inserted_by_delocate.c\"\n", maxObservedFileNumber+1)) + w.WriteString(fmt.Sprintf(".loc %d 1 0\n", maxObservedFileNumber+1)) + w.WriteString("BORINGSSL_bcm_text_start:\n") + + for _, input := range inputs { + if err := d.processInput(input); err != nil { + return err + } + } + + w.WriteString(".text\n") + w.WriteString(fmt.Sprintf(".loc %d 2 0\n", maxObservedFileNumber+1)) + w.WriteString("BORINGSSL_bcm_text_end:\n") + + // Emit redirector functions. Each is a single jump instruction. + var redirectorNames []string + for name := range d.redirectors { + redirectorNames = append(redirectorNames, name) + } + sort.Strings(redirectorNames) + + for _, name := range redirectorNames { + redirector := d.redirectors[name] + if d.processor == ppc64le { + w.WriteString(".section \".toc\", \"aw\"\n") + w.WriteString(".Lredirector_toc_" + name + ":\n") + w.WriteString(".quad " + name + "\n") + w.WriteString(".text\n") + w.WriteString(".type " + redirector + ", @function\n") + w.WriteString(redirector + ":\n") + // |name| will clobber r2, so save it. This is matched by a restore in + // redirector calls. + w.WriteString("\tstd 2, 24(1)\n") + // Load and call |name|'s global entry point. + w.WriteString("\taddis 12, 2, .Lredirector_toc_" + name + "@toc@ha\n") + w.WriteString("\tld 12, .Lredirector_toc_" + name + "@toc@l(12)\n") + w.WriteString("\tmtctr 12\n") + w.WriteString("\tbctr\n") + } else { + w.WriteString(".type " + redirector + ", @function\n") + w.WriteString(redirector + ":\n") + w.WriteString("\tjmp\t" + name + "\n") + } + } + + var accessorNames []string + for accessor := range d.bssAccessorsNeeded { + accessorNames = append(accessorNames, accessor) + } + sort.Strings(accessorNames) + + // Emit BSS accessor functions. Each is a single LEA followed by RET. + for _, name := range accessorNames { + funcName := accessorName(name) + w.WriteString(".type " + funcName + ", @function\n") + w.WriteString(funcName + ":\n") + target := d.bssAccessorsNeeded[name] + + if d.processor == ppc64le { + w.WriteString("\taddis 3, 2, " + target + "@toc@ha\n") + w.WriteString("\taddi 3, 3, " + target + "@toc@l\n") + w.WriteString("\tblr\n") + } else { + w.WriteString("\tleaq\t" + target + "(%rip), %rax\n\tret\n") + } + } + + if d.processor == ppc64le { + loadTOCNames := sortedSet(d.tocLoaders) + for _, symbolAndOffset := range loadTOCNames { + parts := strings.SplitN(symbolAndOffset, "\x00", 2) + symbol, offset := parts[0], parts[1] + + funcName := loadTOCFuncName(symbol, offset) + ref := symbol + offset + + w.WriteString(".type " + funcName[2:] + ", @function\n") + w.WriteString(funcName[2:] + ":\n") + w.WriteString(funcName + ":\n") + w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n") + w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n") + w.WriteString("\tblr\n") + } + + w.WriteString(".LBORINGSSL_external_toc:\n") + w.WriteString(".quad .TOC.-.LBORINGSSL_external_toc\n") + } else { + externalNames := sortedSet(d.gotExternalsNeeded) + for _, name := range externalNames { + parts := strings.SplitN(name, "@", 2) + symbol, section := parts[0], parts[1] + w.WriteString(".type " + symbol + "_" + section + "_external, @object\n") + w.WriteString(".size " + symbol + "_" + section + "_external, 8\n") + w.WriteString(symbol + "_" + section + "_external:\n") + // Ideally this would be .quad foo@GOTPCREL, but clang's + // assembler cannot emit a 64-bit GOTPCREL relocation. Instead, + // we manually sign-extend the value, knowing that the GOT is + // always at the end, thus foo@GOTPCREL has a positive value. + w.WriteString("\t.long " + symbol + "@" + section + "\n") + w.WriteString("\t.long 0\n") + } + + w.WriteString(".type OPENSSL_ia32cap_get, @function\n") + w.WriteString("OPENSSL_ia32cap_get:\n") + w.WriteString("\tleaq OPENSSL_ia32cap_P(%rip), %rax\n") + w.WriteString("\tret\n") + + w.WriteString(".extern OPENSSL_ia32cap_P\n") + w.WriteString(".type OPENSSL_ia32cap_addr_delta, @object\n") + w.WriteString(".size OPENSSL_ia32cap_addr_delta, 8\n") + w.WriteString("OPENSSL_ia32cap_addr_delta:\n") + w.WriteString(".quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta\n") + } + + 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 fipscommon.UninitHashValue { + w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n") + } + + return nil +} + +func parseInputs(inputs []inputFile) error { + for i, input := range inputs { + var contents string + + if input.isArchive { + arFile, err := os.Open(input.path) + if err != nil { + return err + } + defer arFile.Close() + + ar, err := fipscommon.ParseAR(arFile) + if err != nil { + return err + } + + if len(ar) != 1 { + return fmt.Errorf("expected one file in archive, but found %d", len(ar)) + } + + for _, c := range ar { + contents = string(c) + } + } else { + inBytes, err := ioutil.ReadFile(input.path) + if err != nil { + return err + } + + contents = string(inBytes) + } + + asm := Asm{Buffer: contents, Pretty: true} + asm.Init() + if err := asm.Parse(); err != nil { + return fmt.Errorf("error while parsing %q: %s", input.path, err) + } + ast := asm.AST() + + inputs[i].contents = contents + inputs[i].ast = ast + } + + return nil +} + +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") + + flag.Parse() + + if len(*outFile) == 0 { + fmt.Fprintf(os.Stderr, "Must give argument to -o.\n") + os.Exit(1) + } + + var inputs []inputFile + if len(*arInput) > 0 { + inputs = append(inputs, inputFile{ + path: *arInput, + index: 0, + isArchive: true, + }) + } + + for i, path := range flag.Args() { + if len(path) == 0 { + continue + } + + inputs = append(inputs, inputFile{ + path: path, + index: i + 1, + }) + } + + if err := parseInputs(inputs); err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + + out, err := os.OpenFile(*outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + panic(err) + } + defer out.Close() + + if err := transform(out, inputs); err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } +} + +func forEachPath(node *node32, cb func(*node32), rules ...pegRule) { + if node == nil { + return + } + + if len(rules) == 0 { + cb(node) + return + } + + rule := rules[0] + childRules := rules[1:] + + for ; node != nil; node = node.next { + if node.pegRule != rule { + continue + } + + if len(childRules) == 0 { + cb(node) + } else { + forEachPath(node.up, cb, childRules...) + } + } +} + +func skipNodes(node *node32, ruleToSkip pegRule) *node32 { + for ; node != nil && node.pegRule == ruleToSkip; node = node.next { + } + return node +} + +func skipWS(node *node32) *node32 { + return skipNodes(node, ruleWS) +} + +func assertNodeType(node *node32, expected pegRule) { + if rule := node.pegRule; rule != expected { + panic(fmt.Sprintf("node was %q, but wanted %q", rul3s[rule], rul3s[expected])) + } +} + +type wrapperFunc func(func()) + +type wrapperStack []wrapperFunc + +func (w *wrapperStack) do(baseCase func()) { + if len(*w) == 0 { + baseCase() + return + } + + wrapper := (*w)[0] + *w = (*w)[1:] + wrapper(func() { w.do(baseCase) }) +} + +// localTargetName returns the name of the local target label for a global +// symbol named name. +func localTargetName(name string) string { + return ".L" + name + "_local_target" +} + +func localEntryName(name string) string { + return ".L" + name + "_local_entry" +} + +func isSynthesized(symbol string) bool { + return strings.HasSuffix(symbol, "_bss_get") || + symbol == "OPENSSL_ia32cap_get" || + strings.HasPrefix(symbol, "BORINGSSL_bcm_text_") +} + +func redirectorName(symbol string) string { + return "bcm_redirector_" + symbol +} + +// sectionType returns the type of a section. I.e. a section called “.text.foo” +// is a “.text” section. +func sectionType(section string) (string, bool) { + if len(section) == 0 || section[0] != '.' { + return "", false + } + + i := strings.Index(section[1:], ".") + if i != -1 { + section = section[:i+1] + } + + if strings.HasPrefix(section, ".debug_") { + return ".debug", true + } + + return section, true +} + +// accessorName returns the name of the accessor function for a BSS symbol +// named name. +func accessorName(name string) string { + return name + "_bss_get" +} + +func (d *delocation) mapLocalSymbol(symbol string) string { + if d.currentInput.index == 0 { + return symbol + } + return symbol + "_BCM_" + strconv.Itoa(d.currentInput.index) +} + +func detectProcessor(input inputFile) processorType { + for statement := input.ast.up; statement != nil; statement = statement.next { + node := skipNodes(statement.up, ruleWS) + if node == nil || node.pegRule != ruleInstruction { + continue + } + + instruction := node.up + instructionName := input.contents[instruction.begin:instruction.end] + + switch instructionName { + case "movq", "call", "leaq": + return x86_64 + case "addis", "addi", "mflr": + return ppc64le + } + } + + panic("processed entire input and didn't recognise any instructions.") +} + +func sortedSet(m map[string]struct{}) []string { + ret := make([]string, 0, len(m)) + for key := range m { + ret = append(ret, key) + } + sort.Strings(ret) + return ret +} diff --git a/src/util/fipstools/delocate/delocate.peg b/src/util/fipstools/delocate/delocate.peg new file mode 100644 index 00000000..3dcead2d --- /dev/null +++ b/src/util/fipstools/delocate/delocate.peg @@ -0,0 +1,80 @@ +# 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. */ + +# This is a rough parser for x86-64 and ppc64le assembly designed to work with +# https://github.com/pointlander/peg. delocate.go has a go:generate line for +# rebuilding delocate.peg.go from this file. + +package main + +type Asm Peg {} + +AsmFile <- Statement* !. +Statement <- WS? (Label / ((GlobalDirective / + LocationDirective / + LabelContainingDirective / + Instruction / + Directive / + Comment / ) WS? ((Comment? '\n') / ';'))) +GlobalDirective <- (".global" / ".globl") WS SymbolName +Directive <- '.' DirectiveName (WS Args)? +DirectiveName <- [[A-Z0-9_]]+ +LocationDirective <- (".file" / ".loc") WS [^#\n]+ +Args <- Arg ((WS? ',' WS?) Arg)* +Arg <- QuotedArg / [[0-9a-z%+\-*_@.]]* +QuotedArg <- '"' QuotedText '"' +QuotedText <- (EscapedChar / [^"])* +LabelContainingDirective <- LabelContainingDirectiveName WS SymbolArgs +LabelContainingDirectiveName <- ".long" / ".set" / ".8byte" / ".4byte" / ".quad" / ".tc" / ".localentry" / ".size" / ".type" +SymbolArgs <- SymbolArg ((WS? ',' WS?) SymbolArg)* +SymbolArg <- Offset / + SymbolType / + (Offset / LocalSymbol / SymbolName / Dot) WS? Operator WS? (Offset / LocalSymbol / SymbolName) / + LocalSymbol TCMarker? / + SymbolName Offset / + SymbolName TCMarker? +SymbolType <- '@function' / '@object' +Dot <- '.' +TCMarker <- '[TC]' +EscapedChar <- '\\' . +WS <- [ \t]+ +Comment <- '#' [^\n]* +Label <- (LocalSymbol / LocalLabel / SymbolName) ':' +SymbolName <- [[A-Z._]][[A-Z.0-9$_]]* +LocalSymbol <- '.L' [[A-Z.0-9$_]]+ +LocalLabel <- [0-9][0-9$]* +LocalLabelRef <- [0-9][0-9$]*[bf] +Instruction <- InstructionName (WS InstructionArg ((WS? ',' WS?) InstructionArg)*)? (WS? '{' InstructionArg '}')* +InstructionName <- [[A-Z]][[A-Z0-9]]* [.+\-]? +InstructionArg <- IndirectionIndicator? (RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / MemoryRef) +TOCRefHigh <- '.TOC.-' ('0b' / ('.L' [a-zA-Z_0-9]+)) "@ha" +TOCRefLow <- '.TOC.-' ('0b' / ('.L' [a-zA-Z_0-9]+)) "@l" +IndirectionIndicator <- '*' +RegisterOrConstant <- (('%'[[A-Z]][[A-Z0-9]]*) / ('$'? ((Offset Offset) / Offset))) ![fb:(+\-] +# Compilers only output a very limited number of expression forms. Rather than +# implement a full expression parser, this enumerate those forms plus a few +# that appear in our hand-written assembly. +MemoryRef <- (SymbolRef BaseIndexScale / + SymbolRef / + Offset* BaseIndexScale / + SegmentRegister Offset BaseIndexScale / + SegmentRegister BaseIndexScale / + SegmentRegister Offset / + BaseIndexScale) +SymbolRef <- (Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)? +BaseIndexScale <- '(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)? )? ')' +Operator <- [+\-] +Offset <- '+'? '-'? (("0b" [01]+) / ("0x" [[0-9A-F]]+) / [0-9]+) +Section <- [[A-Z@]]+ +SegmentRegister <- '%' [c-gs] 's:' diff --git a/src/util/fipstools/delocate/delocate.peg.go b/src/util/fipstools/delocate/delocate.peg.go new file mode 100644 index 00000000..f0ad78f6 --- /dev/null +++ b/src/util/fipstools/delocate/delocate.peg.go @@ -0,0 +1,4017 @@ +package main + +//go:generate peg delocate.peg + +import ( + "fmt" + "math" + "sort" + "strconv" +) + +const endSymbol rune = 1114112 + +/* The rule types inferred from the grammar are below. */ +type pegRule uint8 + +const ( + ruleUnknown pegRule = iota + ruleAsmFile + ruleStatement + ruleGlobalDirective + ruleDirective + ruleDirectiveName + ruleLocationDirective + ruleArgs + ruleArg + ruleQuotedArg + ruleQuotedText + ruleLabelContainingDirective + ruleLabelContainingDirectiveName + ruleSymbolArgs + ruleSymbolArg + ruleSymbolType + ruleDot + ruleTCMarker + ruleEscapedChar + ruleWS + ruleComment + ruleLabel + ruleSymbolName + ruleLocalSymbol + ruleLocalLabel + ruleLocalLabelRef + ruleInstruction + ruleInstructionName + ruleInstructionArg + ruleTOCRefHigh + ruleTOCRefLow + ruleIndirectionIndicator + ruleRegisterOrConstant + ruleMemoryRef + ruleSymbolRef + ruleBaseIndexScale + ruleOperator + ruleOffset + ruleSection + ruleSegmentRegister +) + +var rul3s = [...]string{ + "Unknown", + "AsmFile", + "Statement", + "GlobalDirective", + "Directive", + "DirectiveName", + "LocationDirective", + "Args", + "Arg", + "QuotedArg", + "QuotedText", + "LabelContainingDirective", + "LabelContainingDirectiveName", + "SymbolArgs", + "SymbolArg", + "SymbolType", + "Dot", + "TCMarker", + "EscapedChar", + "WS", + "Comment", + "Label", + "SymbolName", + "LocalSymbol", + "LocalLabel", + "LocalLabelRef", + "Instruction", + "InstructionName", + "InstructionArg", + "TOCRefHigh", + "TOCRefLow", + "IndirectionIndicator", + "RegisterOrConstant", + "MemoryRef", + "SymbolRef", + "BaseIndexScale", + "Operator", + "Offset", + "Section", + "SegmentRegister", +} + +type token32 struct { + pegRule + begin, end uint32 +} + +func (t *token32) String() string { + return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v", rul3s[t.pegRule], t.begin, t.end) +} + +type node32 struct { + token32 + up, next *node32 +} + +func (node *node32) print(pretty bool, buffer string) { + var print func(node *node32, depth int) + print = func(node *node32, depth int) { + for node != nil { + for c := 0; c < depth; c++ { + fmt.Printf(" ") + } + rule := rul3s[node.pegRule] + quote := strconv.Quote(string(([]rune(buffer)[node.begin:node.end]))) + if !pretty { + fmt.Printf("%v %v\n", rule, quote) + } else { + fmt.Printf("\x1B[34m%v\x1B[m %v\n", rule, quote) + } + if node.up != nil { + print(node.up, depth+1) + } + node = node.next + } + } + print(node, 0) +} + +func (node *node32) Print(buffer string) { + node.print(false, buffer) +} + +func (node *node32) PrettyPrint(buffer string) { + node.print(true, buffer) +} + +type tokens32 struct { + tree []token32 +} + +func (t *tokens32) Trim(length uint32) { + t.tree = t.tree[:length] +} + +func (t *tokens32) Print() { + for _, token := range t.tree { + fmt.Println(token.String()) + } +} + +func (t *tokens32) AST() *node32 { + type element struct { + node *node32 + down *element + } + tokens := t.Tokens() + var stack *element + for _, token := range tokens { + if token.begin == token.end { + continue + } + node := &node32{token32: token} + for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { + stack.node.next = node.up + node.up = stack.node + stack = stack.down + } + stack = &element{node: node, down: stack} + } + if stack != nil { + return stack.node + } + return nil +} + +func (t *tokens32) PrintSyntaxTree(buffer string) { + t.AST().Print(buffer) +} + +func (t *tokens32) PrettyPrintSyntaxTree(buffer string) { + t.AST().PrettyPrint(buffer) +} + +func (t *tokens32) Add(rule pegRule, begin, end, index uint32) { + if tree := t.tree; int(index) >= len(tree) { + expanded := make([]token32, 2*len(tree)) + copy(expanded, tree) + t.tree = expanded + } + t.tree[index] = token32{ + pegRule: rule, + begin: begin, + end: end, + } +} + +func (t *tokens32) Tokens() []token32 { + return t.tree +} + +type Asm struct { + Buffer string + buffer []rune + rules [40]func() bool + parse func(rule ...int) error + reset func() + Pretty bool + tokens32 +} + +func (p *Asm) Parse(rule ...int) error { + return p.parse(rule...) +} + +func (p *Asm) Reset() { + p.reset() +} + +type textPosition struct { + line, symbol int +} + +type textPositionMap map[int]textPosition + +func translatePositions(buffer []rune, positions []int) textPositionMap { + length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 + sort.Ints(positions) + +search: + for i, c := range buffer { + if c == '\n' { + line, symbol = line+1, 0 + } else { + symbol++ + } + if i == positions[j] { + translations[positions[j]] = textPosition{line, symbol} + for j++; j < length; j++ { + if i != positions[j] { + continue search + } + } + break search + } + } + + return translations +} + +type parseError struct { + p *Asm + max token32 +} + +func (e *parseError) Error() string { + tokens, error := []token32{e.max}, "\n" + positions, p := make([]int, 2*len(tokens)), 0 + for _, token := range tokens { + positions[p], p = int(token.begin), p+1 + positions[p], p = int(token.end), p+1 + } + translations := translatePositions(e.p.buffer, positions) + format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" + if e.p.Pretty { + format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" + } + for _, token := range tokens { + begin, end := int(token.begin), int(token.end) + error += fmt.Sprintf(format, + rul3s[token.pegRule], + translations[begin].line, translations[begin].symbol, + translations[end].line, translations[end].symbol, + strconv.Quote(string(e.p.buffer[begin:end]))) + } + + return error +} + +func (p *Asm) PrintSyntaxTree() { + if p.Pretty { + p.tokens32.PrettyPrintSyntaxTree(p.Buffer) + } else { + p.tokens32.PrintSyntaxTree(p.Buffer) + } +} + +func (p *Asm) Init() { + var ( + max token32 + position, tokenIndex uint32 + buffer []rune + ) + p.reset = func() { + max = token32{} + position, tokenIndex = 0, 0 + + p.buffer = []rune(p.Buffer) + if len(p.buffer) == 0 || p.buffer[len(p.buffer)-1] != endSymbol { + p.buffer = append(p.buffer, endSymbol) + } + buffer = p.buffer + } + p.reset() + + _rules := p.rules + tree := tokens32{tree: make([]token32, math.MaxInt16)} + p.parse = func(rule ...int) error { + r := 1 + if len(rule) > 0 { + r = rule[0] + } + matches := p.rules[r]() + p.tokens32 = tree + if matches { + p.Trim(tokenIndex) + return nil + } + return &parseError{p, max} + } + + add := func(rule pegRule, begin uint32) { + tree.Add(rule, begin, position, tokenIndex) + tokenIndex++ + if begin != position && position > max.end { + max = token32{rule, begin, position} + } + } + + matchDot := func() bool { + if buffer[position] != endSymbol { + position++ + return true + } + return false + } + + /*matchChar := func(c byte) bool { + if buffer[position] == c { + position++ + return true + } + return false + }*/ + + /*matchRange := func(lower byte, upper byte) bool { + if c := buffer[position]; c >= lower && c <= upper { + position++ + return true + } + return false + }*/ + + _rules = [...]func() bool{ + nil, + /* 0 AsmFile <- <(Statement* !.)> */ + func() bool { + position0, tokenIndex0 := position, tokenIndex + { + position1 := position + l2: + { + position3, tokenIndex3 := position, tokenIndex + if !_rules[ruleStatement]() { + goto l3 + } + goto l2 + l3: + position, tokenIndex = position3, tokenIndex3 + } + { + position4, tokenIndex4 := position, tokenIndex + if !matchDot() { + goto l4 + } + goto l0 + l4: + position, tokenIndex = position4, tokenIndex4 + } + add(ruleAsmFile, position1) + } + return true + l0: + position, tokenIndex = position0, tokenIndex0 + return false + }, + /* 1 Statement <- <(WS? (Label / ((GlobalDirective / LocationDirective / LabelContainingDirective / Instruction / Directive / Comment / ) WS? ((Comment? '\n') / ';'))))> */ + func() bool { + position5, tokenIndex5 := position, tokenIndex + { + position6 := position + { + position7, tokenIndex7 := position, tokenIndex + if !_rules[ruleWS]() { + goto l7 + } + goto l8 + l7: + position, tokenIndex = position7, tokenIndex7 + } + l8: + { + position9, tokenIndex9 := position, tokenIndex + if !_rules[ruleLabel]() { + goto l10 + } + goto l9 + l10: + position, tokenIndex = position9, tokenIndex9 + { + position11, tokenIndex11 := position, tokenIndex + if !_rules[ruleGlobalDirective]() { + goto l12 + } + goto l11 + l12: + position, tokenIndex = position11, tokenIndex11 + if !_rules[ruleLocationDirective]() { + goto l13 + } + goto l11 + l13: + position, tokenIndex = position11, tokenIndex11 + if !_rules[ruleLabelContainingDirective]() { + goto l14 + } + goto l11 + l14: + position, tokenIndex = position11, tokenIndex11 + if !_rules[ruleInstruction]() { + goto l15 + } + goto l11 + l15: + position, tokenIndex = position11, tokenIndex11 + if !_rules[ruleDirective]() { + goto l16 + } + goto l11 + l16: + position, tokenIndex = position11, tokenIndex11 + if !_rules[ruleComment]() { + goto l17 + } + goto l11 + l17: + position, tokenIndex = position11, tokenIndex11 + } + l11: + { + position18, tokenIndex18 := position, tokenIndex + if !_rules[ruleWS]() { + goto l18 + } + goto l19 + l18: + position, tokenIndex = position18, tokenIndex18 + } + l19: + { + position20, tokenIndex20 := position, tokenIndex + { + position22, tokenIndex22 := position, tokenIndex + if !_rules[ruleComment]() { + goto l22 + } + goto l23 + l22: + position, tokenIndex = position22, tokenIndex22 + } + l23: + if buffer[position] != rune('\n') { + goto l21 + } + position++ + goto l20 + l21: + position, tokenIndex = position20, tokenIndex20 + if buffer[position] != rune(';') { + goto l5 + } + position++ + } + l20: + } + l9: + add(ruleStatement, position6) + } + return true + l5: + position, tokenIndex = position5, tokenIndex5 + return false + }, + /* 2 GlobalDirective <- <((('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('a' / 'A') ('l' / 'L')) / ('.' ('g' / 'G') ('l' / 'L') ('o' / 'O') ('b' / 'B') ('l' / 'L'))) WS SymbolName)> */ + func() bool { + position24, tokenIndex24 := position, tokenIndex + { + position25 := position + { + position26, tokenIndex26 := position, tokenIndex + if buffer[position] != rune('.') { + goto l27 + } + position++ + { + position28, tokenIndex28 := position, tokenIndex + if buffer[position] != rune('g') { + goto l29 + } + position++ + goto l28 + l29: + position, tokenIndex = position28, tokenIndex28 + if buffer[position] != rune('G') { + goto l27 + } + position++ + } + l28: + { + position30, tokenIndex30 := position, tokenIndex + if buffer[position] != rune('l') { + goto l31 + } + position++ + goto l30 + l31: + position, tokenIndex = position30, tokenIndex30 + if buffer[position] != rune('L') { + goto l27 + } + position++ + } + l30: + { + position32, tokenIndex32 := position, tokenIndex + if buffer[position] != rune('o') { + goto l33 + } + position++ + goto l32 + l33: + position, tokenIndex = position32, tokenIndex32 + if buffer[position] != rune('O') { + goto l27 + } + position++ + } + l32: + { + position34, tokenIndex34 := position, tokenIndex + if buffer[position] != rune('b') { + goto l35 + } + position++ + goto l34 + l35: + position, tokenIndex = position34, tokenIndex34 + if buffer[position] != rune('B') { + goto l27 + } + position++ + } + l34: + { + position36, tokenIndex36 := position, tokenIndex + if buffer[position] != rune('a') { + goto l37 + } + position++ + goto l36 + l37: + position, tokenIndex = position36, tokenIndex36 + if buffer[position] != rune('A') { + goto l27 + } + position++ + } + l36: + { + position38, tokenIndex38 := position, tokenIndex + if buffer[position] != rune('l') { + goto l39 + } + position++ + goto l38 + l39: + position, tokenIndex = position38, tokenIndex38 + if buffer[position] != rune('L') { + goto l27 + } + position++ + } + l38: + goto l26 + l27: + position, tokenIndex = position26, tokenIndex26 + if buffer[position] != rune('.') { + goto l24 + } + position++ + { + position40, tokenIndex40 := position, tokenIndex + if buffer[position] != rune('g') { + goto l41 + } + position++ + goto l40 + l41: + position, tokenIndex = position40, tokenIndex40 + if buffer[position] != rune('G') { + goto l24 + } + position++ + } + l40: + { + position42, tokenIndex42 := position, tokenIndex + if buffer[position] != rune('l') { + goto l43 + } + position++ + goto l42 + l43: + position, tokenIndex = position42, tokenIndex42 + if buffer[position] != rune('L') { + goto l24 + } + position++ + } + l42: + { + position44, tokenIndex44 := position, tokenIndex + if buffer[position] != rune('o') { + goto l45 + } + position++ + goto l44 + l45: + position, tokenIndex = position44, tokenIndex44 + if buffer[position] != rune('O') { + goto l24 + } + position++ + } + l44: + { + position46, tokenIndex46 := position, tokenIndex + if buffer[position] != rune('b') { + goto l47 + } + position++ + goto l46 + l47: + position, tokenIndex = position46, tokenIndex46 + if buffer[position] != rune('B') { + goto l24 + } + position++ + } + l46: + { + position48, tokenIndex48 := position, tokenIndex + if buffer[position] != rune('l') { + goto l49 + } + position++ + goto l48 + l49: + position, tokenIndex = position48, tokenIndex48 + if buffer[position] != rune('L') { + goto l24 + } + position++ + } + l48: + } + l26: + if !_rules[ruleWS]() { + goto l24 + } + if !_rules[ruleSymbolName]() { + goto l24 + } + add(ruleGlobalDirective, position25) + } + return true + l24: + position, tokenIndex = position24, tokenIndex24 + return false + }, + /* 3 Directive <- <('.' DirectiveName (WS Args)?)> */ + func() bool { + position50, tokenIndex50 := position, tokenIndex + { + position51 := position + if buffer[position] != rune('.') { + goto l50 + } + position++ + if !_rules[ruleDirectiveName]() { + goto l50 + } + { + position52, tokenIndex52 := position, tokenIndex + if !_rules[ruleWS]() { + goto l52 + } + if !_rules[ruleArgs]() { + goto l52 + } + goto l53 + l52: + position, tokenIndex = position52, tokenIndex52 + } + l53: + add(ruleDirective, position51) + } + return true + l50: + position, tokenIndex = position50, tokenIndex50 + return false + }, + /* 4 DirectiveName <- <([a-z] / [A-Z] / ([0-9] / [0-9]) / '_')+> */ + func() bool { + position54, tokenIndex54 := position, tokenIndex + { + position55 := position + { + position58, tokenIndex58 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l59 + } + position++ + goto l58 + l59: + position, tokenIndex = position58, tokenIndex58 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l60 + } + position++ + goto l58 + l60: + position, tokenIndex = position58, tokenIndex58 + { + position62, tokenIndex62 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l63 + } + position++ + goto l62 + l63: + position, tokenIndex = position62, tokenIndex62 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l61 + } + position++ + } + l62: + goto l58 + l61: + position, tokenIndex = position58, tokenIndex58 + if buffer[position] != rune('_') { + goto l54 + } + position++ + } + l58: + l56: + { + position57, tokenIndex57 := position, tokenIndex + { + position64, tokenIndex64 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l65 + } + position++ + goto l64 + l65: + position, tokenIndex = position64, tokenIndex64 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l66 + } + position++ + goto l64 + l66: + position, tokenIndex = position64, tokenIndex64 + { + position68, tokenIndex68 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l69 + } + position++ + goto l68 + l69: + position, tokenIndex = position68, tokenIndex68 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l67 + } + position++ + } + l68: + goto l64 + l67: + position, tokenIndex = position64, tokenIndex64 + if buffer[position] != rune('_') { + goto l57 + } + position++ + } + l64: + goto l56 + l57: + position, tokenIndex = position57, tokenIndex57 + } + add(ruleDirectiveName, position55) + } + return true + l54: + position, tokenIndex = position54, tokenIndex54 + return false + }, + /* 5 LocationDirective <- <((('.' ('f' / 'F') ('i' / 'I') ('l' / 'L') ('e' / 'E')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C'))) WS (!('#' / '\n') .)+)> */ + func() bool { + position70, tokenIndex70 := position, tokenIndex + { + position71 := position + { + position72, tokenIndex72 := position, tokenIndex + if buffer[position] != rune('.') { + goto l73 + } + position++ + { + position74, tokenIndex74 := position, tokenIndex + if buffer[position] != rune('f') { + goto l75 + } + position++ + goto l74 + l75: + position, tokenIndex = position74, tokenIndex74 + if buffer[position] != rune('F') { + goto l73 + } + position++ + } + l74: + { + position76, tokenIndex76 := position, tokenIndex + if buffer[position] != rune('i') { + goto l77 + } + position++ + goto l76 + l77: + position, tokenIndex = position76, tokenIndex76 + if buffer[position] != rune('I') { + goto l73 + } + position++ + } + l76: + { + position78, tokenIndex78 := position, tokenIndex + if buffer[position] != rune('l') { + goto l79 + } + position++ + goto l78 + l79: + position, tokenIndex = position78, tokenIndex78 + if buffer[position] != rune('L') { + goto l73 + } + position++ + } + l78: + { + position80, tokenIndex80 := position, tokenIndex + if buffer[position] != rune('e') { + goto l81 + } + position++ + goto l80 + l81: + position, tokenIndex = position80, tokenIndex80 + if buffer[position] != rune('E') { + goto l73 + } + position++ + } + l80: + goto l72 + l73: + position, tokenIndex = position72, tokenIndex72 + if buffer[position] != rune('.') { + goto l70 + } + position++ + { + position82, tokenIndex82 := position, tokenIndex + if buffer[position] != rune('l') { + goto l83 + } + position++ + goto l82 + l83: + position, tokenIndex = position82, tokenIndex82 + if buffer[position] != rune('L') { + goto l70 + } + position++ + } + l82: + { + position84, tokenIndex84 := position, tokenIndex + if buffer[position] != rune('o') { + goto l85 + } + position++ + goto l84 + l85: + position, tokenIndex = position84, tokenIndex84 + if buffer[position] != rune('O') { + goto l70 + } + position++ + } + l84: + { + position86, tokenIndex86 := position, tokenIndex + if buffer[position] != rune('c') { + goto l87 + } + position++ + goto l86 + l87: + position, tokenIndex = position86, tokenIndex86 + if buffer[position] != rune('C') { + goto l70 + } + position++ + } + l86: + } + l72: + if !_rules[ruleWS]() { + goto l70 + } + { + position90, tokenIndex90 := position, tokenIndex + { + position91, tokenIndex91 := position, tokenIndex + if buffer[position] != rune('#') { + goto l92 + } + position++ + goto l91 + l92: + position, tokenIndex = position91, tokenIndex91 + if buffer[position] != rune('\n') { + goto l90 + } + position++ + } + l91: + goto l70 + l90: + position, tokenIndex = position90, tokenIndex90 + } + if !matchDot() { + goto l70 + } + l88: + { + position89, tokenIndex89 := position, tokenIndex + { + position93, tokenIndex93 := position, tokenIndex + { + position94, tokenIndex94 := position, tokenIndex + if buffer[position] != rune('#') { + goto l95 + } + position++ + goto l94 + l95: + position, tokenIndex = position94, tokenIndex94 + if buffer[position] != rune('\n') { + goto l93 + } + position++ + } + l94: + goto l89 + l93: + position, tokenIndex = position93, tokenIndex93 + } + if !matchDot() { + goto l89 + } + goto l88 + l89: + position, tokenIndex = position89, tokenIndex89 + } + add(ruleLocationDirective, position71) + } + return true + l70: + position, tokenIndex = position70, tokenIndex70 + return false + }, + /* 6 Args <- <(Arg (WS? ',' WS? Arg)*)> */ + func() bool { + position96, tokenIndex96 := position, tokenIndex + { + position97 := position + if !_rules[ruleArg]() { + goto l96 + } + l98: + { + position99, tokenIndex99 := position, tokenIndex + { + position100, tokenIndex100 := position, tokenIndex + if !_rules[ruleWS]() { + goto l100 + } + goto l101 + l100: + position, tokenIndex = position100, tokenIndex100 + } + l101: + if buffer[position] != rune(',') { + goto l99 + } + position++ + { + position102, tokenIndex102 := position, tokenIndex + if !_rules[ruleWS]() { + goto l102 + } + goto l103 + l102: + position, tokenIndex = position102, tokenIndex102 + } + l103: + if !_rules[ruleArg]() { + goto l99 + } + goto l98 + l99: + position, tokenIndex = position99, tokenIndex99 + } + add(ruleArgs, position97) + } + return true + l96: + position, tokenIndex = position96, tokenIndex96 + return false + }, + /* 7 Arg <- <(QuotedArg / ([0-9] / [0-9] / ([a-z] / [A-Z]) / '%' / '+' / '-' / '*' / '_' / '@' / '.')*)> */ + func() bool { + { + position105 := position + { + position106, tokenIndex106 := position, tokenIndex + if !_rules[ruleQuotedArg]() { + goto l107 + } + goto l106 + l107: + position, tokenIndex = position106, tokenIndex106 + l108: + { + position109, tokenIndex109 := position, tokenIndex + { + position110, tokenIndex110 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l111 + } + position++ + goto l110 + l111: + position, tokenIndex = position110, tokenIndex110 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l112 + } + position++ + goto l110 + l112: + position, tokenIndex = position110, tokenIndex110 + { + position114, tokenIndex114 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l115 + } + position++ + goto l114 + l115: + position, tokenIndex = position114, tokenIndex114 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l113 + } + position++ + } + l114: + goto l110 + l113: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('%') { + goto l116 + } + position++ + goto l110 + l116: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('+') { + goto l117 + } + position++ + goto l110 + l117: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('-') { + goto l118 + } + position++ + goto l110 + l118: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('*') { + goto l119 + } + position++ + goto l110 + l119: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('_') { + goto l120 + } + position++ + goto l110 + l120: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('@') { + goto l121 + } + position++ + goto l110 + l121: + position, tokenIndex = position110, tokenIndex110 + if buffer[position] != rune('.') { + goto l109 + } + position++ + } + l110: + goto l108 + l109: + position, tokenIndex = position109, tokenIndex109 + } + } + l106: + add(ruleArg, position105) + } + return true + }, + /* 8 QuotedArg <- <('"' QuotedText '"')> */ + func() bool { + position122, tokenIndex122 := position, tokenIndex + { + position123 := position + if buffer[position] != rune('"') { + goto l122 + } + position++ + if !_rules[ruleQuotedText]() { + goto l122 + } + if buffer[position] != rune('"') { + goto l122 + } + position++ + add(ruleQuotedArg, position123) + } + return true + l122: + position, tokenIndex = position122, tokenIndex122 + return false + }, + /* 9 QuotedText <- <(EscapedChar / (!'"' .))*> */ + func() bool { + { + position125 := position + l126: + { + position127, tokenIndex127 := position, tokenIndex + { + position128, tokenIndex128 := position, tokenIndex + if !_rules[ruleEscapedChar]() { + goto l129 + } + goto l128 + l129: + position, tokenIndex = position128, tokenIndex128 + { + position130, tokenIndex130 := position, tokenIndex + if buffer[position] != rune('"') { + goto l130 + } + position++ + goto l127 + l130: + position, tokenIndex = position130, tokenIndex130 + } + if !matchDot() { + goto l127 + } + } + l128: + goto l126 + l127: + position, tokenIndex = position127, tokenIndex127 + } + add(ruleQuotedText, position125) + } + return true + }, + /* 10 LabelContainingDirective <- <(LabelContainingDirectiveName WS SymbolArgs)> */ + func() bool { + position131, tokenIndex131 := position, tokenIndex + { + position132 := position + if !_rules[ruleLabelContainingDirectiveName]() { + goto l131 + } + if !_rules[ruleWS]() { + goto l131 + } + if !_rules[ruleSymbolArgs]() { + goto l131 + } + add(ruleLabelContainingDirective, position132) + } + return true + l131: + position, tokenIndex = position131, tokenIndex131 + return false + }, + /* 11 LabelContainingDirectiveName <- <(('.' ('l' / 'L') ('o' / 'O') ('n' / 'N') ('g' / 'G')) / ('.' ('s' / 'S') ('e' / 'E') ('t' / 'T')) / ('.' '8' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' '4' ('b' / 'B') ('y' / 'Y') ('t' / 'T') ('e' / 'E')) / ('.' ('q' / 'Q') ('u' / 'U') ('a' / 'A') ('d' / 'D')) / ('.' ('t' / 'T') ('c' / 'C')) / ('.' ('l' / 'L') ('o' / 'O') ('c' / 'C') ('a' / 'A') ('l' / 'L') ('e' / 'E') ('n' / 'N') ('t' / 'T') ('r' / 'R') ('y' / 'Y')) / ('.' ('s' / 'S') ('i' / 'I') ('z' / 'Z') ('e' / 'E')) / ('.' ('t' / 'T') ('y' / 'Y') ('p' / 'P') ('e' / 'E')))> */ + func() bool { + position133, tokenIndex133 := position, tokenIndex + { + position134 := position + { + position135, tokenIndex135 := position, tokenIndex + if buffer[position] != rune('.') { + goto l136 + } + position++ + { + position137, tokenIndex137 := position, tokenIndex + if buffer[position] != rune('l') { + goto l138 + } + position++ + goto l137 + l138: + position, tokenIndex = position137, tokenIndex137 + if buffer[position] != rune('L') { + goto l136 + } + position++ + } + l137: + { + position139, tokenIndex139 := position, tokenIndex + if buffer[position] != rune('o') { + goto l140 + } + position++ + goto l139 + l140: + position, tokenIndex = position139, tokenIndex139 + if buffer[position] != rune('O') { + goto l136 + } + position++ + } + l139: + { + position141, tokenIndex141 := position, tokenIndex + if buffer[position] != rune('n') { + goto l142 + } + position++ + goto l141 + l142: + position, tokenIndex = position141, tokenIndex141 + if buffer[position] != rune('N') { + goto l136 + } + position++ + } + l141: + { + position143, tokenIndex143 := position, tokenIndex + if buffer[position] != rune('g') { + goto l144 + } + position++ + goto l143 + l144: + position, tokenIndex = position143, tokenIndex143 + if buffer[position] != rune('G') { + goto l136 + } + position++ + } + l143: + goto l135 + l136: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l145 + } + position++ + { + position146, tokenIndex146 := position, tokenIndex + if buffer[position] != rune('s') { + goto l147 + } + position++ + goto l146 + l147: + position, tokenIndex = position146, tokenIndex146 + if buffer[position] != rune('S') { + goto l145 + } + position++ + } + l146: + { + position148, tokenIndex148 := position, tokenIndex + if buffer[position] != rune('e') { + goto l149 + } + position++ + goto l148 + l149: + position, tokenIndex = position148, tokenIndex148 + if buffer[position] != rune('E') { + goto l145 + } + position++ + } + l148: + { + position150, tokenIndex150 := position, tokenIndex + if buffer[position] != rune('t') { + goto l151 + } + position++ + goto l150 + l151: + position, tokenIndex = position150, tokenIndex150 + if buffer[position] != rune('T') { + goto l145 + } + position++ + } + l150: + goto l135 + l145: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l152 + } + position++ + if buffer[position] != rune('8') { + goto l152 + } + position++ + { + position153, tokenIndex153 := position, tokenIndex + if buffer[position] != rune('b') { + goto l154 + } + position++ + goto l153 + l154: + position, tokenIndex = position153, tokenIndex153 + if buffer[position] != rune('B') { + goto l152 + } + position++ + } + l153: + { + position155, tokenIndex155 := position, tokenIndex + if buffer[position] != rune('y') { + goto l156 + } + position++ + goto l155 + l156: + position, tokenIndex = position155, tokenIndex155 + if buffer[position] != rune('Y') { + goto l152 + } + position++ + } + l155: + { + position157, tokenIndex157 := position, tokenIndex + if buffer[position] != rune('t') { + goto l158 + } + position++ + goto l157 + l158: + position, tokenIndex = position157, tokenIndex157 + if buffer[position] != rune('T') { + goto l152 + } + position++ + } + l157: + { + position159, tokenIndex159 := position, tokenIndex + if buffer[position] != rune('e') { + goto l160 + } + position++ + goto l159 + l160: + position, tokenIndex = position159, tokenIndex159 + if buffer[position] != rune('E') { + goto l152 + } + position++ + } + l159: + goto l135 + l152: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l161 + } + position++ + if buffer[position] != rune('4') { + goto l161 + } + position++ + { + position162, tokenIndex162 := position, tokenIndex + if buffer[position] != rune('b') { + goto l163 + } + position++ + goto l162 + l163: + position, tokenIndex = position162, tokenIndex162 + if buffer[position] != rune('B') { + goto l161 + } + position++ + } + l162: + { + position164, tokenIndex164 := position, tokenIndex + if buffer[position] != rune('y') { + goto l165 + } + position++ + goto l164 + l165: + position, tokenIndex = position164, tokenIndex164 + if buffer[position] != rune('Y') { + goto l161 + } + position++ + } + l164: + { + position166, tokenIndex166 := position, tokenIndex + if buffer[position] != rune('t') { + goto l167 + } + position++ + goto l166 + l167: + position, tokenIndex = position166, tokenIndex166 + if buffer[position] != rune('T') { + goto l161 + } + position++ + } + l166: + { + position168, tokenIndex168 := position, tokenIndex + if buffer[position] != rune('e') { + goto l169 + } + position++ + goto l168 + l169: + position, tokenIndex = position168, tokenIndex168 + if buffer[position] != rune('E') { + goto l161 + } + position++ + } + l168: + goto l135 + l161: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l170 + } + position++ + { + position171, tokenIndex171 := position, tokenIndex + if buffer[position] != rune('q') { + goto l172 + } + position++ + goto l171 + l172: + position, tokenIndex = position171, tokenIndex171 + if buffer[position] != rune('Q') { + goto l170 + } + position++ + } + l171: + { + position173, tokenIndex173 := position, tokenIndex + if buffer[position] != rune('u') { + goto l174 + } + position++ + goto l173 + l174: + position, tokenIndex = position173, tokenIndex173 + if buffer[position] != rune('U') { + goto l170 + } + position++ + } + l173: + { + position175, tokenIndex175 := position, tokenIndex + if buffer[position] != rune('a') { + goto l176 + } + position++ + goto l175 + l176: + position, tokenIndex = position175, tokenIndex175 + if buffer[position] != rune('A') { + goto l170 + } + position++ + } + l175: + { + position177, tokenIndex177 := position, tokenIndex + if buffer[position] != rune('d') { + goto l178 + } + position++ + goto l177 + l178: + position, tokenIndex = position177, tokenIndex177 + if buffer[position] != rune('D') { + goto l170 + } + position++ + } + l177: + goto l135 + l170: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l179 + } + position++ + { + position180, tokenIndex180 := position, tokenIndex + if buffer[position] != rune('t') { + goto l181 + } + position++ + goto l180 + l181: + position, tokenIndex = position180, tokenIndex180 + if buffer[position] != rune('T') { + goto l179 + } + position++ + } + l180: + { + position182, tokenIndex182 := position, tokenIndex + if buffer[position] != rune('c') { + goto l183 + } + position++ + goto l182 + l183: + position, tokenIndex = position182, tokenIndex182 + if buffer[position] != rune('C') { + goto l179 + } + position++ + } + l182: + goto l135 + l179: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l184 + } + position++ + { + position185, tokenIndex185 := position, tokenIndex + if buffer[position] != rune('l') { + goto l186 + } + position++ + goto l185 + l186: + position, tokenIndex = position185, tokenIndex185 + if buffer[position] != rune('L') { + goto l184 + } + position++ + } + l185: + { + position187, tokenIndex187 := position, tokenIndex + if buffer[position] != rune('o') { + goto l188 + } + position++ + goto l187 + l188: + position, tokenIndex = position187, tokenIndex187 + if buffer[position] != rune('O') { + goto l184 + } + position++ + } + l187: + { + position189, tokenIndex189 := position, tokenIndex + if buffer[position] != rune('c') { + goto l190 + } + position++ + goto l189 + l190: + position, tokenIndex = position189, tokenIndex189 + if buffer[position] != rune('C') { + goto l184 + } + position++ + } + l189: + { + position191, tokenIndex191 := position, tokenIndex + if buffer[position] != rune('a') { + goto l192 + } + position++ + goto l191 + l192: + position, tokenIndex = position191, tokenIndex191 + if buffer[position] != rune('A') { + goto l184 + } + position++ + } + l191: + { + position193, tokenIndex193 := position, tokenIndex + if buffer[position] != rune('l') { + goto l194 + } + position++ + goto l193 + l194: + position, tokenIndex = position193, tokenIndex193 + if buffer[position] != rune('L') { + goto l184 + } + position++ + } + l193: + { + position195, tokenIndex195 := position, tokenIndex + if buffer[position] != rune('e') { + goto l196 + } + position++ + goto l195 + l196: + position, tokenIndex = position195, tokenIndex195 + if buffer[position] != rune('E') { + goto l184 + } + position++ + } + l195: + { + position197, tokenIndex197 := position, tokenIndex + if buffer[position] != rune('n') { + goto l198 + } + position++ + goto l197 + l198: + position, tokenIndex = position197, tokenIndex197 + if buffer[position] != rune('N') { + goto l184 + } + position++ + } + l197: + { + position199, tokenIndex199 := position, tokenIndex + if buffer[position] != rune('t') { + goto l200 + } + position++ + goto l199 + l200: + position, tokenIndex = position199, tokenIndex199 + if buffer[position] != rune('T') { + goto l184 + } + position++ + } + l199: + { + position201, tokenIndex201 := position, tokenIndex + if buffer[position] != rune('r') { + goto l202 + } + position++ + goto l201 + l202: + position, tokenIndex = position201, tokenIndex201 + if buffer[position] != rune('R') { + goto l184 + } + position++ + } + l201: + { + position203, tokenIndex203 := position, tokenIndex + if buffer[position] != rune('y') { + goto l204 + } + position++ + goto l203 + l204: + position, tokenIndex = position203, tokenIndex203 + if buffer[position] != rune('Y') { + goto l184 + } + position++ + } + l203: + goto l135 + l184: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l205 + } + position++ + { + position206, tokenIndex206 := position, tokenIndex + if buffer[position] != rune('s') { + goto l207 + } + position++ + goto l206 + l207: + position, tokenIndex = position206, tokenIndex206 + if buffer[position] != rune('S') { + goto l205 + } + position++ + } + l206: + { + position208, tokenIndex208 := position, tokenIndex + if buffer[position] != rune('i') { + goto l209 + } + position++ + goto l208 + l209: + position, tokenIndex = position208, tokenIndex208 + if buffer[position] != rune('I') { + goto l205 + } + position++ + } + l208: + { + position210, tokenIndex210 := position, tokenIndex + if buffer[position] != rune('z') { + goto l211 + } + position++ + goto l210 + l211: + position, tokenIndex = position210, tokenIndex210 + if buffer[position] != rune('Z') { + goto l205 + } + position++ + } + l210: + { + position212, tokenIndex212 := position, tokenIndex + if buffer[position] != rune('e') { + goto l213 + } + position++ + goto l212 + l213: + position, tokenIndex = position212, tokenIndex212 + if buffer[position] != rune('E') { + goto l205 + } + position++ + } + l212: + goto l135 + l205: + position, tokenIndex = position135, tokenIndex135 + if buffer[position] != rune('.') { + goto l133 + } + position++ + { + position214, tokenIndex214 := position, tokenIndex + if buffer[position] != rune('t') { + goto l215 + } + position++ + goto l214 + l215: + position, tokenIndex = position214, tokenIndex214 + if buffer[position] != rune('T') { + goto l133 + } + position++ + } + l214: + { + position216, tokenIndex216 := position, tokenIndex + if buffer[position] != rune('y') { + goto l217 + } + position++ + goto l216 + l217: + position, tokenIndex = position216, tokenIndex216 + if buffer[position] != rune('Y') { + goto l133 + } + position++ + } + l216: + { + position218, tokenIndex218 := position, tokenIndex + if buffer[position] != rune('p') { + goto l219 + } + position++ + goto l218 + l219: + position, tokenIndex = position218, tokenIndex218 + if buffer[position] != rune('P') { + goto l133 + } + position++ + } + l218: + { + position220, tokenIndex220 := position, tokenIndex + if buffer[position] != rune('e') { + goto l221 + } + position++ + goto l220 + l221: + position, tokenIndex = position220, tokenIndex220 + if buffer[position] != rune('E') { + goto l133 + } + position++ + } + l220: + } + l135: + add(ruleLabelContainingDirectiveName, position134) + } + return true + l133: + position, tokenIndex = position133, tokenIndex133 + return false + }, + /* 12 SymbolArgs <- <(SymbolArg (WS? ',' WS? SymbolArg)*)> */ + func() bool { + position222, tokenIndex222 := position, tokenIndex + { + position223 := position + if !_rules[ruleSymbolArg]() { + goto l222 + } + l224: + { + position225, tokenIndex225 := position, tokenIndex + { + position226, tokenIndex226 := position, tokenIndex + if !_rules[ruleWS]() { + goto l226 + } + goto l227 + l226: + position, tokenIndex = position226, tokenIndex226 + } + l227: + if buffer[position] != rune(',') { + goto l225 + } + position++ + { + position228, tokenIndex228 := position, tokenIndex + if !_rules[ruleWS]() { + goto l228 + } + goto l229 + l228: + position, tokenIndex = position228, tokenIndex228 + } + l229: + if !_rules[ruleSymbolArg]() { + goto l225 + } + goto l224 + l225: + position, tokenIndex = position225, tokenIndex225 + } + add(ruleSymbolArgs, position223) + } + return true + l222: + position, tokenIndex = position222, tokenIndex222 + return false + }, + /* 13 SymbolArg <- <(Offset / SymbolType / ((Offset / LocalSymbol / SymbolName / Dot) WS? Operator WS? (Offset / LocalSymbol / SymbolName)) / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?))> */ + func() bool { + position230, tokenIndex230 := position, tokenIndex + { + position231 := position + { + position232, tokenIndex232 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l233 + } + goto l232 + l233: + position, tokenIndex = position232, tokenIndex232 + if !_rules[ruleSymbolType]() { + goto l234 + } + goto l232 + l234: + position, tokenIndex = position232, tokenIndex232 + { + position236, tokenIndex236 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l237 + } + goto l236 + l237: + position, tokenIndex = position236, tokenIndex236 + if !_rules[ruleLocalSymbol]() { + goto l238 + } + goto l236 + l238: + position, tokenIndex = position236, tokenIndex236 + if !_rules[ruleSymbolName]() { + goto l239 + } + goto l236 + l239: + position, tokenIndex = position236, tokenIndex236 + if !_rules[ruleDot]() { + goto l235 + } + } + l236: + { + position240, tokenIndex240 := position, tokenIndex + if !_rules[ruleWS]() { + goto l240 + } + goto l241 + l240: + position, tokenIndex = position240, tokenIndex240 + } + l241: + if !_rules[ruleOperator]() { + goto l235 + } + { + position242, tokenIndex242 := position, tokenIndex + if !_rules[ruleWS]() { + goto l242 + } + goto l243 + l242: + position, tokenIndex = position242, tokenIndex242 + } + l243: + { + position244, tokenIndex244 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l245 + } + goto l244 + l245: + position, tokenIndex = position244, tokenIndex244 + if !_rules[ruleLocalSymbol]() { + goto l246 + } + goto l244 + l246: + position, tokenIndex = position244, tokenIndex244 + if !_rules[ruleSymbolName]() { + goto l235 + } + } + l244: + goto l232 + l235: + position, tokenIndex = position232, tokenIndex232 + if !_rules[ruleLocalSymbol]() { + goto l247 + } + { + position248, tokenIndex248 := position, tokenIndex + if !_rules[ruleTCMarker]() { + goto l248 + } + goto l249 + l248: + position, tokenIndex = position248, tokenIndex248 + } + l249: + goto l232 + l247: + position, tokenIndex = position232, tokenIndex232 + if !_rules[ruleSymbolName]() { + goto l250 + } + if !_rules[ruleOffset]() { + goto l250 + } + goto l232 + l250: + position, tokenIndex = position232, tokenIndex232 + if !_rules[ruleSymbolName]() { + goto l230 + } + { + position251, tokenIndex251 := position, tokenIndex + if !_rules[ruleTCMarker]() { + goto l251 + } + goto l252 + l251: + position, tokenIndex = position251, tokenIndex251 + } + l252: + } + l232: + add(ruleSymbolArg, position231) + } + return true + l230: + position, tokenIndex = position230, tokenIndex230 + return false + }, + /* 14 SymbolType <- <(('@' 'f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('@' 'o' 'b' 'j' 'e' 'c' 't'))> */ + func() bool { + position253, tokenIndex253 := position, tokenIndex + { + position254 := position + { + position255, tokenIndex255 := position, tokenIndex + if buffer[position] != rune('@') { + goto l256 + } + position++ + if buffer[position] != rune('f') { + goto l256 + } + position++ + if buffer[position] != rune('u') { + goto l256 + } + position++ + if buffer[position] != rune('n') { + goto l256 + } + position++ + if buffer[position] != rune('c') { + goto l256 + } + position++ + if buffer[position] != rune('t') { + goto l256 + } + position++ + if buffer[position] != rune('i') { + goto l256 + } + position++ + if buffer[position] != rune('o') { + goto l256 + } + position++ + if buffer[position] != rune('n') { + goto l256 + } + position++ + goto l255 + l256: + position, tokenIndex = position255, tokenIndex255 + if buffer[position] != rune('@') { + goto l253 + } + position++ + if buffer[position] != rune('o') { + goto l253 + } + position++ + if buffer[position] != rune('b') { + goto l253 + } + position++ + if buffer[position] != rune('j') { + goto l253 + } + position++ + if buffer[position] != rune('e') { + goto l253 + } + position++ + if buffer[position] != rune('c') { + goto l253 + } + position++ + if buffer[position] != rune('t') { + goto l253 + } + position++ + } + l255: + add(ruleSymbolType, position254) + } + return true + l253: + position, tokenIndex = position253, tokenIndex253 + return false + }, + /* 15 Dot <- <'.'> */ + func() bool { + position257, tokenIndex257 := position, tokenIndex + { + position258 := position + if buffer[position] != rune('.') { + goto l257 + } + position++ + add(ruleDot, position258) + } + return true + l257: + position, tokenIndex = position257, tokenIndex257 + return false + }, + /* 16 TCMarker <- <('[' 'T' 'C' ']')> */ + func() bool { + position259, tokenIndex259 := position, tokenIndex + { + position260 := position + if buffer[position] != rune('[') { + goto l259 + } + position++ + if buffer[position] != rune('T') { + goto l259 + } + position++ + if buffer[position] != rune('C') { + goto l259 + } + position++ + if buffer[position] != rune(']') { + goto l259 + } + position++ + add(ruleTCMarker, position260) + } + return true + l259: + position, tokenIndex = position259, tokenIndex259 + return false + }, + /* 17 EscapedChar <- <('\\' .)> */ + func() bool { + position261, tokenIndex261 := position, tokenIndex + { + position262 := position + if buffer[position] != rune('\\') { + goto l261 + } + position++ + if !matchDot() { + goto l261 + } + add(ruleEscapedChar, position262) + } + return true + l261: + position, tokenIndex = position261, tokenIndex261 + return false + }, + /* 18 WS <- <(' ' / '\t')+> */ + func() bool { + position263, tokenIndex263 := position, tokenIndex + { + position264 := position + { + position267, tokenIndex267 := position, tokenIndex + if buffer[position] != rune(' ') { + goto l268 + } + position++ + goto l267 + l268: + position, tokenIndex = position267, tokenIndex267 + if buffer[position] != rune('\t') { + goto l263 + } + position++ + } + l267: + l265: + { + position266, tokenIndex266 := position, tokenIndex + { + position269, tokenIndex269 := position, tokenIndex + if buffer[position] != rune(' ') { + goto l270 + } + position++ + goto l269 + l270: + position, tokenIndex = position269, tokenIndex269 + if buffer[position] != rune('\t') { + goto l266 + } + position++ + } + l269: + goto l265 + l266: + position, tokenIndex = position266, tokenIndex266 + } + add(ruleWS, position264) + } + return true + l263: + position, tokenIndex = position263, tokenIndex263 + return false + }, + /* 19 Comment <- <('#' (!'\n' .)*)> */ + func() bool { + position271, tokenIndex271 := position, tokenIndex + { + position272 := position + if buffer[position] != rune('#') { + goto l271 + } + position++ + l273: + { + position274, tokenIndex274 := position, tokenIndex + { + position275, tokenIndex275 := position, tokenIndex + if buffer[position] != rune('\n') { + goto l275 + } + position++ + goto l274 + l275: + position, tokenIndex = position275, tokenIndex275 + } + if !matchDot() { + goto l274 + } + goto l273 + l274: + position, tokenIndex = position274, tokenIndex274 + } + add(ruleComment, position272) + } + return true + l271: + position, tokenIndex = position271, tokenIndex271 + return false + }, + /* 20 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */ + func() bool { + position276, tokenIndex276 := position, tokenIndex + { + position277 := position + { + position278, tokenIndex278 := position, tokenIndex + if !_rules[ruleLocalSymbol]() { + goto l279 + } + goto l278 + l279: + position, tokenIndex = position278, tokenIndex278 + if !_rules[ruleLocalLabel]() { + goto l280 + } + goto l278 + l280: + position, tokenIndex = position278, tokenIndex278 + if !_rules[ruleSymbolName]() { + goto l276 + } + } + l278: + if buffer[position] != rune(':') { + goto l276 + } + position++ + add(ruleLabel, position277) + } + return true + l276: + position, tokenIndex = position276, tokenIndex276 + return false + }, + /* 21 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */ + func() bool { + position281, tokenIndex281 := position, tokenIndex + { + position282 := position + { + position283, tokenIndex283 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l284 + } + position++ + goto l283 + l284: + position, tokenIndex = position283, tokenIndex283 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l285 + } + position++ + goto l283 + l285: + position, tokenIndex = position283, tokenIndex283 + if buffer[position] != rune('.') { + goto l286 + } + position++ + goto l283 + l286: + position, tokenIndex = position283, tokenIndex283 + if buffer[position] != rune('_') { + goto l281 + } + position++ + } + l283: + l287: + { + position288, tokenIndex288 := position, tokenIndex + { + position289, tokenIndex289 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l290 + } + position++ + goto l289 + l290: + position, tokenIndex = position289, tokenIndex289 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l291 + } + position++ + goto l289 + l291: + position, tokenIndex = position289, tokenIndex289 + if buffer[position] != rune('.') { + goto l292 + } + position++ + goto l289 + l292: + position, tokenIndex = position289, tokenIndex289 + { + position294, tokenIndex294 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l295 + } + position++ + goto l294 + l295: + position, tokenIndex = position294, tokenIndex294 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l293 + } + position++ + } + l294: + goto l289 + l293: + position, tokenIndex = position289, tokenIndex289 + if buffer[position] != rune('$') { + goto l296 + } + position++ + goto l289 + l296: + position, tokenIndex = position289, tokenIndex289 + if buffer[position] != rune('_') { + goto l288 + } + position++ + } + l289: + goto l287 + l288: + position, tokenIndex = position288, tokenIndex288 + } + add(ruleSymbolName, position282) + } + return true + l281: + position, tokenIndex = position281, tokenIndex281 + return false + }, + /* 22 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */ + func() bool { + position297, tokenIndex297 := position, tokenIndex + { + position298 := position + if buffer[position] != rune('.') { + goto l297 + } + position++ + if buffer[position] != rune('L') { + goto l297 + } + position++ + { + position301, tokenIndex301 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l302 + } + position++ + goto l301 + l302: + position, tokenIndex = position301, tokenIndex301 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l303 + } + position++ + goto l301 + l303: + position, tokenIndex = position301, tokenIndex301 + if buffer[position] != rune('.') { + goto l304 + } + position++ + goto l301 + l304: + position, tokenIndex = position301, tokenIndex301 + { + position306, tokenIndex306 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l307 + } + position++ + goto l306 + l307: + position, tokenIndex = position306, tokenIndex306 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l305 + } + position++ + } + l306: + goto l301 + l305: + position, tokenIndex = position301, tokenIndex301 + if buffer[position] != rune('$') { + goto l308 + } + position++ + goto l301 + l308: + position, tokenIndex = position301, tokenIndex301 + if buffer[position] != rune('_') { + goto l297 + } + position++ + } + l301: + l299: + { + position300, tokenIndex300 := position, tokenIndex + { + position309, tokenIndex309 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l310 + } + position++ + goto l309 + l310: + position, tokenIndex = position309, tokenIndex309 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l311 + } + position++ + goto l309 + l311: + position, tokenIndex = position309, tokenIndex309 + if buffer[position] != rune('.') { + goto l312 + } + position++ + goto l309 + l312: + position, tokenIndex = position309, tokenIndex309 + { + position314, tokenIndex314 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l315 + } + position++ + goto l314 + l315: + position, tokenIndex = position314, tokenIndex314 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l313 + } + position++ + } + l314: + goto l309 + l313: + position, tokenIndex = position309, tokenIndex309 + if buffer[position] != rune('$') { + goto l316 + } + position++ + goto l309 + l316: + position, tokenIndex = position309, tokenIndex309 + if buffer[position] != rune('_') { + goto l300 + } + position++ + } + l309: + goto l299 + l300: + position, tokenIndex = position300, tokenIndex300 + } + add(ruleLocalSymbol, position298) + } + return true + l297: + position, tokenIndex = position297, tokenIndex297 + return false + }, + /* 23 LocalLabel <- <([0-9] ([0-9] / '$')*)> */ + func() bool { + position317, tokenIndex317 := position, tokenIndex + { + position318 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l317 + } + position++ + l319: + { + position320, tokenIndex320 := position, tokenIndex + { + position321, tokenIndex321 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l322 + } + position++ + goto l321 + l322: + position, tokenIndex = position321, tokenIndex321 + if buffer[position] != rune('$') { + goto l320 + } + position++ + } + l321: + goto l319 + l320: + position, tokenIndex = position320, tokenIndex320 + } + add(ruleLocalLabel, position318) + } + return true + l317: + position, tokenIndex = position317, tokenIndex317 + return false + }, + /* 24 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */ + func() bool { + position323, tokenIndex323 := position, tokenIndex + { + position324 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l323 + } + position++ + l325: + { + position326, tokenIndex326 := position, tokenIndex + { + position327, tokenIndex327 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l328 + } + position++ + goto l327 + l328: + position, tokenIndex = position327, tokenIndex327 + if buffer[position] != rune('$') { + goto l326 + } + position++ + } + l327: + goto l325 + l326: + position, tokenIndex = position326, tokenIndex326 + } + { + position329, tokenIndex329 := position, tokenIndex + if buffer[position] != rune('b') { + goto l330 + } + position++ + goto l329 + l330: + position, tokenIndex = position329, tokenIndex329 + if buffer[position] != rune('f') { + goto l323 + } + position++ + } + l329: + add(ruleLocalLabelRef, position324) + } + return true + l323: + position, tokenIndex = position323, tokenIndex323 + return false + }, + /* 25 Instruction <- <(InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)? (WS? '{' InstructionArg '}')*)> */ + func() bool { + position331, tokenIndex331 := position, tokenIndex + { + position332 := position + if !_rules[ruleInstructionName]() { + goto l331 + } + { + position333, tokenIndex333 := position, tokenIndex + if !_rules[ruleWS]() { + goto l333 + } + if !_rules[ruleInstructionArg]() { + goto l333 + } + l335: + { + position336, tokenIndex336 := position, tokenIndex + { + position337, tokenIndex337 := position, tokenIndex + if !_rules[ruleWS]() { + goto l337 + } + goto l338 + l337: + position, tokenIndex = position337, tokenIndex337 + } + l338: + if buffer[position] != rune(',') { + goto l336 + } + position++ + { + position339, tokenIndex339 := position, tokenIndex + if !_rules[ruleWS]() { + goto l339 + } + goto l340 + l339: + position, tokenIndex = position339, tokenIndex339 + } + l340: + if !_rules[ruleInstructionArg]() { + goto l336 + } + goto l335 + l336: + position, tokenIndex = position336, tokenIndex336 + } + goto l334 + l333: + position, tokenIndex = position333, tokenIndex333 + } + l334: + l341: + { + position342, tokenIndex342 := position, tokenIndex + { + position343, tokenIndex343 := position, tokenIndex + if !_rules[ruleWS]() { + goto l343 + } + goto l344 + l343: + position, tokenIndex = position343, tokenIndex343 + } + l344: + if buffer[position] != rune('{') { + goto l342 + } + position++ + if !_rules[ruleInstructionArg]() { + goto l342 + } + if buffer[position] != rune('}') { + goto l342 + } + position++ + goto l341 + l342: + position, tokenIndex = position342, tokenIndex342 + } + add(ruleInstruction, position332) + } + return true + l331: + position, tokenIndex = position331, tokenIndex331 + return false + }, + /* 26 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */ + func() bool { + position345, tokenIndex345 := position, tokenIndex + { + position346 := position + { + position347, tokenIndex347 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l348 + } + position++ + goto l347 + l348: + position, tokenIndex = position347, tokenIndex347 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l345 + } + position++ + } + l347: + l349: + { + position350, tokenIndex350 := position, tokenIndex + { + position351, tokenIndex351 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l352 + } + position++ + goto l351 + l352: + position, tokenIndex = position351, tokenIndex351 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l353 + } + position++ + goto l351 + l353: + position, tokenIndex = position351, tokenIndex351 + { + position354, tokenIndex354 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l355 + } + position++ + goto l354 + l355: + position, tokenIndex = position354, tokenIndex354 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l350 + } + position++ + } + l354: + } + l351: + goto l349 + l350: + position, tokenIndex = position350, tokenIndex350 + } + { + position356, tokenIndex356 := position, tokenIndex + { + position358, tokenIndex358 := position, tokenIndex + if buffer[position] != rune('.') { + goto l359 + } + position++ + goto l358 + l359: + position, tokenIndex = position358, tokenIndex358 + if buffer[position] != rune('+') { + goto l360 + } + position++ + goto l358 + l360: + position, tokenIndex = position358, tokenIndex358 + if buffer[position] != rune('-') { + goto l356 + } + position++ + } + l358: + goto l357 + l356: + position, tokenIndex = position356, tokenIndex356 + } + l357: + add(ruleInstructionName, position346) + } + return true + l345: + position, tokenIndex = position345, tokenIndex345 + return false + }, + /* 27 InstructionArg <- <(IndirectionIndicator? (RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / MemoryRef))> */ + func() bool { + position361, tokenIndex361 := position, tokenIndex + { + position362 := position + { + position363, tokenIndex363 := position, tokenIndex + if !_rules[ruleIndirectionIndicator]() { + goto l363 + } + goto l364 + l363: + position, tokenIndex = position363, tokenIndex363 + } + l364: + { + position365, tokenIndex365 := position, tokenIndex + if !_rules[ruleRegisterOrConstant]() { + goto l366 + } + goto l365 + l366: + position, tokenIndex = position365, tokenIndex365 + if !_rules[ruleLocalLabelRef]() { + goto l367 + } + goto l365 + l367: + position, tokenIndex = position365, tokenIndex365 + if !_rules[ruleTOCRefHigh]() { + goto l368 + } + goto l365 + l368: + position, tokenIndex = position365, tokenIndex365 + if !_rules[ruleTOCRefLow]() { + goto l369 + } + goto l365 + l369: + position, tokenIndex = position365, tokenIndex365 + if !_rules[ruleMemoryRef]() { + goto l361 + } + } + l365: + add(ruleInstructionArg, position362) + } + return true + l361: + position, tokenIndex = position361, tokenIndex361 + return false + }, + /* 28 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ + func() bool { + position370, tokenIndex370 := position, tokenIndex + { + position371 := position + if buffer[position] != rune('.') { + goto l370 + } + position++ + if buffer[position] != rune('T') { + goto l370 + } + position++ + if buffer[position] != rune('O') { + goto l370 + } + position++ + if buffer[position] != rune('C') { + goto l370 + } + position++ + if buffer[position] != rune('.') { + goto l370 + } + position++ + if buffer[position] != rune('-') { + goto l370 + } + position++ + { + position372, tokenIndex372 := position, tokenIndex + if buffer[position] != rune('0') { + goto l373 + } + position++ + if buffer[position] != rune('b') { + goto l373 + } + position++ + goto l372 + l373: + position, tokenIndex = position372, tokenIndex372 + if buffer[position] != rune('.') { + goto l370 + } + position++ + if buffer[position] != rune('L') { + goto l370 + } + position++ + { + position376, tokenIndex376 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l377 + } + position++ + goto l376 + l377: + position, tokenIndex = position376, tokenIndex376 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l378 + } + position++ + goto l376 + l378: + position, tokenIndex = position376, tokenIndex376 + if buffer[position] != rune('_') { + goto l379 + } + position++ + goto l376 + l379: + position, tokenIndex = position376, tokenIndex376 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l370 + } + position++ + } + l376: + l374: + { + position375, tokenIndex375 := position, tokenIndex + { + position380, tokenIndex380 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l381 + } + position++ + goto l380 + l381: + position, tokenIndex = position380, tokenIndex380 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l382 + } + position++ + goto l380 + l382: + position, tokenIndex = position380, tokenIndex380 + if buffer[position] != rune('_') { + goto l383 + } + position++ + goto l380 + l383: + position, tokenIndex = position380, tokenIndex380 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l375 + } + position++ + } + l380: + goto l374 + l375: + position, tokenIndex = position375, tokenIndex375 + } + } + l372: + if buffer[position] != rune('@') { + goto l370 + } + position++ + { + position384, tokenIndex384 := position, tokenIndex + if buffer[position] != rune('h') { + goto l385 + } + position++ + goto l384 + l385: + position, tokenIndex = position384, tokenIndex384 + if buffer[position] != rune('H') { + goto l370 + } + position++ + } + l384: + { + position386, tokenIndex386 := position, tokenIndex + if buffer[position] != rune('a') { + goto l387 + } + position++ + goto l386 + l387: + position, tokenIndex = position386, tokenIndex386 + if buffer[position] != rune('A') { + goto l370 + } + position++ + } + l386: + add(ruleTOCRefHigh, position371) + } + return true + l370: + position, tokenIndex = position370, tokenIndex370 + return false + }, + /* 29 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ + func() bool { + position388, tokenIndex388 := position, tokenIndex + { + position389 := position + if buffer[position] != rune('.') { + goto l388 + } + position++ + if buffer[position] != rune('T') { + goto l388 + } + position++ + if buffer[position] != rune('O') { + goto l388 + } + position++ + if buffer[position] != rune('C') { + goto l388 + } + position++ + if buffer[position] != rune('.') { + goto l388 + } + position++ + if buffer[position] != rune('-') { + goto l388 + } + position++ + { + position390, tokenIndex390 := position, tokenIndex + if buffer[position] != rune('0') { + goto l391 + } + position++ + if buffer[position] != rune('b') { + goto l391 + } + position++ + goto l390 + l391: + position, tokenIndex = position390, tokenIndex390 + if buffer[position] != rune('.') { + goto l388 + } + position++ + if buffer[position] != rune('L') { + goto l388 + } + position++ + { + position394, tokenIndex394 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l395 + } + position++ + goto l394 + l395: + position, tokenIndex = position394, tokenIndex394 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l396 + } + position++ + goto l394 + l396: + position, tokenIndex = position394, tokenIndex394 + if buffer[position] != rune('_') { + goto l397 + } + position++ + goto l394 + l397: + position, tokenIndex = position394, tokenIndex394 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l388 + } + position++ + } + l394: + l392: + { + position393, tokenIndex393 := position, tokenIndex + { + position398, tokenIndex398 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l399 + } + position++ + goto l398 + l399: + position, tokenIndex = position398, tokenIndex398 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l400 + } + position++ + goto l398 + l400: + position, tokenIndex = position398, tokenIndex398 + if buffer[position] != rune('_') { + goto l401 + } + position++ + goto l398 + l401: + position, tokenIndex = position398, tokenIndex398 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l393 + } + position++ + } + l398: + goto l392 + l393: + position, tokenIndex = position393, tokenIndex393 + } + } + l390: + if buffer[position] != rune('@') { + goto l388 + } + position++ + { + position402, tokenIndex402 := position, tokenIndex + if buffer[position] != rune('l') { + goto l403 + } + position++ + goto l402 + l403: + position, tokenIndex = position402, tokenIndex402 + if buffer[position] != rune('L') { + goto l388 + } + position++ + } + l402: + add(ruleTOCRefLow, position389) + } + return true + l388: + position, tokenIndex = position388, tokenIndex388 + return false + }, + /* 30 IndirectionIndicator <- <'*'> */ + func() bool { + position404, tokenIndex404 := position, tokenIndex + { + position405 := position + if buffer[position] != rune('*') { + goto l404 + } + position++ + add(ruleIndirectionIndicator, position405) + } + return true + l404: + position, tokenIndex = position404, tokenIndex404 + return false + }, + /* 31 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset))) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ + func() bool { + position406, tokenIndex406 := position, tokenIndex + { + position407 := position + { + position408, tokenIndex408 := position, tokenIndex + if buffer[position] != rune('%') { + goto l409 + } + position++ + { + position410, tokenIndex410 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l411 + } + position++ + goto l410 + l411: + position, tokenIndex = position410, tokenIndex410 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l409 + } + position++ + } + l410: + l412: + { + position413, tokenIndex413 := position, tokenIndex + { + position414, tokenIndex414 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l415 + } + position++ + goto l414 + l415: + position, tokenIndex = position414, tokenIndex414 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l416 + } + position++ + goto l414 + l416: + position, tokenIndex = position414, tokenIndex414 + { + position417, tokenIndex417 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l418 + } + position++ + goto l417 + l418: + position, tokenIndex = position417, tokenIndex417 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l413 + } + position++ + } + l417: + } + l414: + goto l412 + l413: + position, tokenIndex = position413, tokenIndex413 + } + goto l408 + l409: + position, tokenIndex = position408, tokenIndex408 + { + position419, tokenIndex419 := position, tokenIndex + if buffer[position] != rune('$') { + goto l419 + } + position++ + goto l420 + l419: + position, tokenIndex = position419, tokenIndex419 + } + l420: + { + position421, tokenIndex421 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l422 + } + if !_rules[ruleOffset]() { + goto l422 + } + goto l421 + l422: + position, tokenIndex = position421, tokenIndex421 + if !_rules[ruleOffset]() { + goto l406 + } + } + l421: + } + l408: + { + position423, tokenIndex423 := position, tokenIndex + { + position424, tokenIndex424 := position, tokenIndex + if buffer[position] != rune('f') { + goto l425 + } + position++ + goto l424 + l425: + position, tokenIndex = position424, tokenIndex424 + if buffer[position] != rune('b') { + goto l426 + } + position++ + goto l424 + l426: + position, tokenIndex = position424, tokenIndex424 + if buffer[position] != rune(':') { + goto l427 + } + position++ + goto l424 + l427: + position, tokenIndex = position424, tokenIndex424 + if buffer[position] != rune('(') { + goto l428 + } + position++ + goto l424 + l428: + position, tokenIndex = position424, tokenIndex424 + if buffer[position] != rune('+') { + goto l429 + } + position++ + goto l424 + l429: + position, tokenIndex = position424, tokenIndex424 + if buffer[position] != rune('-') { + goto l423 + } + position++ + } + l424: + goto l406 + l423: + position, tokenIndex = position423, tokenIndex423 + } + add(ruleRegisterOrConstant, position407) + } + return true + l406: + position, tokenIndex = position406, tokenIndex406 + return false + }, + /* 32 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / BaseIndexScale)> */ + func() bool { + position430, tokenIndex430 := position, tokenIndex + { + position431 := position + { + position432, tokenIndex432 := position, tokenIndex + if !_rules[ruleSymbolRef]() { + goto l433 + } + if !_rules[ruleBaseIndexScale]() { + goto l433 + } + goto l432 + l433: + position, tokenIndex = position432, tokenIndex432 + if !_rules[ruleSymbolRef]() { + goto l434 + } + goto l432 + l434: + position, tokenIndex = position432, tokenIndex432 + l436: + { + position437, tokenIndex437 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l437 + } + goto l436 + l437: + position, tokenIndex = position437, tokenIndex437 + } + if !_rules[ruleBaseIndexScale]() { + goto l435 + } + goto l432 + l435: + position, tokenIndex = position432, tokenIndex432 + if !_rules[ruleSegmentRegister]() { + goto l438 + } + if !_rules[ruleOffset]() { + goto l438 + } + if !_rules[ruleBaseIndexScale]() { + goto l438 + } + goto l432 + l438: + position, tokenIndex = position432, tokenIndex432 + if !_rules[ruleSegmentRegister]() { + goto l439 + } + if !_rules[ruleBaseIndexScale]() { + goto l439 + } + goto l432 + l439: + position, tokenIndex = position432, tokenIndex432 + if !_rules[ruleSegmentRegister]() { + goto l440 + } + if !_rules[ruleOffset]() { + goto l440 + } + goto l432 + l440: + position, tokenIndex = position432, tokenIndex432 + if !_rules[ruleBaseIndexScale]() { + goto l430 + } + } + l432: + add(ruleMemoryRef, position431) + } + return true + l430: + position, tokenIndex = position430, tokenIndex430 + return false + }, + /* 33 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ + func() bool { + position441, tokenIndex441 := position, tokenIndex + { + position442 := position + { + position443, tokenIndex443 := position, tokenIndex + l445: + { + position446, tokenIndex446 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l446 + } + goto l445 + l446: + position, tokenIndex = position446, tokenIndex446 + } + if buffer[position] != rune('+') { + goto l443 + } + position++ + goto l444 + l443: + position, tokenIndex = position443, tokenIndex443 + } + l444: + { + position447, tokenIndex447 := position, tokenIndex + if !_rules[ruleLocalSymbol]() { + goto l448 + } + goto l447 + l448: + position, tokenIndex = position447, tokenIndex447 + if !_rules[ruleSymbolName]() { + goto l441 + } + } + l447: + l449: + { + position450, tokenIndex450 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l450 + } + goto l449 + l450: + position, tokenIndex = position450, tokenIndex450 + } + { + position451, tokenIndex451 := position, tokenIndex + if buffer[position] != rune('@') { + goto l451 + } + position++ + if !_rules[ruleSection]() { + goto l451 + } + l453: + { + position454, tokenIndex454 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l454 + } + goto l453 + l454: + position, tokenIndex = position454, tokenIndex454 + } + goto l452 + l451: + position, tokenIndex = position451, tokenIndex451 + } + l452: + add(ruleSymbolRef, position442) + } + return true + l441: + position, tokenIndex = position441, tokenIndex441 + return false + }, + /* 34 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ + func() bool { + position455, tokenIndex455 := position, tokenIndex + { + position456 := position + if buffer[position] != rune('(') { + goto l455 + } + position++ + { + position457, tokenIndex457 := position, tokenIndex + if !_rules[ruleRegisterOrConstant]() { + goto l457 + } + goto l458 + l457: + position, tokenIndex = position457, tokenIndex457 + } + l458: + { + position459, tokenIndex459 := position, tokenIndex + if !_rules[ruleWS]() { + goto l459 + } + goto l460 + l459: + position, tokenIndex = position459, tokenIndex459 + } + l460: + { + position461, tokenIndex461 := position, tokenIndex + if buffer[position] != rune(',') { + goto l461 + } + position++ + { + position463, tokenIndex463 := position, tokenIndex + if !_rules[ruleWS]() { + goto l463 + } + goto l464 + l463: + position, tokenIndex = position463, tokenIndex463 + } + l464: + if !_rules[ruleRegisterOrConstant]() { + goto l461 + } + { + position465, tokenIndex465 := position, tokenIndex + if !_rules[ruleWS]() { + goto l465 + } + goto l466 + l465: + position, tokenIndex = position465, tokenIndex465 + } + l466: + { + position467, tokenIndex467 := position, tokenIndex + if buffer[position] != rune(',') { + goto l467 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l467 + } + position++ + l469: + { + position470, tokenIndex470 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l470 + } + position++ + goto l469 + l470: + position, tokenIndex = position470, tokenIndex470 + } + goto l468 + l467: + position, tokenIndex = position467, tokenIndex467 + } + l468: + goto l462 + l461: + position, tokenIndex = position461, tokenIndex461 + } + l462: + if buffer[position] != rune(')') { + goto l455 + } + position++ + add(ruleBaseIndexScale, position456) + } + return true + l455: + position, tokenIndex = position455, tokenIndex455 + return false + }, + /* 35 Operator <- <('+' / '-')> */ + func() bool { + position471, tokenIndex471 := position, tokenIndex + { + position472 := position + { + position473, tokenIndex473 := position, tokenIndex + if buffer[position] != rune('+') { + goto l474 + } + position++ + goto l473 + l474: + position, tokenIndex = position473, tokenIndex473 + if buffer[position] != rune('-') { + goto l471 + } + position++ + } + l473: + add(ruleOperator, position472) + } + return true + l471: + position, tokenIndex = position471, tokenIndex471 + return false + }, + /* 36 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ + func() bool { + position475, tokenIndex475 := position, tokenIndex + { + position476 := position + { + position477, tokenIndex477 := position, tokenIndex + if buffer[position] != rune('+') { + goto l477 + } + position++ + goto l478 + l477: + position, tokenIndex = position477, tokenIndex477 + } + l478: + { + position479, tokenIndex479 := position, tokenIndex + if buffer[position] != rune('-') { + goto l479 + } + position++ + goto l480 + l479: + position, tokenIndex = position479, tokenIndex479 + } + l480: + { + position481, tokenIndex481 := position, tokenIndex + if buffer[position] != rune('0') { + goto l482 + } + position++ + { + position483, tokenIndex483 := position, tokenIndex + if buffer[position] != rune('b') { + goto l484 + } + position++ + goto l483 + l484: + position, tokenIndex = position483, tokenIndex483 + if buffer[position] != rune('B') { + goto l482 + } + position++ + } + l483: + { + position487, tokenIndex487 := position, tokenIndex + if buffer[position] != rune('0') { + goto l488 + } + position++ + goto l487 + l488: + position, tokenIndex = position487, tokenIndex487 + if buffer[position] != rune('1') { + goto l482 + } + position++ + } + l487: + l485: + { + position486, tokenIndex486 := position, tokenIndex + { + position489, tokenIndex489 := position, tokenIndex + if buffer[position] != rune('0') { + goto l490 + } + position++ + goto l489 + l490: + position, tokenIndex = position489, tokenIndex489 + if buffer[position] != rune('1') { + goto l486 + } + position++ + } + l489: + goto l485 + l486: + position, tokenIndex = position486, tokenIndex486 + } + goto l481 + l482: + position, tokenIndex = position481, tokenIndex481 + if buffer[position] != rune('0') { + goto l491 + } + position++ + { + position492, tokenIndex492 := position, tokenIndex + if buffer[position] != rune('x') { + goto l493 + } + position++ + goto l492 + l493: + position, tokenIndex = position492, tokenIndex492 + if buffer[position] != rune('X') { + goto l491 + } + position++ + } + l492: + { + position496, tokenIndex496 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l497 + } + position++ + goto l496 + l497: + position, tokenIndex = position496, tokenIndex496 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l498 + } + position++ + goto l496 + l498: + position, tokenIndex = position496, tokenIndex496 + { + position499, tokenIndex499 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('f') { + goto l500 + } + position++ + goto l499 + l500: + position, tokenIndex = position499, tokenIndex499 + if c := buffer[position]; c < rune('A') || c > rune('F') { + goto l491 + } + position++ + } + l499: + } + l496: + l494: + { + position495, tokenIndex495 := position, tokenIndex + { + position501, tokenIndex501 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l502 + } + position++ + goto l501 + l502: + position, tokenIndex = position501, tokenIndex501 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l503 + } + position++ + goto l501 + l503: + position, tokenIndex = position501, tokenIndex501 + { + position504, tokenIndex504 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('f') { + goto l505 + } + position++ + goto l504 + l505: + position, tokenIndex = position504, tokenIndex504 + if c := buffer[position]; c < rune('A') || c > rune('F') { + goto l495 + } + position++ + } + l504: + } + l501: + goto l494 + l495: + position, tokenIndex = position495, tokenIndex495 + } + goto l481 + l491: + position, tokenIndex = position481, tokenIndex481 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l475 + } + position++ + l506: + { + position507, tokenIndex507 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l507 + } + position++ + goto l506 + l507: + position, tokenIndex = position507, tokenIndex507 + } + } + l481: + add(ruleOffset, position476) + } + return true + l475: + position, tokenIndex = position475, tokenIndex475 + return false + }, + /* 37 Section <- <([a-z] / [A-Z] / '@')+> */ + func() bool { + position508, tokenIndex508 := position, tokenIndex + { + position509 := position + { + position512, tokenIndex512 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l513 + } + position++ + goto l512 + l513: + position, tokenIndex = position512, tokenIndex512 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l514 + } + position++ + goto l512 + l514: + position, tokenIndex = position512, tokenIndex512 + if buffer[position] != rune('@') { + goto l508 + } + position++ + } + l512: + l510: + { + position511, tokenIndex511 := position, tokenIndex + { + position515, tokenIndex515 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l516 + } + position++ + goto l515 + l516: + position, tokenIndex = position515, tokenIndex515 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l517 + } + position++ + goto l515 + l517: + position, tokenIndex = position515, tokenIndex515 + if buffer[position] != rune('@') { + goto l511 + } + position++ + } + l515: + goto l510 + l511: + position, tokenIndex = position511, tokenIndex511 + } + add(ruleSection, position509) + } + return true + l508: + position, tokenIndex = position508, tokenIndex508 + return false + }, + /* 38 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ + func() bool { + position518, tokenIndex518 := position, tokenIndex + { + position519 := position + if buffer[position] != rune('%') { + goto l518 + } + position++ + { + position520, tokenIndex520 := position, tokenIndex + if c := buffer[position]; c < rune('c') || c > rune('g') { + goto l521 + } + position++ + goto l520 + l521: + position, tokenIndex = position520, tokenIndex520 + if buffer[position] != rune('s') { + goto l518 + } + position++ + } + l520: + if buffer[position] != rune('s') { + goto l518 + } + position++ + if buffer[position] != rune(':') { + goto l518 + } + position++ + add(ruleSegmentRegister, position519) + } + return true + l518: + position, tokenIndex = position518, tokenIndex518 + return false + }, + } + p.rules = _rules +} diff --git a/src/util/fipstools/delocate/delocate_test.go b/src/util/fipstools/delocate/delocate_test.go new file mode 100644 index 00000000..e0ecc177 --- /dev/null +++ b/src/util/fipstools/delocate/delocate_test.go @@ -0,0 +1,86 @@ +// 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. */ + +package main + +import ( + "bytes" + "flag" + "io/ioutil" + "path/filepath" + "testing" +) + +var ( + testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.") + update = flag.Bool("update", false, "If true, update output files rather than compare them.") +) + +type delocateTest struct { + name string + in []string + out string +} + +func (test *delocateTest) Path(file string) string { + return filepath.Join(*testDataDir, test.name, file) +} + +var delocateTests = []delocateTest{ + {"ppc64le-GlobalEntry", []string{"in.s"}, "out.s"}, + {"ppc64le-LoadToR0", []string{"in.s"}, "out.s"}, + {"ppc64le-Sample2", []string{"in.s"}, "out.s"}, + {"ppc64le-Sample", []string{"in.s"}, "out.s"}, + {"ppc64le-TOCWithOffset", []string{"in.s"}, "out.s"}, + {"x86_64-Basic", []string{"in.s"}, "out.s"}, + {"x86_64-BSS", []string{"in.s"}, "out.s"}, + {"x86_64-GOTRewrite", []string{"in.s"}, "out.s"}, + {"x86_64-LabelRewrite", []string{"in1.s", "in2.s"}, "out.s"}, + {"x86_64-Sections", []string{"in.s"}, "out.s"}, +} + +func TestDelocate(t *testing.T) { + for _, test := range delocateTests { + t.Run(test.name, func(t *testing.T) { + var inputs []inputFile + for i, in := range test.in { + inputs = append(inputs, inputFile{ + index: i, + path: test.Path(in), + }) + } + + if err := parseInputs(inputs); err != nil { + t.Fatalf("parseInputs failed: %s", err) + } + + var buf bytes.Buffer + if err := transform(&buf, inputs); err != nil { + t.Fatalf("transform failed: %s", err) + } + + if *update { + ioutil.WriteFile(test.Path(test.out), buf.Bytes(), 0666) + } else { + expected, err := ioutil.ReadFile(test.Path(test.out)) + if err != nil { + t.Fatalf("could not read %q: %s", test.Path(test.out), err) + } + if !bytes.Equal(buf.Bytes(), expected) { + t.Errorf("delocated output differed. Wanted:\n%s\nGot:\n%s\n", expected, buf.Bytes()) + } + } + }) + } +} diff --git a/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s b/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s new file mode 100644 index 00000000..af1a182c --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s @@ -0,0 +1,9 @@ + .text +foo: +.LCF0: +0: + addis 2,12,.TOC.-.LCF0@ha + addi 2,2,.TOC.-.LCF0@l + .localentry foo,.-foo +.LVL0: + bl diff --git a/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s b/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s new file mode 100644 index 00000000..304f697a --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s @@ -0,0 +1,94 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .text +.Lfoo_local_target: +foo: +.LCF0: + +0: + +999: + addis 2, 12, .LBORINGSSL_external_toc-999b@ha + addi 2, 2, .LBORINGSSL_external_toc-999b@l + ld 12, 0(2) + add 2, 2, 12 +# WAS addi 2,2,.TOC.-.LCF0@l + .localentry foo,.-foo +.Lfoo_local_entry: +.LVL0: + + bl +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.LBORINGSSL_external_toc: +.quad .TOC.-.LBORINGSSL_external_toc +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s b/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s new file mode 100644 index 00000000..81766dc0 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s @@ -0,0 +1,4 @@ + .text +foo: + addis 22,2,bar@toc@ha + ld 0,bar@toc@l(22) diff --git a/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s b/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s new file mode 100644 index 00000000..5fdbeb89 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s @@ -0,0 +1,104 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .text +.Lfoo_local_target: +foo: +# WAS addis 22,2,bar@toc@ha +# WAS ld 0,bar@toc@l(22) + addi 1, 1, -288 + mflr 0 + std 0, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc_bar + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 0, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + addi 1, 1, -288 + std 3, -8(1) + mr 3, 0 + ld 0, 0(3) + ld 3, -8(1) + addi 1, 1, 288 +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type bcm_loadtoc_bar, @function +bcm_loadtoc_bar: +.Lbcm_loadtoc_bar: + addis 3, 2, bar@toc@ha + addi 3, 3, bar@toc@l + blr +.LBORINGSSL_external_toc: +.quad .TOC.-.LBORINGSSL_external_toc +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/ppc64le-Sample/in.s b/src/util/fipstools/delocate/testdata/ppc64le-Sample/in.s new file mode 100644 index 00000000..6e7422ab --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-Sample/in.s @@ -0,0 +1,161 @@ + .file "foo.c" + .abiversion 2 + .section ".toc","aw" + .section ".text" + .section .rodata + .align 3 + .type kString, @object + .size kString, 12 +kString: + .string "hello world" + .globl kExportedString + .align 3 + .type kExportedString, @object + .size kExportedString, 26 +kExportedString: + .string "hello world, more visibly" + .align 2 + .type kGiantArray, @object + .size kGiantArray, 400000 +kGiantArray: + .long 1 + .long 0 + .zero 399992 + .lcomm bss,20,4 + .type bss, @object + .align 3 +.LC1: + .string "kString is %p\n" + .align 3 +.LC2: + .string "kExportedString is %p\n" + .align 3 +.LC4: + .string "function is %p\n" + .align 3 +.LC5: + .string "exported_function is %p\n" + .align 3 +.LC7: + .string "&kString[5] is %p\n" + .align 3 +.LC9: + .string "&kGiantArray[0x12345] is %p\n" + .section ".toc","aw" +.LC0: + .quad stderr +.LC3: + .quad kExportedString +.LC6: + .quad exported_function +.LC8: + .quad kString+5 +.LC10: + .quad kGiantArray+298260 + .section ".text" + .align 2 + .type function, @function +function: +0: addis 2,12,.TOC.-0b@ha + addi 2,2,.TOC.-0b@l + .localentry function,.-function + mflr 0 + std 0,16(1) + std 31,-8(1) + stdu 1,-112(1) + mr 31,1 + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC1@toc@ha + addi 4,4,.LC1@toc@l + addis 5,2,kString@toc@ha + addi 5,5,kString@toc@l + bl fprintf + nop + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC2@toc@ha + addi 4,4,.LC2@toc@l + addis 9,2,.LC3@toc@ha + ld 5,.LC3@toc@l(9) + bl fprintf + nop + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC4@toc@ha + addi 4,4,.LC4@toc@l + addis 5,2,function@toc@ha + addi 5,5,function@toc@l + bl fprintf + nop + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC5@toc@ha + addi 4,4,.LC5@toc@l + addis 9,2,.LC6@toc@ha + ld 5,.LC6@toc@l(9) + bl fprintf + nop + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC7@toc@ha + addi 4,4,.LC7@toc@l + addis 9,2,.LC8@toc@ha + ld 5,.LC8@toc@l(9) + bl fprintf + nop + addis 10,2,.LC0@toc@ha + ld 9,.LC0@toc@l(10) + ld 9,0(9) + mr 3,9 + addis 4,2,.LC9@toc@ha + addi 4,4,.LC9@toc@l + addis 9,2,.LC10@toc@ha + ld 5,.LC10@toc@l(9) + bl fprintf + nop + bl exported_function + nop + mr 3,9 + addi 1,31,112 + ld 0,16(1) + mtlr 0 + ld 31,-8(1) + blr + .long 0 + .byte 0,0,0,1,128,1,0,1 + .size function,.-function + .align 2 + .globl exported_function + .type exported_function, @function +exported_function: +0: addis 2,12,.TOC.-0b@ha + addi 2,2,.TOC.-0b@l + .localentry exported_function,.-exported_function + mflr 0 + std 0,16(1) + std 31,-8(1) + stdu 1,-48(1) + mr 31,1 + bl function + mr 3,9 + addi 1,31,48 + ld 0,16(1) + mtlr 0 + ld 31,-8(1) + blr + .long 0 + .byte 0,0,0,1,128,1,0,1 + .size exported_function,.-exported_function + .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" + .section .note.GNU-stack,"",@progbits diff --git a/src/util/fipstools/delocate/testdata/ppc64le-Sample/out.s b/src/util/fipstools/delocate/testdata/ppc64le-Sample/out.s new file mode 100644 index 00000000..e3d682e5 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-Sample/out.s @@ -0,0 +1,584 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .file "foo.c" + .abiversion 2 + .section ".toc","aw" +# WAS .section ".text" +.text +# WAS .section .rodata +.text + .align 3 + .type kString, @object + .size kString, 12 +.LkString_local_target: +kString: + .string "hello world" + .globl kExportedString + .align 3 + .type kExportedString, @object + .size kExportedString, 26 +.LkExportedString_local_target: +kExportedString: + .string "hello world, more visibly" + .align 2 + .type kGiantArray, @object + .size kGiantArray, 400000 +.LkGiantArray_local_target: +kGiantArray: + .long 1 + .long 0 + .zero 399992 + .lcomm bss,20,4 + .type bss, @object + .align 3 +.LC1: + + .string "kString is %p\n" + .align 3 +.LC2: + + .string "kExportedString is %p\n" + .align 3 +.LC4: + + .string "function is %p\n" + .align 3 +.LC5: + + .string "exported_function is %p\n" + .align 3 +.LC7: + + .string "&kString[5] is %p\n" + .align 3 +.LC9: + + .string "&kGiantArray[0x12345] is %p\n" + .section ".toc","aw" +.LC0: + + .quad stderr +.LC3: + + .quad kExportedString +.LC6: + + .quad exported_function +.LC8: + + .quad kString+5 +.LC10: + + .quad kGiantArray+298260 +# WAS .section ".text" +.text + .align 2 + .type function, @function +.Lfunction_local_target: +function: +0: +999: + addis 2, 12, .LBORINGSSL_external_toc-999b@ha + addi 2, 2, .LBORINGSSL_external_toc-999b@l + ld 12, 0(2) + add 2, 2, 12 +# WAS addi 2,2,.TOC.-0b@l + .localentry function,.-function +.Lfunction_local_entry: + mflr 0 + std 0,16(1) + std 31,-8(1) + stdu 1,-112(1) + mr 31,1 +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC1@toc@ha +# WAS addi 4,4,.LC1@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC1 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 5,2,kString@toc@ha +# WAS addi 5,5,kString@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LkString_local_target + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC2@toc@ha +# WAS addi 4,4,.LC2@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC2 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 9,2,.LC3@toc@ha +# WAS ld 5,.LC3@toc@l(9) + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC3 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 5, 0(5) +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC4@toc@ha +# WAS addi 4,4,.LC4@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC4 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 5,2,function@toc@ha +# WAS addi 5,5,function@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfunction_local_target + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC5@toc@ha +# WAS addi 4,4,.LC5@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC5 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 9,2,.LC6@toc@ha +# WAS ld 5,.LC6@toc@l(9) + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC6 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 5, 0(5) +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC7@toc@ha +# WAS addi 4,4,.LC7@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC7 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 9,2,.LC8@toc@ha +# WAS ld 5,.LC8@toc@l(9) + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC8 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 5, 0(5) +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS addis 10,2,.LC0@toc@ha +# WAS ld 9,.LC0@toc@l(10) + addi 1, 1, -288 + mflr 9 + std 9, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 9, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 9, 0(9) + ld 9,0(9) + mr 3,9 +# WAS addis 4,2,.LC9@toc@ha +# WAS addi 4,4,.LC9@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC9 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 9,2,.LC10@toc@ha +# WAS ld 5,.LC10@toc@l(9) + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC10 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 5, 0(5) +# WAS bl fprintf + bl bcm_redirector_fprintf + ld 2, 24(1) + nop +# WAS bl exported_function + bl .Lexported_function_local_entry + nop + mr 3,9 + addi 1,31,112 + ld 0,16(1) + mtlr 0 + ld 31,-8(1) + blr + .long 0 + .byte 0,0,0,1,128,1,0,1 + .size function,.-function + .align 2 + .globl exported_function + .type exported_function, @function +.Lexported_function_local_target: +exported_function: +0: +999: + addis 2, 12, .LBORINGSSL_external_toc-999b@ha + addi 2, 2, .LBORINGSSL_external_toc-999b@l + ld 12, 0(2) + add 2, 2, 12 +# WAS addi 2,2,.TOC.-0b@l + .localentry exported_function,.-exported_function +.Lexported_function_local_entry: + mflr 0 + std 0,16(1) + std 31,-8(1) + stdu 1,-48(1) + mr 31,1 +# WAS bl function + bl .Lfunction_local_entry + mr 3,9 + addi 1,31,48 + ld 0,16(1) + mtlr 0 + ld 31,-8(1) + blr + .long 0 + .byte 0,0,0,1,128,1,0,1 + .size exported_function,.-exported_function + .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" + .section .note.GNU-stack,"",@progbits +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.section ".toc", "aw" +.Lredirector_toc_fprintf: +.quad fprintf +.text +.type bcm_redirector_fprintf, @function +bcm_redirector_fprintf: + std 2, 24(1) + addis 12, 2, .Lredirector_toc_fprintf@toc@ha + ld 12, .Lredirector_toc_fprintf@toc@l(12) + mtctr 12 + bctr +.type bss_bss_get, @function +bss_bss_get: + addis 3, 2, bss@toc@ha + addi 3, 3, bss@toc@l + blr +.type bcm_loadtoc__dot_LC0, @function +bcm_loadtoc__dot_LC0: +.Lbcm_loadtoc__dot_LC0: + addis 3, 2, .LC0@toc@ha + addi 3, 3, .LC0@toc@l + blr +.type bcm_loadtoc__dot_LC1, @function +bcm_loadtoc__dot_LC1: +.Lbcm_loadtoc__dot_LC1: + addis 3, 2, .LC1@toc@ha + addi 3, 3, .LC1@toc@l + blr +.type bcm_loadtoc__dot_LC10, @function +bcm_loadtoc__dot_LC10: +.Lbcm_loadtoc__dot_LC10: + addis 3, 2, .LC10@toc@ha + addi 3, 3, .LC10@toc@l + blr +.type bcm_loadtoc__dot_LC2, @function +bcm_loadtoc__dot_LC2: +.Lbcm_loadtoc__dot_LC2: + addis 3, 2, .LC2@toc@ha + addi 3, 3, .LC2@toc@l + blr +.type bcm_loadtoc__dot_LC3, @function +bcm_loadtoc__dot_LC3: +.Lbcm_loadtoc__dot_LC3: + addis 3, 2, .LC3@toc@ha + addi 3, 3, .LC3@toc@l + blr +.type bcm_loadtoc__dot_LC4, @function +bcm_loadtoc__dot_LC4: +.Lbcm_loadtoc__dot_LC4: + addis 3, 2, .LC4@toc@ha + addi 3, 3, .LC4@toc@l + blr +.type bcm_loadtoc__dot_LC5, @function +bcm_loadtoc__dot_LC5: +.Lbcm_loadtoc__dot_LC5: + addis 3, 2, .LC5@toc@ha + addi 3, 3, .LC5@toc@l + blr +.type bcm_loadtoc__dot_LC6, @function +bcm_loadtoc__dot_LC6: +.Lbcm_loadtoc__dot_LC6: + addis 3, 2, .LC6@toc@ha + addi 3, 3, .LC6@toc@l + blr +.type bcm_loadtoc__dot_LC7, @function +bcm_loadtoc__dot_LC7: +.Lbcm_loadtoc__dot_LC7: + addis 3, 2, .LC7@toc@ha + addi 3, 3, .LC7@toc@l + blr +.type bcm_loadtoc__dot_LC8, @function +bcm_loadtoc__dot_LC8: +.Lbcm_loadtoc__dot_LC8: + addis 3, 2, .LC8@toc@ha + addi 3, 3, .LC8@toc@l + blr +.type bcm_loadtoc__dot_LC9, @function +bcm_loadtoc__dot_LC9: +.Lbcm_loadtoc__dot_LC9: + addis 3, 2, .LC9@toc@ha + addi 3, 3, .LC9@toc@l + blr +.type bcm_loadtoc__dot_Lfunction_local_target, @function +bcm_loadtoc__dot_Lfunction_local_target: +.Lbcm_loadtoc__dot_Lfunction_local_target: + addis 3, 2, .Lfunction_local_target@toc@ha + addi 3, 3, .Lfunction_local_target@toc@l + blr +.type bcm_loadtoc__dot_LkString_local_target, @function +bcm_loadtoc__dot_LkString_local_target: +.Lbcm_loadtoc__dot_LkString_local_target: + addis 3, 2, .LkString_local_target@toc@ha + addi 3, 3, .LkString_local_target@toc@l + blr +.LBORINGSSL_external_toc: +.quad .TOC.-.LBORINGSSL_external_toc +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s b/src/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s new file mode 100644 index 00000000..eb856269 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s @@ -0,0 +1,226 @@ + .file "foo.c" + .abiversion 2 + .section ".toc","aw" + .section ".text" + .section ".toc","aw" +.LC0: + .quad stderr +.LC3: + .quad kExportedString +.LC6: + .quad exported_function + .section ".text" + .align 2 + .p2align 4,,15 + .globl exported_function + .type exported_function, @function +exported_function: +0: addis 2,12,.TOC.-0b@ha + addi 2,2,.TOC.-0b@l + .localentry exported_function,.-exported_function + mflr 0 + std 19,-104(1) + std 20,-96(1) + std 21,-88(1) + std 22,-80(1) + addis 21,2,.LC1@toc@ha + addis 22,2,.LC2@toc@ha + std 23,-72(1) + std 24,-64(1) + addis 23,2,.LC4@toc@ha + addis 24,2,function@toc@ha + std 25,-56(1) + std 26,-48(1) + addis 25,2,.LC5@toc@ha + addis 26,2,.LC7@toc@ha + std 27,-40(1) + std 28,-32(1) + addis 28,2,.LC8@toc@ha + addi 21,21,.LC1@toc@l + std 29,-24(1) + std 30,-16(1) + addis 29,2,.LANCHOR0@toc@ha + addi 22,22,.LC2@toc@l + std 31,-8(1) + std 0,16(1) + addi 29,29,.LANCHOR0@toc@l + addi 23,23,.LC4@toc@l + stdu 1,-208(1) + addis 31,2,.LC0@toc@ha # gpr load fusion, type long + ld 31,.LC0@toc@l(31) + addis 19,2,.LC3@toc@ha # gpr load fusion, type long + ld 19,.LC3@toc@l(19) + addis 30,29,0x5 + addi 24,24,function@toc@l + addis 20,2,.LC6@toc@ha # gpr load fusion, type long + ld 20,.LC6@toc@l(20) + addi 25,25,.LC5@toc@l + addi 26,26,.LC7@toc@l + addi 27,29,5 + addi 28,28,.LC8@toc@l + addi 30,30,-29404 + .p2align 4,,15 +.L2: + ld 3,0(31) + mr 5,21 + mr 6,29 + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + mr 5,22 + mr 6,19 + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + mr 5,23 + mr 6,24 + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + mr 5,25 + mr 6,20 + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + mr 5,26 + mr 6,27 + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + li 4,1 + mr 5,28 + mr 6,30 + bl __fprintf_chk + nop + b .L2 + .long 0 + .byte 0,0,0,1,128,13,0,0 + .size exported_function,.-exported_function + .section ".toc","aw" + .set .LC11,.LC0 + .set .LC12,.LC3 + .set .LC13,.LC6 + .section ".text" + .align 2 + .p2align 4,,15 + .type function, @function +function: +0: addis 2,12,.TOC.-0b@ha + addi 2,2,.TOC.-0b@l + .localentry function,.-function + mflr 0 + std 31,-8(1) + addis 31,2,.LC11@toc@ha # gpr load fusion, type long + ld 31,.LC11@toc@l(31) + addis 5,2,.LC1@toc@ha + std 30,-16(1) + addis 30,2,.LANCHOR0@toc@ha + addi 5,5,.LC1@toc@l + addi 30,30,.LANCHOR0@toc@l + li 4,1 + mr 6,30 + std 0,16(1) + stdu 1,-112(1) + ld 3,0(31) + bl __fprintf_chk + nop + addis 6,2,.LC12@toc@ha # gpr load fusion, type long + ld 6,.LC12@toc@l(6) + ld 3,0(31) + addis 5,2,.LC2@toc@ha + li 4,1 + addi 5,5,.LC2@toc@l + bl __fprintf_chk + nop + ld 3,0(31) + addis 5,2,.LC4@toc@ha + addis 6,2,function@toc@ha + addi 5,5,.LC4@toc@l + addi 6,6,function@toc@l + li 4,1 + bl __fprintf_chk + nop + addis 6,2,.LC13@toc@ha # gpr load fusion, type long + ld 6,.LC13@toc@l(6) + ld 3,0(31) + addis 5,2,.LC5@toc@ha + li 4,1 + addi 5,5,.LC5@toc@l + bl __fprintf_chk + nop + ld 3,0(31) + addis 5,2,.LC7@toc@ha + addi 6,30,5 + addi 5,5,.LC7@toc@l + li 4,1 + bl __fprintf_chk + nop + ld 3,0(31) + addis 6,30,0x5 + addis 5,2,.LC8@toc@ha + li 4,1 + addi 5,5,.LC8@toc@l + addi 6,6,-29404 + bl __fprintf_chk + nop + bl exported_function + nop + addi 1,1,112 + ld 0,16(1) + ld 30,-16(1) + ld 31,-8(1) + mtlr 0 + blr + .long 0 + .byte 0,0,0,1,128,2,0,0 + .size function,.-function + .globl kExportedString + .section .rodata + .align 4 + .set .LANCHOR0,. + 0 + .type kString, @object + .size kString, 12 +kString: + .string "hello world" + .zero 4 + .type kGiantArray, @object + .size kGiantArray, 400000 +kGiantArray: + .long 1 + .long 0 + .zero 399992 + .type kExportedString, @object + .size kExportedString, 26 +kExportedString: + .string "hello world, more visibly" + .section .rodata.str1.8,"aMS",@progbits,1 + .align 3 +.LC1: + .string "kString is %p\n" + .zero 1 +.LC2: + .string "kExportedString is %p\n" + .zero 1 +.LC4: + .string "function is %p\n" +.LC5: + .string "exported_function is %p\n" + .zero 7 +.LC7: + .string "&kString[5] is %p\n" + .zero 5 +.LC8: + .string "&kGiantArray[0x12345] is %p\n" + .section ".bss" + .align 2 + .type bss, @object + .size bss, 20 +bss: + .zero 20 + .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" + .section .note.GNU-stack,"",@progbits diff --git a/src/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s b/src/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s new file mode 100644 index 00000000..54cbd6f8 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s @@ -0,0 +1,709 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .file "foo.c" + .abiversion 2 + .section ".toc","aw" +# WAS .section ".text" +.text + .section ".toc","aw" +.LC0: + + .quad stderr +.LC3: + + .quad kExportedString +.LC6: + + .quad exported_function +# WAS .section ".text" +.text + .align 2 + .p2align 4,,15 + .globl exported_function + .type exported_function, @function +.Lexported_function_local_target: +exported_function: +0: +999: + addis 2, 12, .LBORINGSSL_external_toc-999b@ha + addi 2, 2, .LBORINGSSL_external_toc-999b@l + ld 12, 0(2) + add 2, 2, 12 +# WAS addi 2,2,.TOC.-0b@l + .localentry exported_function,.-exported_function +.Lexported_function_local_entry: + mflr 0 + std 19,-104(1) + std 20,-96(1) + std 21,-88(1) + std 22,-80(1) +# WAS addis 21,2,.LC1@toc@ha +# WAS addis 22,2,.LC2@toc@ha + std 23,-72(1) + std 24,-64(1) +# WAS addis 23,2,.LC4@toc@ha +# WAS addis 24,2,function@toc@ha + std 25,-56(1) + std 26,-48(1) +# WAS addis 25,2,.LC5@toc@ha +# WAS addis 26,2,.LC7@toc@ha + std 27,-40(1) + std 28,-32(1) +# WAS addis 28,2,.LC8@toc@ha +# WAS addi 21,21,.LC1@toc@l + addi 1, 1, -288 + mflr 21 + std 21, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC1 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 21, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + std 29,-24(1) + std 30,-16(1) +# WAS addis 29,2,.LANCHOR0@toc@ha +# WAS addi 22,22,.LC2@toc@l + addi 1, 1, -288 + mflr 22 + std 22, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC2 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 22, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + std 31,-8(1) + std 0,16(1) +# WAS addi 29,29,.LANCHOR0@toc@l + addi 1, 1, -288 + mflr 29 + std 29, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LANCHOR0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 29, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addi 23,23,.LC4@toc@l + addi 1, 1, -288 + mflr 23 + std 23, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC4 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 23, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + stdu 1,-208(1) +# WAS addis 31,2,.LC0@toc@ha # gpr load fusion, type long +# WAS ld 31,.LC0@toc@l(31) + addi 1, 1, -288 + mflr 31 + std 31, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 31, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 31, 0(31) +# WAS addis 19,2,.LC3@toc@ha # gpr load fusion, type long +# WAS ld 19,.LC3@toc@l(19) + addi 1, 1, -288 + mflr 19 + std 19, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC3 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 19, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 19, 0(19) + addis 30,29,0x5 +# WAS addi 24,24,function@toc@l + addi 1, 1, -288 + mflr 24 + std 24, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfunction_local_target + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 24, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addis 20,2,.LC6@toc@ha # gpr load fusion, type long +# WAS ld 20,.LC6@toc@l(20) + addi 1, 1, -288 + mflr 20 + std 20, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC6 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 20, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 20, 0(20) +# WAS addi 25,25,.LC5@toc@l + addi 1, 1, -288 + mflr 25 + std 25, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC5 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 25, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addi 26,26,.LC7@toc@l + addi 1, 1, -288 + mflr 26 + std 26, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC7 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 26, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + addi 27,29,5 +# WAS addi 28,28,.LC8@toc@l + addi 1, 1, -288 + mflr 28 + std 28, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC8 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 28, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + addi 30,30,-29404 + .p2align 4,,15 +.L2: + + ld 3,0(31) + mr 5,21 + mr 6,29 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + mr 5,22 + mr 6,19 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + mr 5,23 + mr 6,24 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + mr 5,25 + mr 6,20 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + mr 5,26 + mr 6,27 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + li 4,1 + mr 5,28 + mr 6,30 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + b .L2 + .long 0 + .byte 0,0,0,1,128,13,0,0 + .size exported_function,.-exported_function + .section ".toc","aw" + .set .LC11,.LC0 + .set .LC12,.LC3 + .set .LC13,.LC6 +# WAS .section ".text" +.text + .align 2 + .p2align 4,,15 + .type function, @function +.Lfunction_local_target: +function: +0: +999: + addis 2, 12, .LBORINGSSL_external_toc-999b@ha + addi 2, 2, .LBORINGSSL_external_toc-999b@l + ld 12, 0(2) + add 2, 2, 12 +# WAS addi 2,2,.TOC.-0b@l + .localentry function,.-function +.Lfunction_local_entry: + mflr 0 + std 31,-8(1) +# WAS addis 31,2,.LC11@toc@ha # gpr load fusion, type long +# WAS ld 31,.LC11@toc@l(31) + addi 1, 1, -288 + mflr 31 + std 31, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC11 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 31, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 31, 0(31) +# WAS addis 5,2,.LC1@toc@ha + std 30,-16(1) +# WAS addis 30,2,.LANCHOR0@toc@ha +# WAS addi 5,5,.LC1@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC1 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addi 30,30,.LANCHOR0@toc@l + addi 1, 1, -288 + mflr 30 + std 30, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LANCHOR0 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 30, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + li 4,1 + mr 6,30 + std 0,16(1) + stdu 1,-112(1) + ld 3,0(31) +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop +# WAS addis 6,2,.LC12@toc@ha # gpr load fusion, type long +# WAS ld 6,.LC12@toc@l(6) + addi 1, 1, -288 + mflr 6 + std 6, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC12 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 6, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 6, 0(6) + ld 3,0(31) +# WAS addis 5,2,.LC2@toc@ha + li 4,1 +# WAS addi 5,5,.LC2@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC2 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) +# WAS addis 5,2,.LC4@toc@ha +# WAS addis 6,2,function@toc@ha +# WAS addi 5,5,.LC4@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC4 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS addi 6,6,function@toc@l + addi 1, 1, -288 + mflr 6 + std 6, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfunction_local_target + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 6, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop +# WAS addis 6,2,.LC13@toc@ha # gpr load fusion, type long +# WAS ld 6,.LC13@toc@l(6) + addi 1, 1, -288 + mflr 6 + std 6, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC13 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 6, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 6, 0(6) + ld 3,0(31) +# WAS addis 5,2,.LC5@toc@ha + li 4,1 +# WAS addi 5,5,.LC5@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC5 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) +# WAS addis 5,2,.LC7@toc@ha + addi 6,30,5 +# WAS addi 5,5,.LC7@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC7 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + li 4,1 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop + ld 3,0(31) + addis 6,30,0x5 +# WAS addis 5,2,.LC8@toc@ha + li 4,1 +# WAS addi 5,5,.LC8@toc@l + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_LC8 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + addi 6,6,-29404 +# WAS bl __fprintf_chk + bl bcm_redirector___fprintf_chk + ld 2, 24(1) + nop +# WAS bl exported_function + bl .Lexported_function_local_entry + nop + addi 1,1,112 + ld 0,16(1) + ld 30,-16(1) + ld 31,-8(1) + mtlr 0 + blr + .long 0 + .byte 0,0,0,1,128,2,0,0 + .size function,.-function + .globl kExportedString +# WAS .section .rodata +.text + .align 4 + .set .LANCHOR0,. + 0 + .type kString, @object + .size kString, 12 +.LkString_local_target: +kString: + .string "hello world" + .zero 4 + .type kGiantArray, @object + .size kGiantArray, 400000 +.LkGiantArray_local_target: +kGiantArray: + .long 1 + .long 0 + .zero 399992 + .type kExportedString, @object + .size kExportedString, 26 +.LkExportedString_local_target: +kExportedString: + .string "hello world, more visibly" +# WAS .section .rodata.str1.8,"aMS",@progbits,1 +.text + .align 3 +.LC1: + + .string "kString is %p\n" + .zero 1 +.LC2: + + .string "kExportedString is %p\n" + .zero 1 +.LC4: + + .string "function is %p\n" +.LC5: + + .string "exported_function is %p\n" + .zero 7 +.LC7: + + .string "&kString[5] is %p\n" + .zero 5 +.LC8: + + .string "&kGiantArray[0x12345] is %p\n" + .section ".bss" + .align 2 + .type bss, @object + .size bss, 20 +bss: +.Lbss_local_target: + + .zero 20 + .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" + .section .note.GNU-stack,"",@progbits +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.section ".toc", "aw" +.Lredirector_toc___fprintf_chk: +.quad __fprintf_chk +.text +.type bcm_redirector___fprintf_chk, @function +bcm_redirector___fprintf_chk: + std 2, 24(1) + addis 12, 2, .Lredirector_toc___fprintf_chk@toc@ha + ld 12, .Lredirector_toc___fprintf_chk@toc@l(12) + mtctr 12 + bctr +.type bss_bss_get, @function +bss_bss_get: + addis 3, 2, .Lbss_local_target@toc@ha + addi 3, 3, .Lbss_local_target@toc@l + blr +.type bcm_loadtoc__dot_LANCHOR0, @function +bcm_loadtoc__dot_LANCHOR0: +.Lbcm_loadtoc__dot_LANCHOR0: + addis 3, 2, .LANCHOR0@toc@ha + addi 3, 3, .LANCHOR0@toc@l + blr +.type bcm_loadtoc__dot_LC0, @function +bcm_loadtoc__dot_LC0: +.Lbcm_loadtoc__dot_LC0: + addis 3, 2, .LC0@toc@ha + addi 3, 3, .LC0@toc@l + blr +.type bcm_loadtoc__dot_LC1, @function +bcm_loadtoc__dot_LC1: +.Lbcm_loadtoc__dot_LC1: + addis 3, 2, .LC1@toc@ha + addi 3, 3, .LC1@toc@l + blr +.type bcm_loadtoc__dot_LC11, @function +bcm_loadtoc__dot_LC11: +.Lbcm_loadtoc__dot_LC11: + addis 3, 2, .LC11@toc@ha + addi 3, 3, .LC11@toc@l + blr +.type bcm_loadtoc__dot_LC12, @function +bcm_loadtoc__dot_LC12: +.Lbcm_loadtoc__dot_LC12: + addis 3, 2, .LC12@toc@ha + addi 3, 3, .LC12@toc@l + blr +.type bcm_loadtoc__dot_LC13, @function +bcm_loadtoc__dot_LC13: +.Lbcm_loadtoc__dot_LC13: + addis 3, 2, .LC13@toc@ha + addi 3, 3, .LC13@toc@l + blr +.type bcm_loadtoc__dot_LC2, @function +bcm_loadtoc__dot_LC2: +.Lbcm_loadtoc__dot_LC2: + addis 3, 2, .LC2@toc@ha + addi 3, 3, .LC2@toc@l + blr +.type bcm_loadtoc__dot_LC3, @function +bcm_loadtoc__dot_LC3: +.Lbcm_loadtoc__dot_LC3: + addis 3, 2, .LC3@toc@ha + addi 3, 3, .LC3@toc@l + blr +.type bcm_loadtoc__dot_LC4, @function +bcm_loadtoc__dot_LC4: +.Lbcm_loadtoc__dot_LC4: + addis 3, 2, .LC4@toc@ha + addi 3, 3, .LC4@toc@l + blr +.type bcm_loadtoc__dot_LC5, @function +bcm_loadtoc__dot_LC5: +.Lbcm_loadtoc__dot_LC5: + addis 3, 2, .LC5@toc@ha + addi 3, 3, .LC5@toc@l + blr +.type bcm_loadtoc__dot_LC6, @function +bcm_loadtoc__dot_LC6: +.Lbcm_loadtoc__dot_LC6: + addis 3, 2, .LC6@toc@ha + addi 3, 3, .LC6@toc@l + blr +.type bcm_loadtoc__dot_LC7, @function +bcm_loadtoc__dot_LC7: +.Lbcm_loadtoc__dot_LC7: + addis 3, 2, .LC7@toc@ha + addi 3, 3, .LC7@toc@l + blr +.type bcm_loadtoc__dot_LC8, @function +bcm_loadtoc__dot_LC8: +.Lbcm_loadtoc__dot_LC8: + addis 3, 2, .LC8@toc@ha + addi 3, 3, .LC8@toc@l + blr +.type bcm_loadtoc__dot_Lfunction_local_target, @function +bcm_loadtoc__dot_Lfunction_local_target: +.Lbcm_loadtoc__dot_Lfunction_local_target: + addis 3, 2, .Lfunction_local_target@toc@ha + addi 3, 3, .Lfunction_local_target@toc@l + blr +.LBORINGSSL_external_toc: +.quad .TOC.-.LBORINGSSL_external_toc +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s b/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s new file mode 100644 index 00000000..94ea2111 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s @@ -0,0 +1,23 @@ + .text +foo: + # TOC references may have offsets. + addis 3, 2, 5+foo@toc@ha + addi 3, 3, 10+foo@toc@l + + addis 3, 2, 15+foo@toc@ha + addi 3, 3, 20+foo@toc@l + + addis 4, 2, foo@toc@ha + addi 4, 4, foo@toc@l + + addis 5, 2, 5+foo@toc@ha + ld 5, 10+foo@toc@l(5) + + addis 4, 2, foo-10@toc@ha + addi 4, 4, foo-10@toc@l + + addis 4, 2, foo@toc@ha+25 + addi 4, 4, foo@toc@l+25 + + addis 4, 2, 1+foo-2@toc@ha+3 + addi 4, 4, 1+foo-2@toc@l+3 diff --git a/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s b/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s new file mode 100644 index 00000000..2fff0efb --- /dev/null +++ b/src/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s @@ -0,0 +1,210 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .text +.Lfoo_local_target: +foo: + # TOC references may have offsets. +# WAS addis 3, 2, 5+foo@toc@ha +# WAS addi 3, 3, 10+foo@toc@l + addi 1, 1, -288 + mflr 3 + std 3, -8(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 3, -24(1) + addi 1, 1, 288 + +# WAS addis 3, 2, 15+foo@toc@ha +# WAS addi 3, 3, 20+foo@toc@l + addi 1, 1, -288 + mflr 3 + std 3, -8(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_20 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 3, -24(1) + addi 1, 1, 288 + +# WAS addis 4, 2, foo@toc@ha +# WAS addi 4, 4, foo@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + +# WAS addis 5, 2, 5+foo@toc@ha +# WAS ld 5, 10+foo@toc@l(5) + addi 1, 1, -288 + mflr 5 + std 5, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 5, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + ld 5, 0(5) + +# WAS addis 4, 2, foo-10@toc@ha +# WAS addi 4, 4, foo-10@toc@l + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__minus_10 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + +# WAS addis 4, 2, foo@toc@ha+25 +# WAS addi 4, 4, foo@toc@l+25 + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_25 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 + +# WAS addis 4, 2, 1+foo-2@toc@ha+3 +# WAS addi 4, 4, 1+foo-2@toc@l+3 + addi 1, 1, -288 + mflr 4 + std 4, -8(1) + std 3, -16(1) + bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3 + std 3, -24(1) + ld 3, -8(1) + mtlr 3 + ld 4, -24(1) + ld 3, -16(1) + addi 1, 1, 288 +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type bcm_loadtoc__dot_Lfoo_local_target, @function +bcm_loadtoc__dot_Lfoo_local_target: +.Lbcm_loadtoc__dot_Lfoo_local_target: + addis 3, 2, .Lfoo_local_target@toc@ha + addi 3, 3, .Lfoo_local_target@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3: + addis 3, 2, .Lfoo_local_target+1-2+3@toc@ha + addi 3, 3, .Lfoo_local_target+1-2+3@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_10, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_10: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_10: + addis 3, 2, .Lfoo_local_target+10@toc@ha + addi 3, 3, .Lfoo_local_target+10@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_20, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_20: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_20: + addis 3, 2, .Lfoo_local_target+20@toc@ha + addi 3, 3, .Lfoo_local_target+20@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__plus_25, @function +bcm_loadtoc__dot_Lfoo_local_target__plus_25: +.Lbcm_loadtoc__dot_Lfoo_local_target__plus_25: + addis 3, 2, .Lfoo_local_target+25@toc@ha + addi 3, 3, .Lfoo_local_target+25@toc@l + blr +.type bcm_loadtoc__dot_Lfoo_local_target__minus_10, @function +bcm_loadtoc__dot_Lfoo_local_target__minus_10: +.Lbcm_loadtoc__dot_Lfoo_local_target__minus_10: + addis 3, 2, .Lfoo_local_target-10@toc@ha + addi 3, 3, .Lfoo_local_target-10@toc@l + blr +.LBORINGSSL_external_toc: +.quad .TOC.-.LBORINGSSL_external_toc +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s b/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s new file mode 100644 index 00000000..2d313635 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-BSS/in.s @@ -0,0 +1,33 @@ + .text + movq %rax, %rax + + # BSS declarations emit accessors. + .comm aes_128_ctr_generic_storage,64,32 + .lcomm aes_128_ctr_generic_storage2,64,32 + + # BSS symbols may also be emitted in .bss sections. + .section .bss,"awT",@nobits + .align 4 + .globl x + .type x, @object + .size x, 4 +x: + .zero 4 +.Llocal: + .quad 0 + .size .Llocal, 4 + + # .bss handling is terminated by a .text directive. + .text + .section .bss,"awT",@nobits +y: + .quad 0 + + # Or a .section directive. + .section .rodata + .quad 0 + + # Or the end of the file. + .section .bss,"awT",@nobits +z: + .quad 0 diff --git a/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s b/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s new file mode 100644 index 00000000..5c576d95 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-BSS/out.s @@ -0,0 +1,143 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .text + movq %rax, %rax + + # BSS declarations emit accessors. + .comm aes_128_ctr_generic_storage,64,32 + .lcomm aes_128_ctr_generic_storage2,64,32 + + # BSS symbols may also be emitted in .bss sections. + .section .bss,"awT",@nobits + .align 4 + .globl x + .type x, @object + .size x, 4 +x: +.Lx_local_target: + + .zero 4 +.Llocal: + .quad 0 + .size .Llocal, 4 + + # .bss handling is terminated by a .text directive. + .text + .section .bss,"awT",@nobits +y: +.Ly_local_target: + + .quad 0 + + # Or a .section directive. +# WAS .section .rodata +.text + .quad 0 + + # Or the end of the file. + .section .bss,"awT",@nobits +z: +.Lz_local_target: + + .quad 0 +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type aes_128_ctr_generic_storage_bss_get, @function +aes_128_ctr_generic_storage_bss_get: + leaq aes_128_ctr_generic_storage(%rip), %rax + ret +.type aes_128_ctr_generic_storage2_bss_get, @function +aes_128_ctr_generic_storage2_bss_get: + leaq aes_128_ctr_generic_storage2(%rip), %rax + ret +.type x_bss_get, @function +x_bss_get: + leaq .Lx_local_target(%rip), %rax + ret +.type y_bss_get, @function +y_bss_get: + leaq .Ly_local_target(%rip), %rax + ret +.type z_bss_get, @function +z_bss_get: + leaq .Lz_local_target(%rip), %rax + ret +.type OPENSSL_ia32cap_get, @function +OPENSSL_ia32cap_get: + leaq OPENSSL_ia32cap_P(%rip), %rax + ret +.extern OPENSSL_ia32cap_P +.type OPENSSL_ia32cap_addr_delta, @object +.size OPENSSL_ia32cap_addr_delta, 8 +OPENSSL_ia32cap_addr_delta: +.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s b/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s new file mode 100644 index 00000000..89e8aafa --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s @@ -0,0 +1,46 @@ + # Most instructions and lines should pass unaltered. This is made up of + # copy-and-pasted bits of compiler output and likely does not actually + # run. + .file "bcm.c" + .text + + .type foo, @function + .globl foo +foo: + .file 1 "../foo/bar.c" + .loc 1 2 3 + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + .cfi_adjust_cfa_offset 32*5+8 + movq %rsp, %rbp + movq %rdi, -24(%rbp) + movq -24(%rbp), %rax + .loc 1 168 0 is_stmt 0 discriminator 1 + cmpq -8(%rbp), %rax + jmpq *%rax + movdqa %xmm3,%xmm10 + psrlq $1,%xmm3 + pxor %xmm6,%xmm5 + pxor %xmm4,%xmm3 + pand %xmm7,%xmm5 + pand %xmm7,%xmm3 + pxor %xmm5,%xmm6 + paddd 112(%r11),%xmm15 + vmovdqa %xmm0,%xmm5 + vpunpckhqdq %xmm0,%xmm0,%xmm3 + vpxor %xmm0,%xmm3,%xmm3 + vpclmulqdq $0x11,%xmm2,%xmm0,%xmm1 + vpclmulqdq $0x00,%xmm2,%xmm0,%xmm0 + vpclmulqdq $0x00,%xmm6,%xmm3,%xmm3 + vpxor %xmm0,%xmm1,%xmm4 + vpxor %xmm4,%xmm3,%xmm3 + vmovdqu8 %ymm1,%ymm6{%k1}{z} + vmovdqu8 %ymm2,%ymm4{%k3} + .byte 0xf3,0xc3 + movq %rax, %rbx # Comments can be on the same line as an instruction. +.L3: # Or on the same line as a label. +.L4: .L5: movq %rbx, %rax # This is also legal. +.size foo, .-foo +.type foo, @function diff --git a/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s b/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s new file mode 100644 index 00000000..02a60256 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s @@ -0,0 +1,133 @@ +.text +.file 2 "inserted_by_delocate.c" +.loc 2 1 0 +BORINGSSL_bcm_text_start: + # Most instructions and lines should pass unaltered. This is made up of + # copy-and-pasted bits of compiler output and likely does not actually + # run. + .file "bcm.c" + .text + + .type foo, @function + .globl foo +.Lfoo_local_target: +foo: + .file 1 "../foo/bar.c" + .loc 1 2 3 + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + .cfi_adjust_cfa_offset 32*5+8 + movq %rsp, %rbp + movq %rdi, -24(%rbp) + movq -24(%rbp), %rax + .loc 1 168 0 is_stmt 0 discriminator 1 + cmpq -8(%rbp), %rax + jmpq *%rax + movdqa %xmm3,%xmm10 + psrlq $1,%xmm3 + pxor %xmm6,%xmm5 + pxor %xmm4,%xmm3 + pand %xmm7,%xmm5 + pand %xmm7,%xmm3 + pxor %xmm5,%xmm6 + paddd 112(%r11),%xmm15 + vmovdqa %xmm0,%xmm5 + vpunpckhqdq %xmm0,%xmm0,%xmm3 + vpxor %xmm0,%xmm3,%xmm3 + vpclmulqdq $0x11,%xmm2,%xmm0,%xmm1 + vpclmulqdq $0x00,%xmm2,%xmm0,%xmm0 + vpclmulqdq $0x00,%xmm6,%xmm3,%xmm3 + vpxor %xmm0,%xmm1,%xmm4 + vpxor %xmm4,%xmm3,%xmm3 + vmovdqu8 %ymm1,%ymm6{%k1}{z} + vmovdqu8 %ymm2,%ymm4{%k3} + .byte 0xf3,0xc3 + movq %rax, %rbx # Comments can be on the same line as an instruction. +.L3: + # Or on the same line as a label. +.L4: +.L5: + movq %rbx, %rax # This is also legal. +.size foo, .-foo +.type foo, @function +.text +.loc 2 2 0 +BORINGSSL_bcm_text_end: +.type OPENSSL_ia32cap_get, @function +OPENSSL_ia32cap_get: + leaq OPENSSL_ia32cap_P(%rip), %rax + ret +.extern OPENSSL_ia32cap_P +.type OPENSSL_ia32cap_addr_delta, @object +.size OPENSSL_ia32cap_addr_delta, 8 +OPENSSL_ia32cap_addr_delta: +.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s new file mode 100644 index 00000000..ccbc0bf3 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s @@ -0,0 +1,47 @@ + .text +foo: + # leaq of OPENSSL_ia32cap_P is supported. + leaq OPENSSL_ia32cap_P(%rip), %r11 + + # As is the equivalent GOTPCREL movq. + movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 + + # And a non-movq instruction via the GOT. + orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 + + # ... which targets the default temp register + orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax + + # Test that GOTPCREL accesses get translated. They are handled + # differently for local and external symbols. + + pushq stderr@GOTPCREL(%rip) + pushq foo@GOTPCREL(%rip) + + movq stderr@GOTPCREL(%rip), %r11 + movq foo@GOTPCREL(%rip), %r11 + + vmovq stderr@GOTPCREL(%rip), %xmm0 + vmovq foo@GOTPCREL(%rip), %xmm0 + + cmoveq stderr@GOTPCREL(%rip), %r11 + cmoveq foo@GOTPCREL(%rip), %r11 + cmovneq stderr@GOTPCREL(%rip), %r11 + cmovneq foo@GOTPCREL(%rip), %r11 + + movsd foo@GOTPCREL(%rip), %xmm0 + vmovsd foo@GOTPCREL(%rip), %xmm0 + + # movsd without arguments should be left as-is. + movsd + + # Synthesized symbols do not use the GOT. + movq BORINGSSL_bcm_text_start@GOTPCREL(%rip), %r11 + movq foobar_bss_get@GOTPCREL(%rip), %r11 + movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11 + + # Transforming moves run the transform in-place after the load. + vpbroadcastq stderr@GOTPCREL(%rip), %xmm0 + vpbroadcastq foo@GOTPCREL(%rip), %xmm0 + +.comm foobar,64,32 diff --git a/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s new file mode 100644 index 00000000..3d421e56 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s @@ -0,0 +1,263 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .text +.Lfoo_local_target: +foo: + # leaq of OPENSSL_ia32cap_P is supported. +# WAS leaq OPENSSL_ia32cap_P(%rip), %r11 + leaq -128(%rsp), %rsp + pushfq + leaq OPENSSL_ia32cap_addr_delta(%rip), %r11 + addq (%r11), %r11 + popfq + leaq 128(%rsp), %rsp + + # As is the equivalent GOTPCREL movq. +# WAS movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 + leaq -128(%rsp), %rsp + pushfq + leaq OPENSSL_ia32cap_addr_delta(%rip), %r12 + addq (%r12), %r12 + popfq + leaq 128(%rsp), %rsp + + # And a non-movq instruction via the GOT. +# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 + leaq -128(%rsp), %rsp + pushq %rax + pushfq + leaq OPENSSL_ia32cap_addr_delta(%rip), %rax + addq (%rax), %rax + popfq + orq %rax, %r12 + popq %rax + leaq 128(%rsp), %rsp + + # ... which targets the default temp register +# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax + leaq -128(%rsp), %rsp + pushq %rbx + pushfq + leaq OPENSSL_ia32cap_addr_delta(%rip), %rbx + addq (%rbx), %rbx + popfq + orq %rbx, %rax + popq %rbx + leaq 128(%rsp), %rsp + + # Test that GOTPCREL accesses get translated. They are handled + # differently for local and external symbols. + +# WAS pushq stderr@GOTPCREL(%rip) + pushq %rax + leaq -128(%rsp), %rsp + pushf + leaq stderr_GOTPCREL_external(%rip), %rax + addq (%rax), %rax + movq (%rax), %rax + popf + leaq 128(%rsp), %rsp + xchg %rax, (%rsp) +# WAS pushq foo@GOTPCREL(%rip) + pushq %rax + leaq .Lfoo_local_target(%rip), %rax + xchg %rax, (%rsp) + +# WAS movq stderr@GOTPCREL(%rip), %r11 + leaq -128(%rsp), %rsp + pushf + leaq stderr_GOTPCREL_external(%rip), %r11 + addq (%r11), %r11 + movq (%r11), %r11 + popf + leaq 128(%rsp), %rsp +# WAS movq foo@GOTPCREL(%rip), %r11 + leaq .Lfoo_local_target(%rip), %r11 + +# WAS vmovq stderr@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + pushf + leaq stderr_GOTPCREL_external(%rip), %rax + addq (%rax), %rax + movq (%rax), %rax + popf + vmovq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp +# WAS vmovq foo@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + leaq .Lfoo_local_target(%rip), %rax + vmovq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp + +# WAS cmoveq stderr@GOTPCREL(%rip), %r11 + jne 999f + leaq -128(%rsp), %rsp + pushf + leaq stderr_GOTPCREL_external(%rip), %r11 + addq (%r11), %r11 + movq (%r11), %r11 + popf + leaq 128(%rsp), %rsp +999: +# WAS cmoveq foo@GOTPCREL(%rip), %r11 + jne 999f + leaq .Lfoo_local_target(%rip), %r11 +999: +# WAS cmovneq stderr@GOTPCREL(%rip), %r11 + je 999f + leaq -128(%rsp), %rsp + pushf + leaq stderr_GOTPCREL_external(%rip), %r11 + addq (%r11), %r11 + movq (%r11), %r11 + popf + leaq 128(%rsp), %rsp +999: +# WAS cmovneq foo@GOTPCREL(%rip), %r11 + je 999f + leaq .Lfoo_local_target(%rip), %r11 +999: + +# WAS movsd foo@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + leaq .Lfoo_local_target(%rip), %rax + movq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp +# WAS vmovsd foo@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + leaq .Lfoo_local_target(%rip), %rax + vmovq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp + + # movsd without arguments should be left as-is. + movsd + + # Synthesized symbols do not use the GOT. +# WAS movq BORINGSSL_bcm_text_start@GOTPCREL(%rip), %r11 + leaq BORINGSSL_bcm_text_start(%rip), %r11 +# WAS movq foobar_bss_get@GOTPCREL(%rip), %r11 + leaq foobar_bss_get(%rip), %r11 +# WAS movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11 + leaq OPENSSL_ia32cap_get(%rip), %r11 + + # Transforming moves run the transform in-place after the load. +# WAS vpbroadcastq stderr@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + pushf + leaq stderr_GOTPCREL_external(%rip), %rax + addq (%rax), %rax + movq (%rax), %rax + popf + vmovq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp + vpbroadcastq %xmm0, %xmm0 +# WAS vpbroadcastq foo@GOTPCREL(%rip), %xmm0 + leaq -128(%rsp), %rsp + pushq %rax + leaq .Lfoo_local_target(%rip), %rax + vmovq %rax, %xmm0 + popq %rax + leaq 128(%rsp), %rsp + vpbroadcastq %xmm0, %xmm0 + +.comm foobar,64,32 +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type foobar_bss_get, @function +foobar_bss_get: + leaq foobar(%rip), %rax + ret +.type stderr_GOTPCREL_external, @object +.size stderr_GOTPCREL_external, 8 +stderr_GOTPCREL_external: + .long stderr@GOTPCREL + .long 0 +.type OPENSSL_ia32cap_get, @function +OPENSSL_ia32cap_get: + leaq OPENSSL_ia32cap_P(%rip), %rax + ret +.extern OPENSSL_ia32cap_P +.type OPENSSL_ia32cap_addr_delta, @object +.size OPENSSL_ia32cap_addr_delta, 8 +OPENSSL_ia32cap_addr_delta: +.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s new file mode 100644 index 00000000..e97b280b --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s @@ -0,0 +1,43 @@ + .type foo, @function + .globl foo +foo: + movq $0, %rax + ret + +bar: + # References to globals must be rewritten to their local targets. + call foo + jmp foo + jbe foo + jne foo + + # Jumps to PLT symbols are rewritten through redirectors. + call memcpy@PLT + jmp memcpy@PLT + jbe memcpy@PLT + + # Jumps to local PLT symbols use their local targets. + call foo@PLT + jmp foo@PLT + jbe foo@PLT + + # Synthesized symbols are treated as local ones. + call OPENSSL_ia32cap_get@PLT + + # References to local labels are left as-is in the first file. +.Llocal_label: + jbe .Llocal_label + leaq .Llocal_label+2048(%rip), %r14 + leaq .Llocal_label+2048+1024(%rip), %r14 + + .section .rodata +.L1: + .quad 42 +.L2: + .quad .L2-.L1 + + # Local labels and their jumps are left alone. + .text + jmp 1f +1: + jmp 1b diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s new file mode 100644 index 00000000..7a5a5510 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s @@ -0,0 +1,12 @@ + # References to local labels are rewrittenn in subsequent files. +.Llocal_label: + jbe .Llocal_label + leaq .Llocal_label+2048(%rip), %r14 + leaq .Llocal_label+2048+1024(%rip), %r14 + + .section .rodata +.L1: + .quad 42 +.L2: + .quad .L2-.L1 + diff --git a/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s new file mode 100644 index 00000000..4a018537 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s @@ -0,0 +1,167 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + .type foo, @function + .globl foo +.Lfoo_local_target: +foo: + movq $0, %rax + ret + +.Lbar_local_target: +bar: + # References to globals must be rewritten to their local targets. +# WAS call foo + call .Lfoo_local_target +# WAS jmp foo + jmp .Lfoo_local_target +# WAS jbe foo + jbe .Lfoo_local_target +# WAS jne foo + jne .Lfoo_local_target + + # Jumps to PLT symbols are rewritten through redirectors. +# WAS call memcpy@PLT + call bcm_redirector_memcpy +# WAS jmp memcpy@PLT + jmp bcm_redirector_memcpy +# WAS jbe memcpy@PLT + jbe bcm_redirector_memcpy + + # Jumps to local PLT symbols use their local targets. +# WAS call foo@PLT + call .Lfoo_local_target +# WAS jmp foo@PLT + jmp .Lfoo_local_target +# WAS jbe foo@PLT + jbe .Lfoo_local_target + + # Synthesized symbols are treated as local ones. +# WAS call OPENSSL_ia32cap_get@PLT + call OPENSSL_ia32cap_get + + # References to local labels are left as-is in the first file. +.Llocal_label: + + jbe .Llocal_label + leaq .Llocal_label+2048(%rip), %r14 + leaq .Llocal_label+2048+1024(%rip), %r14 + +# WAS .section .rodata +.text +.L1: + + .quad 42 +.L2: + + .quad .L2-.L1 + + # Local labels and their jumps are left alone. + .text + jmp 1f +1: + + jmp 1b + # References to local labels are rewrittenn in subsequent files. +.Llocal_label_BCM_1: + +# WAS jbe .Llocal_label + jbe .Llocal_label_BCM_1 +# WAS leaq .Llocal_label+2048(%rip), %r14 + leaq .Llocal_label_BCM_1+2048(%rip), %r14 +# WAS leaq .Llocal_label+2048+1024(%rip), %r14 + leaq .Llocal_label_BCM_1+2048+1024(%rip), %r14 + +# WAS .section .rodata +.text +.L1_BCM_1: + + .quad 42 +.L2_BCM_1: + +# WAS .quad .L2-.L1 + .quad .L2_BCM_1-.L1_BCM_1 + +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type bcm_redirector_memcpy, @function +bcm_redirector_memcpy: + jmp memcpy@PLT +.type OPENSSL_ia32cap_get, @function +OPENSSL_ia32cap_get: + leaq OPENSSL_ia32cap_P(%rip), %rax + ret +.extern OPENSSL_ia32cap_P +.type OPENSSL_ia32cap_addr_delta, @object +.size OPENSSL_ia32cap_addr_delta, 8 +OPENSSL_ia32cap_addr_delta: +.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate/testdata/x86_64-Sections/in.s b/src/util/fipstools/delocate/testdata/x86_64-Sections/in.s new file mode 100644 index 00000000..8358a4c5 --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-Sections/in.s @@ -0,0 +1,36 @@ + # .text stays in .text + .text + movq %rax, %rax + + # -ffunction-sections is undone. + .section .text.foo,"ax",@progbits + .globl foo +foo: + ret + + # .rodata is moved to .text. + .section .rodata + .long 42 + .string "Hello world, esc\ape characters are \"fun\"\\" + + # Compilers sometimes emit extra rodata sections. + .section .rodata.str1.1,"aMS",@progbits,1 + .string "NIST P-256" + .text + + # A number of sections are left alone. + .section .init_array,"aw" + .align 8 + .quad foo + .section .rodata + .align 16 + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x1b35e + .value 0x4 + .long .L1 + .byte 0x8 + .uleb128 0x1 + .long .L2 + .byte 0x1 + .long .L3 diff --git a/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s b/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s new file mode 100644 index 00000000..ba427ade --- /dev/null +++ b/src/util/fipstools/delocate/testdata/x86_64-Sections/out.s @@ -0,0 +1,125 @@ +.text +.file 1 "inserted_by_delocate.c" +.loc 1 1 0 +BORINGSSL_bcm_text_start: + # .text stays in .text + .text + movq %rax, %rax + + # -ffunction-sections is undone. +# WAS .section .text.foo,"ax",@progbits +.text + .globl foo +.Lfoo_local_target: +foo: + ret + + # .rodata is moved to .text. +# WAS .section .rodata +.text + .long 42 + .string "Hello world, esc\ape characters are \"fun\"\\" + + # Compilers sometimes emit extra rodata sections. +# WAS .section .rodata.str1.1,"aMS",@progbits,1 +.text + .string "NIST P-256" + .text + + # A number of sections are left alone. + .section .init_array,"aw" + .align 8 + .quad foo +# WAS .section .rodata +.text + .align 16 + .section .debug_info,"",@progbits +.Ldebug_info0: + + .long 0x1b35e + .value 0x4 + .long .L1 + .byte 0x8 + .uleb128 0x1 + .long .L2 + .byte 0x1 + .long .L3 +.text +.loc 1 2 0 +BORINGSSL_bcm_text_end: +.type OPENSSL_ia32cap_get, @function +OPENSSL_ia32cap_get: + leaq OPENSSL_ia32cap_P(%rip), %rax + ret +.extern OPENSSL_ia32cap_P +.type OPENSSL_ia32cap_addr_delta, @object +.size OPENSSL_ia32cap_addr_delta, 8 +OPENSSL_ia32cap_addr_delta: +.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta +.type BORINGSSL_bcm_text_hash, @object +.size BORINGSSL_bcm_text_hash, 64 +BORINGSSL_bcm_text_hash: +.byte 0xae +.byte 0x2c +.byte 0xea +.byte 0x2a +.byte 0xbd +.byte 0xa6 +.byte 0xf3 +.byte 0xec +.byte 0x97 +.byte 0x7f +.byte 0x9b +.byte 0xf6 +.byte 0x94 +.byte 0x9a +.byte 0xfc +.byte 0x83 +.byte 0x68 +.byte 0x27 +.byte 0xcb +.byte 0xa0 +.byte 0xa0 +.byte 0x9f +.byte 0x6b +.byte 0x6f +.byte 0xde +.byte 0x52 +.byte 0xcd +.byte 0xe2 +.byte 0xcd +.byte 0xff +.byte 0x31 +.byte 0x80 +.byte 0xa2 +.byte 0xd4 +.byte 0xc3 +.byte 0x66 +.byte 0xf +.byte 0xc2 +.byte 0x6a +.byte 0x7b +.byte 0xf4 +.byte 0xbe +.byte 0x39 +.byte 0xa2 +.byte 0xd7 +.byte 0x25 +.byte 0xdb +.byte 0x21 +.byte 0x98 +.byte 0xe9 +.byte 0xd5 +.byte 0x53 +.byte 0xbf +.byte 0x5c +.byte 0x32 +.byte 0x6 +.byte 0x83 +.byte 0x34 +.byte 0xc +.byte 0x65 +.byte 0x89 +.byte 0x52 +.byte 0xbd +.byte 0x1f diff --git a/src/util/fipstools/delocate_test.go b/src/util/fipstools/delocate_test.go deleted file mode 100644 index e0ecc177..00000000 --- a/src/util/fipstools/delocate_test.go +++ /dev/null @@ -1,86 +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. */ - -package main - -import ( - "bytes" - "flag" - "io/ioutil" - "path/filepath" - "testing" -) - -var ( - testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.") - update = flag.Bool("update", false, "If true, update output files rather than compare them.") -) - -type delocateTest struct { - name string - in []string - out string -} - -func (test *delocateTest) Path(file string) string { - return filepath.Join(*testDataDir, test.name, file) -} - -var delocateTests = []delocateTest{ - {"ppc64le-GlobalEntry", []string{"in.s"}, "out.s"}, - {"ppc64le-LoadToR0", []string{"in.s"}, "out.s"}, - {"ppc64le-Sample2", []string{"in.s"}, "out.s"}, - {"ppc64le-Sample", []string{"in.s"}, "out.s"}, - {"ppc64le-TOCWithOffset", []string{"in.s"}, "out.s"}, - {"x86_64-Basic", []string{"in.s"}, "out.s"}, - {"x86_64-BSS", []string{"in.s"}, "out.s"}, - {"x86_64-GOTRewrite", []string{"in.s"}, "out.s"}, - {"x86_64-LabelRewrite", []string{"in1.s", "in2.s"}, "out.s"}, - {"x86_64-Sections", []string{"in.s"}, "out.s"}, -} - -func TestDelocate(t *testing.T) { - for _, test := range delocateTests { - t.Run(test.name, func(t *testing.T) { - var inputs []inputFile - for i, in := range test.in { - inputs = append(inputs, inputFile{ - index: i, - path: test.Path(in), - }) - } - - if err := parseInputs(inputs); err != nil { - t.Fatalf("parseInputs failed: %s", err) - } - - var buf bytes.Buffer - if err := transform(&buf, inputs); err != nil { - t.Fatalf("transform failed: %s", err) - } - - if *update { - ioutil.WriteFile(test.Path(test.out), buf.Bytes(), 0666) - } else { - expected, err := ioutil.ReadFile(test.Path(test.out)) - if err != nil { - t.Fatalf("could not read %q: %s", test.Path(test.out), err) - } - if !bytes.Equal(buf.Bytes(), expected) { - t.Errorf("delocated output differed. Wanted:\n%s\nGot:\n%s\n", expected, buf.Bytes()) - } - } - }) - } -} diff --git a/src/util/fipstools/fipscommon/ar.go b/src/util/fipstools/fipscommon/ar.go new file mode 100644 index 00000000..85b378d6 --- /dev/null +++ b/src/util/fipstools/fipscommon/ar.go @@ -0,0 +1,120 @@ +// 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 fipscommon + +import ( + "bytes" + "errors" + "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 = "!\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:] + if i := bytes.IndexByte(filename, '/'); i < 0 { + return nil, errors.New("ar: unterminated filename in table") + } else { + filename = filename[:i] + } + + name = string(filename) + + default: + name = strings.TrimRight(name, "/") + } + + ret[name] = contents + } + + return ret, nil +} diff --git a/src/util/fipstools/fipscommon/const.go b/src/util/fipstools/fipscommon/const.go new file mode 100644 index 00000000..56934140 --- /dev/null +++ b/src/util/fipstools/fipscommon/const.go @@ -0,0 +1,22 @@ +// 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. */ + +package fipscommon + +// 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{ + 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/src/util/fipstools/inject-hash.go b/src/util/fipstools/inject-hash.go deleted file mode 100644 index 688024d1..00000000 --- a/src/util/fipstools/inject-hash.go +++ /dev/null @@ -1,173 +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. */ - -// inject-hash parses an archive containing a file object file. It finds a FIPS -// module inside that object, calculates its hash and replaces the default hash -// value in the object with the calculated value. -package main - -import ( - "bytes" - "crypto/hmac" - "crypto/sha512" - "debug/elf" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" -) - -func do(outPath, oInput string, arInput string) error { - var objectBytes []byte - if len(arInput) > 0 { - if len(oInput) > 0 { - return fmt.Errorf("-in-archive and -in-object are mutually exclusive") - } - - arFile, err := os.Open(arInput) - if err != nil { - return err - } - defer arFile.Close() - - ar, err := ParseAR(arFile) - if err != nil { - return err - } - - if len(ar) != 1 { - return fmt.Errorf("expected one file in archive, but found %d", len(ar)) - } - - for _, contents := range ar { - objectBytes = contents - } - } else if len(oInput) > 0 { - var err error - if objectBytes, err = ioutil.ReadFile(oInput); err != nil { - return err - } - } else { - return fmt.Errorf("exactly one of -in-archive or -in-object is required") - } - - object, err := elf.NewFile(bytes.NewReader(objectBytes)) - if err != nil { - return errors.New("failed to parse object: " + err.Error()) - } - - // Find the .text section. - - var textSection *elf.Section - var textSectionIndex elf.SectionIndex - for i, section := range object.Sections { - if section.Name == ".text" { - textSectionIndex = elf.SectionIndex(i) - textSection = section - break - } - } - - if textSection == nil { - return errors.New("failed to find .text section in object") - } - - // Find the starting and ending symbols for the module. - - var startSeen, endSeen bool - var start, end uint64 - - symbols, err := object.Symbols() - if err != nil { - return errors.New("failed to parse symbols: " + err.Error()) - } - - for _, symbol := range symbols { - if symbol.Section != textSectionIndex { - continue - } - - switch symbol.Name { - case "BORINGSSL_bcm_text_start": - if startSeen { - return errors.New("duplicate start symbol found") - } - startSeen = true - start = symbol.Value - case "BORINGSSL_bcm_text_end": - if endSeen { - return errors.New("duplicate end symbol found") - } - endSeen = true - end = symbol.Value - default: - continue - } - } - - if !startSeen || !endSeen { - return errors.New("could not find module boundaries in object") - } - - if max := textSection.Size; start > max || start > end || end > max { - return fmt.Errorf("invalid module boundaries: start: %x, end: %x, max: %x", start, end, max) - } - - // Extract the module from the .text section and hash it. - - text := textSection.Open() - if _, err := text.Seek(int64(start), 0); err != nil { - return errors.New("failed to seek to module start in .text: " + err.Error()) - } - moduleText := make([]byte, end-start) - if _, err := io.ReadFull(text, moduleText); err != nil { - return errors.New("failed to read .text: " + err.Error()) - } - - var zeroKey [64]byte - mac := hmac.New(sha512.New, zeroKey[:]) - mac.Write(moduleText) - calculated := mac.Sum(nil) - - // Replace the default hash value in the object with the calculated - // value and write it out. - - offset := bytes.Index(objectBytes, uninitHashValue[:]) - if offset < 0 { - return errors.New("did not find uninitialised hash value in object file") - } - - if bytes.Index(objectBytes[offset+1:], uninitHashValue[:]) >= 0 { - return errors.New("found two occurrences of uninitialised hash value in object file") - } - - copy(objectBytes[offset:], calculated) - - return ioutil.WriteFile(outPath, objectBytes, 0644) -} - -func main() { - arInput := flag.String("in-archive", "", "Path to a .a file") - oInput := flag.String("in-object", "", "Path to a .o file") - outPath := flag.String("o", "", "Path to output object") - - flag.Parse() - - if err := do(*outPath, *oInput, *arInput); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } -} diff --git a/src/util/fipstools/inject-hash/inject-hash.go b/src/util/fipstools/inject-hash/inject-hash.go new file mode 100644 index 00000000..14418a38 --- /dev/null +++ b/src/util/fipstools/inject-hash/inject-hash.go @@ -0,0 +1,175 @@ +// 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. */ + +// inject-hash parses an archive containing a file object file. It finds a FIPS +// module inside that object, calculates its hash and replaces the default hash +// value in the object with the calculated value. +package main + +import ( + "bytes" + "crypto/hmac" + "crypto/sha512" + "debug/elf" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "os" + + "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon" +) + +func do(outPath, oInput string, arInput string) error { + var objectBytes []byte + if len(arInput) > 0 { + if len(oInput) > 0 { + return fmt.Errorf("-in-archive and -in-object are mutually exclusive") + } + + arFile, err := os.Open(arInput) + if err != nil { + return err + } + defer arFile.Close() + + ar, err := fipscommon.ParseAR(arFile) + if err != nil { + return err + } + + if len(ar) != 1 { + return fmt.Errorf("expected one file in archive, but found %d", len(ar)) + } + + for _, contents := range ar { + objectBytes = contents + } + } else if len(oInput) > 0 { + var err error + if objectBytes, err = ioutil.ReadFile(oInput); err != nil { + return err + } + } else { + return fmt.Errorf("exactly one of -in-archive or -in-object is required") + } + + object, err := elf.NewFile(bytes.NewReader(objectBytes)) + if err != nil { + return errors.New("failed to parse object: " + err.Error()) + } + + // Find the .text section. + + var textSection *elf.Section + var textSectionIndex elf.SectionIndex + for i, section := range object.Sections { + if section.Name == ".text" { + textSectionIndex = elf.SectionIndex(i) + textSection = section + break + } + } + + if textSection == nil { + return errors.New("failed to find .text section in object") + } + + // Find the starting and ending symbols for the module. + + var startSeen, endSeen bool + var start, end uint64 + + symbols, err := object.Symbols() + if err != nil { + return errors.New("failed to parse symbols: " + err.Error()) + } + + for _, symbol := range symbols { + if symbol.Section != textSectionIndex { + continue + } + + switch symbol.Name { + case "BORINGSSL_bcm_text_start": + if startSeen { + return errors.New("duplicate start symbol found") + } + startSeen = true + start = symbol.Value + case "BORINGSSL_bcm_text_end": + if endSeen { + return errors.New("duplicate end symbol found") + } + endSeen = true + end = symbol.Value + default: + continue + } + } + + if !startSeen || !endSeen { + return errors.New("could not find module boundaries in object") + } + + if max := textSection.Size; start > max || start > end || end > max { + return fmt.Errorf("invalid module boundaries: start: %x, end: %x, max: %x", start, end, max) + } + + // Extract the module from the .text section and hash it. + + text := textSection.Open() + if _, err := text.Seek(int64(start), 0); err != nil { + return errors.New("failed to seek to module start in .text: " + err.Error()) + } + moduleText := make([]byte, end-start) + if _, err := io.ReadFull(text, moduleText); err != nil { + return errors.New("failed to read .text: " + err.Error()) + } + + var zeroKey [64]byte + mac := hmac.New(sha512.New, zeroKey[:]) + mac.Write(moduleText) + calculated := mac.Sum(nil) + + // Replace the default hash value in the object with the calculated + // value and write it out. + + 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:], fipscommon.UninitHashValue[:]) >= 0 { + return errors.New("found two occurrences of uninitialised hash value in object file") + } + + copy(objectBytes[offset:], calculated) + + return ioutil.WriteFile(outPath, objectBytes, 0644) +} + +func main() { + arInput := flag.String("in-archive", "", "Path to a .a file") + oInput := flag.String("in-object", "", "Path to a .o file") + outPath := flag.String("o", "", "Path to output object") + + flag.Parse() + + if err := do(*outPath, *oInput, *arInput); err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } +} diff --git a/src/util/fipstools/testdata/ppc64le-GlobalEntry/in.s b/src/util/fipstools/testdata/ppc64le-GlobalEntry/in.s deleted file mode 100644 index af1a182c..00000000 --- a/src/util/fipstools/testdata/ppc64le-GlobalEntry/in.s +++ /dev/null @@ -1,9 +0,0 @@ - .text -foo: -.LCF0: -0: - addis 2,12,.TOC.-.LCF0@ha - addi 2,2,.TOC.-.LCF0@l - .localentry foo,.-foo -.LVL0: - bl diff --git a/src/util/fipstools/testdata/ppc64le-GlobalEntry/out.s b/src/util/fipstools/testdata/ppc64le-GlobalEntry/out.s deleted file mode 100644 index 304f697a..00000000 --- a/src/util/fipstools/testdata/ppc64le-GlobalEntry/out.s +++ /dev/null @@ -1,94 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .text -.Lfoo_local_target: -foo: -.LCF0: - -0: - -999: - addis 2, 12, .LBORINGSSL_external_toc-999b@ha - addi 2, 2, .LBORINGSSL_external_toc-999b@l - ld 12, 0(2) - add 2, 2, 12 -# WAS addi 2,2,.TOC.-.LCF0@l - .localentry foo,.-foo -.Lfoo_local_entry: -.LVL0: - - bl -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.LBORINGSSL_external_toc: -.quad .TOC.-.LBORINGSSL_external_toc -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/ppc64le-LoadToR0/in.s b/src/util/fipstools/testdata/ppc64le-LoadToR0/in.s deleted file mode 100644 index 81766dc0..00000000 --- a/src/util/fipstools/testdata/ppc64le-LoadToR0/in.s +++ /dev/null @@ -1,4 +0,0 @@ - .text -foo: - addis 22,2,bar@toc@ha - ld 0,bar@toc@l(22) diff --git a/src/util/fipstools/testdata/ppc64le-LoadToR0/out.s b/src/util/fipstools/testdata/ppc64le-LoadToR0/out.s deleted file mode 100644 index 5fdbeb89..00000000 --- a/src/util/fipstools/testdata/ppc64le-LoadToR0/out.s +++ /dev/null @@ -1,104 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .text -.Lfoo_local_target: -foo: -# WAS addis 22,2,bar@toc@ha -# WAS ld 0,bar@toc@l(22) - addi 1, 1, -288 - mflr 0 - std 0, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc_bar - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 0, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - addi 1, 1, -288 - std 3, -8(1) - mr 3, 0 - ld 0, 0(3) - ld 3, -8(1) - addi 1, 1, 288 -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type bcm_loadtoc_bar, @function -bcm_loadtoc_bar: -.Lbcm_loadtoc_bar: - addis 3, 2, bar@toc@ha - addi 3, 3, bar@toc@l - blr -.LBORINGSSL_external_toc: -.quad .TOC.-.LBORINGSSL_external_toc -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/ppc64le-Sample/in.s b/src/util/fipstools/testdata/ppc64le-Sample/in.s deleted file mode 100644 index 6e7422ab..00000000 --- a/src/util/fipstools/testdata/ppc64le-Sample/in.s +++ /dev/null @@ -1,161 +0,0 @@ - .file "foo.c" - .abiversion 2 - .section ".toc","aw" - .section ".text" - .section .rodata - .align 3 - .type kString, @object - .size kString, 12 -kString: - .string "hello world" - .globl kExportedString - .align 3 - .type kExportedString, @object - .size kExportedString, 26 -kExportedString: - .string "hello world, more visibly" - .align 2 - .type kGiantArray, @object - .size kGiantArray, 400000 -kGiantArray: - .long 1 - .long 0 - .zero 399992 - .lcomm bss,20,4 - .type bss, @object - .align 3 -.LC1: - .string "kString is %p\n" - .align 3 -.LC2: - .string "kExportedString is %p\n" - .align 3 -.LC4: - .string "function is %p\n" - .align 3 -.LC5: - .string "exported_function is %p\n" - .align 3 -.LC7: - .string "&kString[5] is %p\n" - .align 3 -.LC9: - .string "&kGiantArray[0x12345] is %p\n" - .section ".toc","aw" -.LC0: - .quad stderr -.LC3: - .quad kExportedString -.LC6: - .quad exported_function -.LC8: - .quad kString+5 -.LC10: - .quad kGiantArray+298260 - .section ".text" - .align 2 - .type function, @function -function: -0: addis 2,12,.TOC.-0b@ha - addi 2,2,.TOC.-0b@l - .localentry function,.-function - mflr 0 - std 0,16(1) - std 31,-8(1) - stdu 1,-112(1) - mr 31,1 - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC1@toc@ha - addi 4,4,.LC1@toc@l - addis 5,2,kString@toc@ha - addi 5,5,kString@toc@l - bl fprintf - nop - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC2@toc@ha - addi 4,4,.LC2@toc@l - addis 9,2,.LC3@toc@ha - ld 5,.LC3@toc@l(9) - bl fprintf - nop - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC4@toc@ha - addi 4,4,.LC4@toc@l - addis 5,2,function@toc@ha - addi 5,5,function@toc@l - bl fprintf - nop - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC5@toc@ha - addi 4,4,.LC5@toc@l - addis 9,2,.LC6@toc@ha - ld 5,.LC6@toc@l(9) - bl fprintf - nop - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC7@toc@ha - addi 4,4,.LC7@toc@l - addis 9,2,.LC8@toc@ha - ld 5,.LC8@toc@l(9) - bl fprintf - nop - addis 10,2,.LC0@toc@ha - ld 9,.LC0@toc@l(10) - ld 9,0(9) - mr 3,9 - addis 4,2,.LC9@toc@ha - addi 4,4,.LC9@toc@l - addis 9,2,.LC10@toc@ha - ld 5,.LC10@toc@l(9) - bl fprintf - nop - bl exported_function - nop - mr 3,9 - addi 1,31,112 - ld 0,16(1) - mtlr 0 - ld 31,-8(1) - blr - .long 0 - .byte 0,0,0,1,128,1,0,1 - .size function,.-function - .align 2 - .globl exported_function - .type exported_function, @function -exported_function: -0: addis 2,12,.TOC.-0b@ha - addi 2,2,.TOC.-0b@l - .localentry exported_function,.-exported_function - mflr 0 - std 0,16(1) - std 31,-8(1) - stdu 1,-48(1) - mr 31,1 - bl function - mr 3,9 - addi 1,31,48 - ld 0,16(1) - mtlr 0 - ld 31,-8(1) - blr - .long 0 - .byte 0,0,0,1,128,1,0,1 - .size exported_function,.-exported_function - .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" - .section .note.GNU-stack,"",@progbits diff --git a/src/util/fipstools/testdata/ppc64le-Sample/out.s b/src/util/fipstools/testdata/ppc64le-Sample/out.s deleted file mode 100644 index e3d682e5..00000000 --- a/src/util/fipstools/testdata/ppc64le-Sample/out.s +++ /dev/null @@ -1,584 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .file "foo.c" - .abiversion 2 - .section ".toc","aw" -# WAS .section ".text" -.text -# WAS .section .rodata -.text - .align 3 - .type kString, @object - .size kString, 12 -.LkString_local_target: -kString: - .string "hello world" - .globl kExportedString - .align 3 - .type kExportedString, @object - .size kExportedString, 26 -.LkExportedString_local_target: -kExportedString: - .string "hello world, more visibly" - .align 2 - .type kGiantArray, @object - .size kGiantArray, 400000 -.LkGiantArray_local_target: -kGiantArray: - .long 1 - .long 0 - .zero 399992 - .lcomm bss,20,4 - .type bss, @object - .align 3 -.LC1: - - .string "kString is %p\n" - .align 3 -.LC2: - - .string "kExportedString is %p\n" - .align 3 -.LC4: - - .string "function is %p\n" - .align 3 -.LC5: - - .string "exported_function is %p\n" - .align 3 -.LC7: - - .string "&kString[5] is %p\n" - .align 3 -.LC9: - - .string "&kGiantArray[0x12345] is %p\n" - .section ".toc","aw" -.LC0: - - .quad stderr -.LC3: - - .quad kExportedString -.LC6: - - .quad exported_function -.LC8: - - .quad kString+5 -.LC10: - - .quad kGiantArray+298260 -# WAS .section ".text" -.text - .align 2 - .type function, @function -.Lfunction_local_target: -function: -0: -999: - addis 2, 12, .LBORINGSSL_external_toc-999b@ha - addi 2, 2, .LBORINGSSL_external_toc-999b@l - ld 12, 0(2) - add 2, 2, 12 -# WAS addi 2,2,.TOC.-0b@l - .localentry function,.-function -.Lfunction_local_entry: - mflr 0 - std 0,16(1) - std 31,-8(1) - stdu 1,-112(1) - mr 31,1 -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC1@toc@ha -# WAS addi 4,4,.LC1@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC1 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 5,2,kString@toc@ha -# WAS addi 5,5,kString@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LkString_local_target - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC2@toc@ha -# WAS addi 4,4,.LC2@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC2 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 9,2,.LC3@toc@ha -# WAS ld 5,.LC3@toc@l(9) - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC3 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 5, 0(5) -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC4@toc@ha -# WAS addi 4,4,.LC4@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC4 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 5,2,function@toc@ha -# WAS addi 5,5,function@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfunction_local_target - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC5@toc@ha -# WAS addi 4,4,.LC5@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC5 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 9,2,.LC6@toc@ha -# WAS ld 5,.LC6@toc@l(9) - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC6 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 5, 0(5) -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC7@toc@ha -# WAS addi 4,4,.LC7@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC7 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 9,2,.LC8@toc@ha -# WAS ld 5,.LC8@toc@l(9) - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC8 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 5, 0(5) -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS addis 10,2,.LC0@toc@ha -# WAS ld 9,.LC0@toc@l(10) - addi 1, 1, -288 - mflr 9 - std 9, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 9, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 9, 0(9) - ld 9,0(9) - mr 3,9 -# WAS addis 4,2,.LC9@toc@ha -# WAS addi 4,4,.LC9@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC9 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 9,2,.LC10@toc@ha -# WAS ld 5,.LC10@toc@l(9) - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC10 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 5, 0(5) -# WAS bl fprintf - bl bcm_redirector_fprintf - ld 2, 24(1) - nop -# WAS bl exported_function - bl .Lexported_function_local_entry - nop - mr 3,9 - addi 1,31,112 - ld 0,16(1) - mtlr 0 - ld 31,-8(1) - blr - .long 0 - .byte 0,0,0,1,128,1,0,1 - .size function,.-function - .align 2 - .globl exported_function - .type exported_function, @function -.Lexported_function_local_target: -exported_function: -0: -999: - addis 2, 12, .LBORINGSSL_external_toc-999b@ha - addi 2, 2, .LBORINGSSL_external_toc-999b@l - ld 12, 0(2) - add 2, 2, 12 -# WAS addi 2,2,.TOC.-0b@l - .localentry exported_function,.-exported_function -.Lexported_function_local_entry: - mflr 0 - std 0,16(1) - std 31,-8(1) - stdu 1,-48(1) - mr 31,1 -# WAS bl function - bl .Lfunction_local_entry - mr 3,9 - addi 1,31,48 - ld 0,16(1) - mtlr 0 - ld 31,-8(1) - blr - .long 0 - .byte 0,0,0,1,128,1,0,1 - .size exported_function,.-exported_function - .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" - .section .note.GNU-stack,"",@progbits -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.section ".toc", "aw" -.Lredirector_toc_fprintf: -.quad fprintf -.text -.type bcm_redirector_fprintf, @function -bcm_redirector_fprintf: - std 2, 24(1) - addis 12, 2, .Lredirector_toc_fprintf@toc@ha - ld 12, .Lredirector_toc_fprintf@toc@l(12) - mtctr 12 - bctr -.type bss_bss_get, @function -bss_bss_get: - addis 3, 2, bss@toc@ha - addi 3, 3, bss@toc@l - blr -.type bcm_loadtoc__dot_LC0, @function -bcm_loadtoc__dot_LC0: -.Lbcm_loadtoc__dot_LC0: - addis 3, 2, .LC0@toc@ha - addi 3, 3, .LC0@toc@l - blr -.type bcm_loadtoc__dot_LC1, @function -bcm_loadtoc__dot_LC1: -.Lbcm_loadtoc__dot_LC1: - addis 3, 2, .LC1@toc@ha - addi 3, 3, .LC1@toc@l - blr -.type bcm_loadtoc__dot_LC10, @function -bcm_loadtoc__dot_LC10: -.Lbcm_loadtoc__dot_LC10: - addis 3, 2, .LC10@toc@ha - addi 3, 3, .LC10@toc@l - blr -.type bcm_loadtoc__dot_LC2, @function -bcm_loadtoc__dot_LC2: -.Lbcm_loadtoc__dot_LC2: - addis 3, 2, .LC2@toc@ha - addi 3, 3, .LC2@toc@l - blr -.type bcm_loadtoc__dot_LC3, @function -bcm_loadtoc__dot_LC3: -.Lbcm_loadtoc__dot_LC3: - addis 3, 2, .LC3@toc@ha - addi 3, 3, .LC3@toc@l - blr -.type bcm_loadtoc__dot_LC4, @function -bcm_loadtoc__dot_LC4: -.Lbcm_loadtoc__dot_LC4: - addis 3, 2, .LC4@toc@ha - addi 3, 3, .LC4@toc@l - blr -.type bcm_loadtoc__dot_LC5, @function -bcm_loadtoc__dot_LC5: -.Lbcm_loadtoc__dot_LC5: - addis 3, 2, .LC5@toc@ha - addi 3, 3, .LC5@toc@l - blr -.type bcm_loadtoc__dot_LC6, @function -bcm_loadtoc__dot_LC6: -.Lbcm_loadtoc__dot_LC6: - addis 3, 2, .LC6@toc@ha - addi 3, 3, .LC6@toc@l - blr -.type bcm_loadtoc__dot_LC7, @function -bcm_loadtoc__dot_LC7: -.Lbcm_loadtoc__dot_LC7: - addis 3, 2, .LC7@toc@ha - addi 3, 3, .LC7@toc@l - blr -.type bcm_loadtoc__dot_LC8, @function -bcm_loadtoc__dot_LC8: -.Lbcm_loadtoc__dot_LC8: - addis 3, 2, .LC8@toc@ha - addi 3, 3, .LC8@toc@l - blr -.type bcm_loadtoc__dot_LC9, @function -bcm_loadtoc__dot_LC9: -.Lbcm_loadtoc__dot_LC9: - addis 3, 2, .LC9@toc@ha - addi 3, 3, .LC9@toc@l - blr -.type bcm_loadtoc__dot_Lfunction_local_target, @function -bcm_loadtoc__dot_Lfunction_local_target: -.Lbcm_loadtoc__dot_Lfunction_local_target: - addis 3, 2, .Lfunction_local_target@toc@ha - addi 3, 3, .Lfunction_local_target@toc@l - blr -.type bcm_loadtoc__dot_LkString_local_target, @function -bcm_loadtoc__dot_LkString_local_target: -.Lbcm_loadtoc__dot_LkString_local_target: - addis 3, 2, .LkString_local_target@toc@ha - addi 3, 3, .LkString_local_target@toc@l - blr -.LBORINGSSL_external_toc: -.quad .TOC.-.LBORINGSSL_external_toc -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/ppc64le-Sample2/in.s b/src/util/fipstools/testdata/ppc64le-Sample2/in.s deleted file mode 100644 index eb856269..00000000 --- a/src/util/fipstools/testdata/ppc64le-Sample2/in.s +++ /dev/null @@ -1,226 +0,0 @@ - .file "foo.c" - .abiversion 2 - .section ".toc","aw" - .section ".text" - .section ".toc","aw" -.LC0: - .quad stderr -.LC3: - .quad kExportedString -.LC6: - .quad exported_function - .section ".text" - .align 2 - .p2align 4,,15 - .globl exported_function - .type exported_function, @function -exported_function: -0: addis 2,12,.TOC.-0b@ha - addi 2,2,.TOC.-0b@l - .localentry exported_function,.-exported_function - mflr 0 - std 19,-104(1) - std 20,-96(1) - std 21,-88(1) - std 22,-80(1) - addis 21,2,.LC1@toc@ha - addis 22,2,.LC2@toc@ha - std 23,-72(1) - std 24,-64(1) - addis 23,2,.LC4@toc@ha - addis 24,2,function@toc@ha - std 25,-56(1) - std 26,-48(1) - addis 25,2,.LC5@toc@ha - addis 26,2,.LC7@toc@ha - std 27,-40(1) - std 28,-32(1) - addis 28,2,.LC8@toc@ha - addi 21,21,.LC1@toc@l - std 29,-24(1) - std 30,-16(1) - addis 29,2,.LANCHOR0@toc@ha - addi 22,22,.LC2@toc@l - std 31,-8(1) - std 0,16(1) - addi 29,29,.LANCHOR0@toc@l - addi 23,23,.LC4@toc@l - stdu 1,-208(1) - addis 31,2,.LC0@toc@ha # gpr load fusion, type long - ld 31,.LC0@toc@l(31) - addis 19,2,.LC3@toc@ha # gpr load fusion, type long - ld 19,.LC3@toc@l(19) - addis 30,29,0x5 - addi 24,24,function@toc@l - addis 20,2,.LC6@toc@ha # gpr load fusion, type long - ld 20,.LC6@toc@l(20) - addi 25,25,.LC5@toc@l - addi 26,26,.LC7@toc@l - addi 27,29,5 - addi 28,28,.LC8@toc@l - addi 30,30,-29404 - .p2align 4,,15 -.L2: - ld 3,0(31) - mr 5,21 - mr 6,29 - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - mr 5,22 - mr 6,19 - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - mr 5,23 - mr 6,24 - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - mr 5,25 - mr 6,20 - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - mr 5,26 - mr 6,27 - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - li 4,1 - mr 5,28 - mr 6,30 - bl __fprintf_chk - nop - b .L2 - .long 0 - .byte 0,0,0,1,128,13,0,0 - .size exported_function,.-exported_function - .section ".toc","aw" - .set .LC11,.LC0 - .set .LC12,.LC3 - .set .LC13,.LC6 - .section ".text" - .align 2 - .p2align 4,,15 - .type function, @function -function: -0: addis 2,12,.TOC.-0b@ha - addi 2,2,.TOC.-0b@l - .localentry function,.-function - mflr 0 - std 31,-8(1) - addis 31,2,.LC11@toc@ha # gpr load fusion, type long - ld 31,.LC11@toc@l(31) - addis 5,2,.LC1@toc@ha - std 30,-16(1) - addis 30,2,.LANCHOR0@toc@ha - addi 5,5,.LC1@toc@l - addi 30,30,.LANCHOR0@toc@l - li 4,1 - mr 6,30 - std 0,16(1) - stdu 1,-112(1) - ld 3,0(31) - bl __fprintf_chk - nop - addis 6,2,.LC12@toc@ha # gpr load fusion, type long - ld 6,.LC12@toc@l(6) - ld 3,0(31) - addis 5,2,.LC2@toc@ha - li 4,1 - addi 5,5,.LC2@toc@l - bl __fprintf_chk - nop - ld 3,0(31) - addis 5,2,.LC4@toc@ha - addis 6,2,function@toc@ha - addi 5,5,.LC4@toc@l - addi 6,6,function@toc@l - li 4,1 - bl __fprintf_chk - nop - addis 6,2,.LC13@toc@ha # gpr load fusion, type long - ld 6,.LC13@toc@l(6) - ld 3,0(31) - addis 5,2,.LC5@toc@ha - li 4,1 - addi 5,5,.LC5@toc@l - bl __fprintf_chk - nop - ld 3,0(31) - addis 5,2,.LC7@toc@ha - addi 6,30,5 - addi 5,5,.LC7@toc@l - li 4,1 - bl __fprintf_chk - nop - ld 3,0(31) - addis 6,30,0x5 - addis 5,2,.LC8@toc@ha - li 4,1 - addi 5,5,.LC8@toc@l - addi 6,6,-29404 - bl __fprintf_chk - nop - bl exported_function - nop - addi 1,1,112 - ld 0,16(1) - ld 30,-16(1) - ld 31,-8(1) - mtlr 0 - blr - .long 0 - .byte 0,0,0,1,128,2,0,0 - .size function,.-function - .globl kExportedString - .section .rodata - .align 4 - .set .LANCHOR0,. + 0 - .type kString, @object - .size kString, 12 -kString: - .string "hello world" - .zero 4 - .type kGiantArray, @object - .size kGiantArray, 400000 -kGiantArray: - .long 1 - .long 0 - .zero 399992 - .type kExportedString, @object - .size kExportedString, 26 -kExportedString: - .string "hello world, more visibly" - .section .rodata.str1.8,"aMS",@progbits,1 - .align 3 -.LC1: - .string "kString is %p\n" - .zero 1 -.LC2: - .string "kExportedString is %p\n" - .zero 1 -.LC4: - .string "function is %p\n" -.LC5: - .string "exported_function is %p\n" - .zero 7 -.LC7: - .string "&kString[5] is %p\n" - .zero 5 -.LC8: - .string "&kGiantArray[0x12345] is %p\n" - .section ".bss" - .align 2 - .type bss, @object - .size bss, 20 -bss: - .zero 20 - .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" - .section .note.GNU-stack,"",@progbits diff --git a/src/util/fipstools/testdata/ppc64le-Sample2/out.s b/src/util/fipstools/testdata/ppc64le-Sample2/out.s deleted file mode 100644 index 54cbd6f8..00000000 --- a/src/util/fipstools/testdata/ppc64le-Sample2/out.s +++ /dev/null @@ -1,709 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .file "foo.c" - .abiversion 2 - .section ".toc","aw" -# WAS .section ".text" -.text - .section ".toc","aw" -.LC0: - - .quad stderr -.LC3: - - .quad kExportedString -.LC6: - - .quad exported_function -# WAS .section ".text" -.text - .align 2 - .p2align 4,,15 - .globl exported_function - .type exported_function, @function -.Lexported_function_local_target: -exported_function: -0: -999: - addis 2, 12, .LBORINGSSL_external_toc-999b@ha - addi 2, 2, .LBORINGSSL_external_toc-999b@l - ld 12, 0(2) - add 2, 2, 12 -# WAS addi 2,2,.TOC.-0b@l - .localentry exported_function,.-exported_function -.Lexported_function_local_entry: - mflr 0 - std 19,-104(1) - std 20,-96(1) - std 21,-88(1) - std 22,-80(1) -# WAS addis 21,2,.LC1@toc@ha -# WAS addis 22,2,.LC2@toc@ha - std 23,-72(1) - std 24,-64(1) -# WAS addis 23,2,.LC4@toc@ha -# WAS addis 24,2,function@toc@ha - std 25,-56(1) - std 26,-48(1) -# WAS addis 25,2,.LC5@toc@ha -# WAS addis 26,2,.LC7@toc@ha - std 27,-40(1) - std 28,-32(1) -# WAS addis 28,2,.LC8@toc@ha -# WAS addi 21,21,.LC1@toc@l - addi 1, 1, -288 - mflr 21 - std 21, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC1 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 21, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - std 29,-24(1) - std 30,-16(1) -# WAS addis 29,2,.LANCHOR0@toc@ha -# WAS addi 22,22,.LC2@toc@l - addi 1, 1, -288 - mflr 22 - std 22, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC2 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 22, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - std 31,-8(1) - std 0,16(1) -# WAS addi 29,29,.LANCHOR0@toc@l - addi 1, 1, -288 - mflr 29 - std 29, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LANCHOR0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 29, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addi 23,23,.LC4@toc@l - addi 1, 1, -288 - mflr 23 - std 23, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC4 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 23, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - stdu 1,-208(1) -# WAS addis 31,2,.LC0@toc@ha # gpr load fusion, type long -# WAS ld 31,.LC0@toc@l(31) - addi 1, 1, -288 - mflr 31 - std 31, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 31, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 31, 0(31) -# WAS addis 19,2,.LC3@toc@ha # gpr load fusion, type long -# WAS ld 19,.LC3@toc@l(19) - addi 1, 1, -288 - mflr 19 - std 19, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC3 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 19, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 19, 0(19) - addis 30,29,0x5 -# WAS addi 24,24,function@toc@l - addi 1, 1, -288 - mflr 24 - std 24, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfunction_local_target - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 24, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addis 20,2,.LC6@toc@ha # gpr load fusion, type long -# WAS ld 20,.LC6@toc@l(20) - addi 1, 1, -288 - mflr 20 - std 20, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC6 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 20, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 20, 0(20) -# WAS addi 25,25,.LC5@toc@l - addi 1, 1, -288 - mflr 25 - std 25, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC5 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 25, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addi 26,26,.LC7@toc@l - addi 1, 1, -288 - mflr 26 - std 26, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC7 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 26, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - addi 27,29,5 -# WAS addi 28,28,.LC8@toc@l - addi 1, 1, -288 - mflr 28 - std 28, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC8 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 28, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - addi 30,30,-29404 - .p2align 4,,15 -.L2: - - ld 3,0(31) - mr 5,21 - mr 6,29 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - mr 5,22 - mr 6,19 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - mr 5,23 - mr 6,24 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - mr 5,25 - mr 6,20 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - mr 5,26 - mr 6,27 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - li 4,1 - mr 5,28 - mr 6,30 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - b .L2 - .long 0 - .byte 0,0,0,1,128,13,0,0 - .size exported_function,.-exported_function - .section ".toc","aw" - .set .LC11,.LC0 - .set .LC12,.LC3 - .set .LC13,.LC6 -# WAS .section ".text" -.text - .align 2 - .p2align 4,,15 - .type function, @function -.Lfunction_local_target: -function: -0: -999: - addis 2, 12, .LBORINGSSL_external_toc-999b@ha - addi 2, 2, .LBORINGSSL_external_toc-999b@l - ld 12, 0(2) - add 2, 2, 12 -# WAS addi 2,2,.TOC.-0b@l - .localentry function,.-function -.Lfunction_local_entry: - mflr 0 - std 31,-8(1) -# WAS addis 31,2,.LC11@toc@ha # gpr load fusion, type long -# WAS ld 31,.LC11@toc@l(31) - addi 1, 1, -288 - mflr 31 - std 31, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC11 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 31, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 31, 0(31) -# WAS addis 5,2,.LC1@toc@ha - std 30,-16(1) -# WAS addis 30,2,.LANCHOR0@toc@ha -# WAS addi 5,5,.LC1@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC1 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addi 30,30,.LANCHOR0@toc@l - addi 1, 1, -288 - mflr 30 - std 30, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LANCHOR0 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 30, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - li 4,1 - mr 6,30 - std 0,16(1) - stdu 1,-112(1) - ld 3,0(31) -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop -# WAS addis 6,2,.LC12@toc@ha # gpr load fusion, type long -# WAS ld 6,.LC12@toc@l(6) - addi 1, 1, -288 - mflr 6 - std 6, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC12 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 6, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 6, 0(6) - ld 3,0(31) -# WAS addis 5,2,.LC2@toc@ha - li 4,1 -# WAS addi 5,5,.LC2@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC2 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) -# WAS addis 5,2,.LC4@toc@ha -# WAS addis 6,2,function@toc@ha -# WAS addi 5,5,.LC4@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC4 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS addi 6,6,function@toc@l - addi 1, 1, -288 - mflr 6 - std 6, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfunction_local_target - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 6, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop -# WAS addis 6,2,.LC13@toc@ha # gpr load fusion, type long -# WAS ld 6,.LC13@toc@l(6) - addi 1, 1, -288 - mflr 6 - std 6, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC13 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 6, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 6, 0(6) - ld 3,0(31) -# WAS addis 5,2,.LC5@toc@ha - li 4,1 -# WAS addi 5,5,.LC5@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC5 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) -# WAS addis 5,2,.LC7@toc@ha - addi 6,30,5 -# WAS addi 5,5,.LC7@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC7 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - li 4,1 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop - ld 3,0(31) - addis 6,30,0x5 -# WAS addis 5,2,.LC8@toc@ha - li 4,1 -# WAS addi 5,5,.LC8@toc@l - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_LC8 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - addi 6,6,-29404 -# WAS bl __fprintf_chk - bl bcm_redirector___fprintf_chk - ld 2, 24(1) - nop -# WAS bl exported_function - bl .Lexported_function_local_entry - nop - addi 1,1,112 - ld 0,16(1) - ld 30,-16(1) - ld 31,-8(1) - mtlr 0 - blr - .long 0 - .byte 0,0,0,1,128,2,0,0 - .size function,.-function - .globl kExportedString -# WAS .section .rodata -.text - .align 4 - .set .LANCHOR0,. + 0 - .type kString, @object - .size kString, 12 -.LkString_local_target: -kString: - .string "hello world" - .zero 4 - .type kGiantArray, @object - .size kGiantArray, 400000 -.LkGiantArray_local_target: -kGiantArray: - .long 1 - .long 0 - .zero 399992 - .type kExportedString, @object - .size kExportedString, 26 -.LkExportedString_local_target: -kExportedString: - .string "hello world, more visibly" -# WAS .section .rodata.str1.8,"aMS",@progbits,1 -.text - .align 3 -.LC1: - - .string "kString is %p\n" - .zero 1 -.LC2: - - .string "kExportedString is %p\n" - .zero 1 -.LC4: - - .string "function is %p\n" -.LC5: - - .string "exported_function is %p\n" - .zero 7 -.LC7: - - .string "&kString[5] is %p\n" - .zero 5 -.LC8: - - .string "&kGiantArray[0x12345] is %p\n" - .section ".bss" - .align 2 - .type bss, @object - .size bss, 20 -bss: -.Lbss_local_target: - - .zero 20 - .ident "GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2" - .section .note.GNU-stack,"",@progbits -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.section ".toc", "aw" -.Lredirector_toc___fprintf_chk: -.quad __fprintf_chk -.text -.type bcm_redirector___fprintf_chk, @function -bcm_redirector___fprintf_chk: - std 2, 24(1) - addis 12, 2, .Lredirector_toc___fprintf_chk@toc@ha - ld 12, .Lredirector_toc___fprintf_chk@toc@l(12) - mtctr 12 - bctr -.type bss_bss_get, @function -bss_bss_get: - addis 3, 2, .Lbss_local_target@toc@ha - addi 3, 3, .Lbss_local_target@toc@l - blr -.type bcm_loadtoc__dot_LANCHOR0, @function -bcm_loadtoc__dot_LANCHOR0: -.Lbcm_loadtoc__dot_LANCHOR0: - addis 3, 2, .LANCHOR0@toc@ha - addi 3, 3, .LANCHOR0@toc@l - blr -.type bcm_loadtoc__dot_LC0, @function -bcm_loadtoc__dot_LC0: -.Lbcm_loadtoc__dot_LC0: - addis 3, 2, .LC0@toc@ha - addi 3, 3, .LC0@toc@l - blr -.type bcm_loadtoc__dot_LC1, @function -bcm_loadtoc__dot_LC1: -.Lbcm_loadtoc__dot_LC1: - addis 3, 2, .LC1@toc@ha - addi 3, 3, .LC1@toc@l - blr -.type bcm_loadtoc__dot_LC11, @function -bcm_loadtoc__dot_LC11: -.Lbcm_loadtoc__dot_LC11: - addis 3, 2, .LC11@toc@ha - addi 3, 3, .LC11@toc@l - blr -.type bcm_loadtoc__dot_LC12, @function -bcm_loadtoc__dot_LC12: -.Lbcm_loadtoc__dot_LC12: - addis 3, 2, .LC12@toc@ha - addi 3, 3, .LC12@toc@l - blr -.type bcm_loadtoc__dot_LC13, @function -bcm_loadtoc__dot_LC13: -.Lbcm_loadtoc__dot_LC13: - addis 3, 2, .LC13@toc@ha - addi 3, 3, .LC13@toc@l - blr -.type bcm_loadtoc__dot_LC2, @function -bcm_loadtoc__dot_LC2: -.Lbcm_loadtoc__dot_LC2: - addis 3, 2, .LC2@toc@ha - addi 3, 3, .LC2@toc@l - blr -.type bcm_loadtoc__dot_LC3, @function -bcm_loadtoc__dot_LC3: -.Lbcm_loadtoc__dot_LC3: - addis 3, 2, .LC3@toc@ha - addi 3, 3, .LC3@toc@l - blr -.type bcm_loadtoc__dot_LC4, @function -bcm_loadtoc__dot_LC4: -.Lbcm_loadtoc__dot_LC4: - addis 3, 2, .LC4@toc@ha - addi 3, 3, .LC4@toc@l - blr -.type bcm_loadtoc__dot_LC5, @function -bcm_loadtoc__dot_LC5: -.Lbcm_loadtoc__dot_LC5: - addis 3, 2, .LC5@toc@ha - addi 3, 3, .LC5@toc@l - blr -.type bcm_loadtoc__dot_LC6, @function -bcm_loadtoc__dot_LC6: -.Lbcm_loadtoc__dot_LC6: - addis 3, 2, .LC6@toc@ha - addi 3, 3, .LC6@toc@l - blr -.type bcm_loadtoc__dot_LC7, @function -bcm_loadtoc__dot_LC7: -.Lbcm_loadtoc__dot_LC7: - addis 3, 2, .LC7@toc@ha - addi 3, 3, .LC7@toc@l - blr -.type bcm_loadtoc__dot_LC8, @function -bcm_loadtoc__dot_LC8: -.Lbcm_loadtoc__dot_LC8: - addis 3, 2, .LC8@toc@ha - addi 3, 3, .LC8@toc@l - blr -.type bcm_loadtoc__dot_Lfunction_local_target, @function -bcm_loadtoc__dot_Lfunction_local_target: -.Lbcm_loadtoc__dot_Lfunction_local_target: - addis 3, 2, .Lfunction_local_target@toc@ha - addi 3, 3, .Lfunction_local_target@toc@l - blr -.LBORINGSSL_external_toc: -.quad .TOC.-.LBORINGSSL_external_toc -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s b/src/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s deleted file mode 100644 index 94ea2111..00000000 --- a/src/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s +++ /dev/null @@ -1,23 +0,0 @@ - .text -foo: - # TOC references may have offsets. - addis 3, 2, 5+foo@toc@ha - addi 3, 3, 10+foo@toc@l - - addis 3, 2, 15+foo@toc@ha - addi 3, 3, 20+foo@toc@l - - addis 4, 2, foo@toc@ha - addi 4, 4, foo@toc@l - - addis 5, 2, 5+foo@toc@ha - ld 5, 10+foo@toc@l(5) - - addis 4, 2, foo-10@toc@ha - addi 4, 4, foo-10@toc@l - - addis 4, 2, foo@toc@ha+25 - addi 4, 4, foo@toc@l+25 - - addis 4, 2, 1+foo-2@toc@ha+3 - addi 4, 4, 1+foo-2@toc@l+3 diff --git a/src/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s b/src/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s deleted file mode 100644 index 2fff0efb..00000000 --- a/src/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s +++ /dev/null @@ -1,210 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .text -.Lfoo_local_target: -foo: - # TOC references may have offsets. -# WAS addis 3, 2, 5+foo@toc@ha -# WAS addi 3, 3, 10+foo@toc@l - addi 1, 1, -288 - mflr 3 - std 3, -8(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 3, -24(1) - addi 1, 1, 288 - -# WAS addis 3, 2, 15+foo@toc@ha -# WAS addi 3, 3, 20+foo@toc@l - addi 1, 1, -288 - mflr 3 - std 3, -8(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_20 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 3, -24(1) - addi 1, 1, 288 - -# WAS addis 4, 2, foo@toc@ha -# WAS addi 4, 4, foo@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - -# WAS addis 5, 2, 5+foo@toc@ha -# WAS ld 5, 10+foo@toc@l(5) - addi 1, 1, -288 - mflr 5 - std 5, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_10 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 5, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - ld 5, 0(5) - -# WAS addis 4, 2, foo-10@toc@ha -# WAS addi 4, 4, foo-10@toc@l - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__minus_10 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - -# WAS addis 4, 2, foo@toc@ha+25 -# WAS addi 4, 4, foo@toc@l+25 - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_25 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 - -# WAS addis 4, 2, 1+foo-2@toc@ha+3 -# WAS addi 4, 4, 1+foo-2@toc@l+3 - addi 1, 1, -288 - mflr 4 - std 4, -8(1) - std 3, -16(1) - bl .Lbcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3 - std 3, -24(1) - ld 3, -8(1) - mtlr 3 - ld 4, -24(1) - ld 3, -16(1) - addi 1, 1, 288 -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type bcm_loadtoc__dot_Lfoo_local_target, @function -bcm_loadtoc__dot_Lfoo_local_target: -.Lbcm_loadtoc__dot_Lfoo_local_target: - addis 3, 2, .Lfoo_local_target@toc@ha - addi 3, 3, .Lfoo_local_target@toc@l - blr -.type bcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3, @function -bcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3: -.Lbcm_loadtoc__dot_Lfoo_local_target__plus_1_minus_2_plus_3: - addis 3, 2, .Lfoo_local_target+1-2+3@toc@ha - addi 3, 3, .Lfoo_local_target+1-2+3@toc@l - blr -.type bcm_loadtoc__dot_Lfoo_local_target__plus_10, @function -bcm_loadtoc__dot_Lfoo_local_target__plus_10: -.Lbcm_loadtoc__dot_Lfoo_local_target__plus_10: - addis 3, 2, .Lfoo_local_target+10@toc@ha - addi 3, 3, .Lfoo_local_target+10@toc@l - blr -.type bcm_loadtoc__dot_Lfoo_local_target__plus_20, @function -bcm_loadtoc__dot_Lfoo_local_target__plus_20: -.Lbcm_loadtoc__dot_Lfoo_local_target__plus_20: - addis 3, 2, .Lfoo_local_target+20@toc@ha - addi 3, 3, .Lfoo_local_target+20@toc@l - blr -.type bcm_loadtoc__dot_Lfoo_local_target__plus_25, @function -bcm_loadtoc__dot_Lfoo_local_target__plus_25: -.Lbcm_loadtoc__dot_Lfoo_local_target__plus_25: - addis 3, 2, .Lfoo_local_target+25@toc@ha - addi 3, 3, .Lfoo_local_target+25@toc@l - blr -.type bcm_loadtoc__dot_Lfoo_local_target__minus_10, @function -bcm_loadtoc__dot_Lfoo_local_target__minus_10: -.Lbcm_loadtoc__dot_Lfoo_local_target__minus_10: - addis 3, 2, .Lfoo_local_target-10@toc@ha - addi 3, 3, .Lfoo_local_target-10@toc@l - blr -.LBORINGSSL_external_toc: -.quad .TOC.-.LBORINGSSL_external_toc -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/x86_64-BSS/in.s b/src/util/fipstools/testdata/x86_64-BSS/in.s deleted file mode 100644 index 2d313635..00000000 --- a/src/util/fipstools/testdata/x86_64-BSS/in.s +++ /dev/null @@ -1,33 +0,0 @@ - .text - movq %rax, %rax - - # BSS declarations emit accessors. - .comm aes_128_ctr_generic_storage,64,32 - .lcomm aes_128_ctr_generic_storage2,64,32 - - # BSS symbols may also be emitted in .bss sections. - .section .bss,"awT",@nobits - .align 4 - .globl x - .type x, @object - .size x, 4 -x: - .zero 4 -.Llocal: - .quad 0 - .size .Llocal, 4 - - # .bss handling is terminated by a .text directive. - .text - .section .bss,"awT",@nobits -y: - .quad 0 - - # Or a .section directive. - .section .rodata - .quad 0 - - # Or the end of the file. - .section .bss,"awT",@nobits -z: - .quad 0 diff --git a/src/util/fipstools/testdata/x86_64-BSS/out.s b/src/util/fipstools/testdata/x86_64-BSS/out.s deleted file mode 100644 index 5c576d95..00000000 --- a/src/util/fipstools/testdata/x86_64-BSS/out.s +++ /dev/null @@ -1,143 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .text - movq %rax, %rax - - # BSS declarations emit accessors. - .comm aes_128_ctr_generic_storage,64,32 - .lcomm aes_128_ctr_generic_storage2,64,32 - - # BSS symbols may also be emitted in .bss sections. - .section .bss,"awT",@nobits - .align 4 - .globl x - .type x, @object - .size x, 4 -x: -.Lx_local_target: - - .zero 4 -.Llocal: - .quad 0 - .size .Llocal, 4 - - # .bss handling is terminated by a .text directive. - .text - .section .bss,"awT",@nobits -y: -.Ly_local_target: - - .quad 0 - - # Or a .section directive. -# WAS .section .rodata -.text - .quad 0 - - # Or the end of the file. - .section .bss,"awT",@nobits -z: -.Lz_local_target: - - .quad 0 -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type aes_128_ctr_generic_storage_bss_get, @function -aes_128_ctr_generic_storage_bss_get: - leaq aes_128_ctr_generic_storage(%rip), %rax - ret -.type aes_128_ctr_generic_storage2_bss_get, @function -aes_128_ctr_generic_storage2_bss_get: - leaq aes_128_ctr_generic_storage2(%rip), %rax - ret -.type x_bss_get, @function -x_bss_get: - leaq .Lx_local_target(%rip), %rax - ret -.type y_bss_get, @function -y_bss_get: - leaq .Ly_local_target(%rip), %rax - ret -.type z_bss_get, @function -z_bss_get: - leaq .Lz_local_target(%rip), %rax - ret -.type OPENSSL_ia32cap_get, @function -OPENSSL_ia32cap_get: - leaq OPENSSL_ia32cap_P(%rip), %rax - ret -.extern OPENSSL_ia32cap_P -.type OPENSSL_ia32cap_addr_delta, @object -.size OPENSSL_ia32cap_addr_delta, 8 -OPENSSL_ia32cap_addr_delta: -.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/x86_64-Basic/in.s b/src/util/fipstools/testdata/x86_64-Basic/in.s deleted file mode 100644 index 89e8aafa..00000000 --- a/src/util/fipstools/testdata/x86_64-Basic/in.s +++ /dev/null @@ -1,46 +0,0 @@ - # Most instructions and lines should pass unaltered. This is made up of - # copy-and-pasted bits of compiler output and likely does not actually - # run. - .file "bcm.c" - .text - - .type foo, @function - .globl foo -foo: - .file 1 "../foo/bar.c" - .loc 1 2 3 - .cfi_startproc - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset 6, -16 - .cfi_adjust_cfa_offset 32*5+8 - movq %rsp, %rbp - movq %rdi, -24(%rbp) - movq -24(%rbp), %rax - .loc 1 168 0 is_stmt 0 discriminator 1 - cmpq -8(%rbp), %rax - jmpq *%rax - movdqa %xmm3,%xmm10 - psrlq $1,%xmm3 - pxor %xmm6,%xmm5 - pxor %xmm4,%xmm3 - pand %xmm7,%xmm5 - pand %xmm7,%xmm3 - pxor %xmm5,%xmm6 - paddd 112(%r11),%xmm15 - vmovdqa %xmm0,%xmm5 - vpunpckhqdq %xmm0,%xmm0,%xmm3 - vpxor %xmm0,%xmm3,%xmm3 - vpclmulqdq $0x11,%xmm2,%xmm0,%xmm1 - vpclmulqdq $0x00,%xmm2,%xmm0,%xmm0 - vpclmulqdq $0x00,%xmm6,%xmm3,%xmm3 - vpxor %xmm0,%xmm1,%xmm4 - vpxor %xmm4,%xmm3,%xmm3 - vmovdqu8 %ymm1,%ymm6{%k1}{z} - vmovdqu8 %ymm2,%ymm4{%k3} - .byte 0xf3,0xc3 - movq %rax, %rbx # Comments can be on the same line as an instruction. -.L3: # Or on the same line as a label. -.L4: .L5: movq %rbx, %rax # This is also legal. -.size foo, .-foo -.type foo, @function diff --git a/src/util/fipstools/testdata/x86_64-Basic/out.s b/src/util/fipstools/testdata/x86_64-Basic/out.s deleted file mode 100644 index 02a60256..00000000 --- a/src/util/fipstools/testdata/x86_64-Basic/out.s +++ /dev/null @@ -1,133 +0,0 @@ -.text -.file 2 "inserted_by_delocate.c" -.loc 2 1 0 -BORINGSSL_bcm_text_start: - # Most instructions and lines should pass unaltered. This is made up of - # copy-and-pasted bits of compiler output and likely does not actually - # run. - .file "bcm.c" - .text - - .type foo, @function - .globl foo -.Lfoo_local_target: -foo: - .file 1 "../foo/bar.c" - .loc 1 2 3 - .cfi_startproc - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset 6, -16 - .cfi_adjust_cfa_offset 32*5+8 - movq %rsp, %rbp - movq %rdi, -24(%rbp) - movq -24(%rbp), %rax - .loc 1 168 0 is_stmt 0 discriminator 1 - cmpq -8(%rbp), %rax - jmpq *%rax - movdqa %xmm3,%xmm10 - psrlq $1,%xmm3 - pxor %xmm6,%xmm5 - pxor %xmm4,%xmm3 - pand %xmm7,%xmm5 - pand %xmm7,%xmm3 - pxor %xmm5,%xmm6 - paddd 112(%r11),%xmm15 - vmovdqa %xmm0,%xmm5 - vpunpckhqdq %xmm0,%xmm0,%xmm3 - vpxor %xmm0,%xmm3,%xmm3 - vpclmulqdq $0x11,%xmm2,%xmm0,%xmm1 - vpclmulqdq $0x00,%xmm2,%xmm0,%xmm0 - vpclmulqdq $0x00,%xmm6,%xmm3,%xmm3 - vpxor %xmm0,%xmm1,%xmm4 - vpxor %xmm4,%xmm3,%xmm3 - vmovdqu8 %ymm1,%ymm6{%k1}{z} - vmovdqu8 %ymm2,%ymm4{%k3} - .byte 0xf3,0xc3 - movq %rax, %rbx # Comments can be on the same line as an instruction. -.L3: - # Or on the same line as a label. -.L4: -.L5: - movq %rbx, %rax # This is also legal. -.size foo, .-foo -.type foo, @function -.text -.loc 2 2 0 -BORINGSSL_bcm_text_end: -.type OPENSSL_ia32cap_get, @function -OPENSSL_ia32cap_get: - leaq OPENSSL_ia32cap_P(%rip), %rax - ret -.extern OPENSSL_ia32cap_P -.type OPENSSL_ia32cap_addr_delta, @object -.size OPENSSL_ia32cap_addr_delta, 8 -OPENSSL_ia32cap_addr_delta: -.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/x86_64-GOTRewrite/in.s b/src/util/fipstools/testdata/x86_64-GOTRewrite/in.s deleted file mode 100644 index ccbc0bf3..00000000 --- a/src/util/fipstools/testdata/x86_64-GOTRewrite/in.s +++ /dev/null @@ -1,47 +0,0 @@ - .text -foo: - # leaq of OPENSSL_ia32cap_P is supported. - leaq OPENSSL_ia32cap_P(%rip), %r11 - - # As is the equivalent GOTPCREL movq. - movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 - - # And a non-movq instruction via the GOT. - orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 - - # ... which targets the default temp register - orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax - - # Test that GOTPCREL accesses get translated. They are handled - # differently for local and external symbols. - - pushq stderr@GOTPCREL(%rip) - pushq foo@GOTPCREL(%rip) - - movq stderr@GOTPCREL(%rip), %r11 - movq foo@GOTPCREL(%rip), %r11 - - vmovq stderr@GOTPCREL(%rip), %xmm0 - vmovq foo@GOTPCREL(%rip), %xmm0 - - cmoveq stderr@GOTPCREL(%rip), %r11 - cmoveq foo@GOTPCREL(%rip), %r11 - cmovneq stderr@GOTPCREL(%rip), %r11 - cmovneq foo@GOTPCREL(%rip), %r11 - - movsd foo@GOTPCREL(%rip), %xmm0 - vmovsd foo@GOTPCREL(%rip), %xmm0 - - # movsd without arguments should be left as-is. - movsd - - # Synthesized symbols do not use the GOT. - movq BORINGSSL_bcm_text_start@GOTPCREL(%rip), %r11 - movq foobar_bss_get@GOTPCREL(%rip), %r11 - movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11 - - # Transforming moves run the transform in-place after the load. - vpbroadcastq stderr@GOTPCREL(%rip), %xmm0 - vpbroadcastq foo@GOTPCREL(%rip), %xmm0 - -.comm foobar,64,32 diff --git a/src/util/fipstools/testdata/x86_64-GOTRewrite/out.s b/src/util/fipstools/testdata/x86_64-GOTRewrite/out.s deleted file mode 100644 index 3d421e56..00000000 --- a/src/util/fipstools/testdata/x86_64-GOTRewrite/out.s +++ /dev/null @@ -1,263 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .text -.Lfoo_local_target: -foo: - # leaq of OPENSSL_ia32cap_P is supported. -# WAS leaq OPENSSL_ia32cap_P(%rip), %r11 - leaq -128(%rsp), %rsp - pushfq - leaq OPENSSL_ia32cap_addr_delta(%rip), %r11 - addq (%r11), %r11 - popfq - leaq 128(%rsp), %rsp - - # As is the equivalent GOTPCREL movq. -# WAS movq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 - leaq -128(%rsp), %rsp - pushfq - leaq OPENSSL_ia32cap_addr_delta(%rip), %r12 - addq (%r12), %r12 - popfq - leaq 128(%rsp), %rsp - - # And a non-movq instruction via the GOT. -# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %r12 - leaq -128(%rsp), %rsp - pushq %rax - pushfq - leaq OPENSSL_ia32cap_addr_delta(%rip), %rax - addq (%rax), %rax - popfq - orq %rax, %r12 - popq %rax - leaq 128(%rsp), %rsp - - # ... which targets the default temp register -# WAS orq OPENSSL_ia32cap_P@GOTPCREL(%rip), %rax - leaq -128(%rsp), %rsp - pushq %rbx - pushfq - leaq OPENSSL_ia32cap_addr_delta(%rip), %rbx - addq (%rbx), %rbx - popfq - orq %rbx, %rax - popq %rbx - leaq 128(%rsp), %rsp - - # Test that GOTPCREL accesses get translated. They are handled - # differently for local and external symbols. - -# WAS pushq stderr@GOTPCREL(%rip) - pushq %rax - leaq -128(%rsp), %rsp - pushf - leaq stderr_GOTPCREL_external(%rip), %rax - addq (%rax), %rax - movq (%rax), %rax - popf - leaq 128(%rsp), %rsp - xchg %rax, (%rsp) -# WAS pushq foo@GOTPCREL(%rip) - pushq %rax - leaq .Lfoo_local_target(%rip), %rax - xchg %rax, (%rsp) - -# WAS movq stderr@GOTPCREL(%rip), %r11 - leaq -128(%rsp), %rsp - pushf - leaq stderr_GOTPCREL_external(%rip), %r11 - addq (%r11), %r11 - movq (%r11), %r11 - popf - leaq 128(%rsp), %rsp -# WAS movq foo@GOTPCREL(%rip), %r11 - leaq .Lfoo_local_target(%rip), %r11 - -# WAS vmovq stderr@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - pushf - leaq stderr_GOTPCREL_external(%rip), %rax - addq (%rax), %rax - movq (%rax), %rax - popf - vmovq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp -# WAS vmovq foo@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - leaq .Lfoo_local_target(%rip), %rax - vmovq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp - -# WAS cmoveq stderr@GOTPCREL(%rip), %r11 - jne 999f - leaq -128(%rsp), %rsp - pushf - leaq stderr_GOTPCREL_external(%rip), %r11 - addq (%r11), %r11 - movq (%r11), %r11 - popf - leaq 128(%rsp), %rsp -999: -# WAS cmoveq foo@GOTPCREL(%rip), %r11 - jne 999f - leaq .Lfoo_local_target(%rip), %r11 -999: -# WAS cmovneq stderr@GOTPCREL(%rip), %r11 - je 999f - leaq -128(%rsp), %rsp - pushf - leaq stderr_GOTPCREL_external(%rip), %r11 - addq (%r11), %r11 - movq (%r11), %r11 - popf - leaq 128(%rsp), %rsp -999: -# WAS cmovneq foo@GOTPCREL(%rip), %r11 - je 999f - leaq .Lfoo_local_target(%rip), %r11 -999: - -# WAS movsd foo@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - leaq .Lfoo_local_target(%rip), %rax - movq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp -# WAS vmovsd foo@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - leaq .Lfoo_local_target(%rip), %rax - vmovq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp - - # movsd without arguments should be left as-is. - movsd - - # Synthesized symbols do not use the GOT. -# WAS movq BORINGSSL_bcm_text_start@GOTPCREL(%rip), %r11 - leaq BORINGSSL_bcm_text_start(%rip), %r11 -# WAS movq foobar_bss_get@GOTPCREL(%rip), %r11 - leaq foobar_bss_get(%rip), %r11 -# WAS movq OPENSSL_ia32cap_get@GOTPCREL(%rip), %r11 - leaq OPENSSL_ia32cap_get(%rip), %r11 - - # Transforming moves run the transform in-place after the load. -# WAS vpbroadcastq stderr@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - pushf - leaq stderr_GOTPCREL_external(%rip), %rax - addq (%rax), %rax - movq (%rax), %rax - popf - vmovq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp - vpbroadcastq %xmm0, %xmm0 -# WAS vpbroadcastq foo@GOTPCREL(%rip), %xmm0 - leaq -128(%rsp), %rsp - pushq %rax - leaq .Lfoo_local_target(%rip), %rax - vmovq %rax, %xmm0 - popq %rax - leaq 128(%rsp), %rsp - vpbroadcastq %xmm0, %xmm0 - -.comm foobar,64,32 -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type foobar_bss_get, @function -foobar_bss_get: - leaq foobar(%rip), %rax - ret -.type stderr_GOTPCREL_external, @object -.size stderr_GOTPCREL_external, 8 -stderr_GOTPCREL_external: - .long stderr@GOTPCREL - .long 0 -.type OPENSSL_ia32cap_get, @function -OPENSSL_ia32cap_get: - leaq OPENSSL_ia32cap_P(%rip), %rax - ret -.extern OPENSSL_ia32cap_P -.type OPENSSL_ia32cap_addr_delta, @object -.size OPENSSL_ia32cap_addr_delta, 8 -OPENSSL_ia32cap_addr_delta: -.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/x86_64-LabelRewrite/in1.s b/src/util/fipstools/testdata/x86_64-LabelRewrite/in1.s deleted file mode 100644 index e97b280b..00000000 --- a/src/util/fipstools/testdata/x86_64-LabelRewrite/in1.s +++ /dev/null @@ -1,43 +0,0 @@ - .type foo, @function - .globl foo -foo: - movq $0, %rax - ret - -bar: - # References to globals must be rewritten to their local targets. - call foo - jmp foo - jbe foo - jne foo - - # Jumps to PLT symbols are rewritten through redirectors. - call memcpy@PLT - jmp memcpy@PLT - jbe memcpy@PLT - - # Jumps to local PLT symbols use their local targets. - call foo@PLT - jmp foo@PLT - jbe foo@PLT - - # Synthesized symbols are treated as local ones. - call OPENSSL_ia32cap_get@PLT - - # References to local labels are left as-is in the first file. -.Llocal_label: - jbe .Llocal_label - leaq .Llocal_label+2048(%rip), %r14 - leaq .Llocal_label+2048+1024(%rip), %r14 - - .section .rodata -.L1: - .quad 42 -.L2: - .quad .L2-.L1 - - # Local labels and their jumps are left alone. - .text - jmp 1f -1: - jmp 1b diff --git a/src/util/fipstools/testdata/x86_64-LabelRewrite/in2.s b/src/util/fipstools/testdata/x86_64-LabelRewrite/in2.s deleted file mode 100644 index 7a5a5510..00000000 --- a/src/util/fipstools/testdata/x86_64-LabelRewrite/in2.s +++ /dev/null @@ -1,12 +0,0 @@ - # References to local labels are rewrittenn in subsequent files. -.Llocal_label: - jbe .Llocal_label - leaq .Llocal_label+2048(%rip), %r14 - leaq .Llocal_label+2048+1024(%rip), %r14 - - .section .rodata -.L1: - .quad 42 -.L2: - .quad .L2-.L1 - diff --git a/src/util/fipstools/testdata/x86_64-LabelRewrite/out.s b/src/util/fipstools/testdata/x86_64-LabelRewrite/out.s deleted file mode 100644 index 4a018537..00000000 --- a/src/util/fipstools/testdata/x86_64-LabelRewrite/out.s +++ /dev/null @@ -1,167 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - .type foo, @function - .globl foo -.Lfoo_local_target: -foo: - movq $0, %rax - ret - -.Lbar_local_target: -bar: - # References to globals must be rewritten to their local targets. -# WAS call foo - call .Lfoo_local_target -# WAS jmp foo - jmp .Lfoo_local_target -# WAS jbe foo - jbe .Lfoo_local_target -# WAS jne foo - jne .Lfoo_local_target - - # Jumps to PLT symbols are rewritten through redirectors. -# WAS call memcpy@PLT - call bcm_redirector_memcpy -# WAS jmp memcpy@PLT - jmp bcm_redirector_memcpy -# WAS jbe memcpy@PLT - jbe bcm_redirector_memcpy - - # Jumps to local PLT symbols use their local targets. -# WAS call foo@PLT - call .Lfoo_local_target -# WAS jmp foo@PLT - jmp .Lfoo_local_target -# WAS jbe foo@PLT - jbe .Lfoo_local_target - - # Synthesized symbols are treated as local ones. -# WAS call OPENSSL_ia32cap_get@PLT - call OPENSSL_ia32cap_get - - # References to local labels are left as-is in the first file. -.Llocal_label: - - jbe .Llocal_label - leaq .Llocal_label+2048(%rip), %r14 - leaq .Llocal_label+2048+1024(%rip), %r14 - -# WAS .section .rodata -.text -.L1: - - .quad 42 -.L2: - - .quad .L2-.L1 - - # Local labels and their jumps are left alone. - .text - jmp 1f -1: - - jmp 1b - # References to local labels are rewrittenn in subsequent files. -.Llocal_label_BCM_1: - -# WAS jbe .Llocal_label - jbe .Llocal_label_BCM_1 -# WAS leaq .Llocal_label+2048(%rip), %r14 - leaq .Llocal_label_BCM_1+2048(%rip), %r14 -# WAS leaq .Llocal_label+2048+1024(%rip), %r14 - leaq .Llocal_label_BCM_1+2048+1024(%rip), %r14 - -# WAS .section .rodata -.text -.L1_BCM_1: - - .quad 42 -.L2_BCM_1: - -# WAS .quad .L2-.L1 - .quad .L2_BCM_1-.L1_BCM_1 - -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type bcm_redirector_memcpy, @function -bcm_redirector_memcpy: - jmp memcpy@PLT -.type OPENSSL_ia32cap_get, @function -OPENSSL_ia32cap_get: - leaq OPENSSL_ia32cap_P(%rip), %rax - ret -.extern OPENSSL_ia32cap_P -.type OPENSSL_ia32cap_addr_delta, @object -.size OPENSSL_ia32cap_addr_delta, 8 -OPENSSL_ia32cap_addr_delta: -.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/fipstools/testdata/x86_64-Sections/in.s b/src/util/fipstools/testdata/x86_64-Sections/in.s deleted file mode 100644 index 8358a4c5..00000000 --- a/src/util/fipstools/testdata/x86_64-Sections/in.s +++ /dev/null @@ -1,36 +0,0 @@ - # .text stays in .text - .text - movq %rax, %rax - - # -ffunction-sections is undone. - .section .text.foo,"ax",@progbits - .globl foo -foo: - ret - - # .rodata is moved to .text. - .section .rodata - .long 42 - .string "Hello world, esc\ape characters are \"fun\"\\" - - # Compilers sometimes emit extra rodata sections. - .section .rodata.str1.1,"aMS",@progbits,1 - .string "NIST P-256" - .text - - # A number of sections are left alone. - .section .init_array,"aw" - .align 8 - .quad foo - .section .rodata - .align 16 - .section .debug_info,"",@progbits -.Ldebug_info0: - .long 0x1b35e - .value 0x4 - .long .L1 - .byte 0x8 - .uleb128 0x1 - .long .L2 - .byte 0x1 - .long .L3 diff --git a/src/util/fipstools/testdata/x86_64-Sections/out.s b/src/util/fipstools/testdata/x86_64-Sections/out.s deleted file mode 100644 index ba427ade..00000000 --- a/src/util/fipstools/testdata/x86_64-Sections/out.s +++ /dev/null @@ -1,125 +0,0 @@ -.text -.file 1 "inserted_by_delocate.c" -.loc 1 1 0 -BORINGSSL_bcm_text_start: - # .text stays in .text - .text - movq %rax, %rax - - # -ffunction-sections is undone. -# WAS .section .text.foo,"ax",@progbits -.text - .globl foo -.Lfoo_local_target: -foo: - ret - - # .rodata is moved to .text. -# WAS .section .rodata -.text - .long 42 - .string "Hello world, esc\ape characters are \"fun\"\\" - - # Compilers sometimes emit extra rodata sections. -# WAS .section .rodata.str1.1,"aMS",@progbits,1 -.text - .string "NIST P-256" - .text - - # A number of sections are left alone. - .section .init_array,"aw" - .align 8 - .quad foo -# WAS .section .rodata -.text - .align 16 - .section .debug_info,"",@progbits -.Ldebug_info0: - - .long 0x1b35e - .value 0x4 - .long .L1 - .byte 0x8 - .uleb128 0x1 - .long .L2 - .byte 0x1 - .long .L3 -.text -.loc 1 2 0 -BORINGSSL_bcm_text_end: -.type OPENSSL_ia32cap_get, @function -OPENSSL_ia32cap_get: - leaq OPENSSL_ia32cap_P(%rip), %rax - ret -.extern OPENSSL_ia32cap_P -.type OPENSSL_ia32cap_addr_delta, @object -.size OPENSSL_ia32cap_addr_delta, 8 -OPENSSL_ia32cap_addr_delta: -.quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta -.type BORINGSSL_bcm_text_hash, @object -.size BORINGSSL_bcm_text_hash, 64 -BORINGSSL_bcm_text_hash: -.byte 0xae -.byte 0x2c -.byte 0xea -.byte 0x2a -.byte 0xbd -.byte 0xa6 -.byte 0xf3 -.byte 0xec -.byte 0x97 -.byte 0x7f -.byte 0x9b -.byte 0xf6 -.byte 0x94 -.byte 0x9a -.byte 0xfc -.byte 0x83 -.byte 0x68 -.byte 0x27 -.byte 0xcb -.byte 0xa0 -.byte 0xa0 -.byte 0x9f -.byte 0x6b -.byte 0x6f -.byte 0xde -.byte 0x52 -.byte 0xcd -.byte 0xe2 -.byte 0xcd -.byte 0xff -.byte 0x31 -.byte 0x80 -.byte 0xa2 -.byte 0xd4 -.byte 0xc3 -.byte 0x66 -.byte 0xf -.byte 0xc2 -.byte 0x6a -.byte 0x7b -.byte 0xf4 -.byte 0xbe -.byte 0x39 -.byte 0xa2 -.byte 0xd7 -.byte 0x25 -.byte 0xdb -.byte 0x21 -.byte 0x98 -.byte 0xe9 -.byte 0xd5 -.byte 0x53 -.byte 0xbf -.byte 0x5c -.byte 0x32 -.byte 0x6 -.byte 0x83 -.byte 0x34 -.byte 0xc -.byte 0x65 -.byte 0x89 -.byte 0x52 -.byte 0xbd -.byte 0x1f diff --git a/src/util/godeps.go b/src/util/godeps.go new file mode 100644 index 00000000..960faa46 --- /dev/null +++ b/src/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) + } +} -- cgit v1.2.3