diff --git a/include/remill/Arch/AArch32/Runtime/State.h b/include/remill/Arch/AArch32/Runtime/State.h index e6a20b414..63f9ab76d 100644 --- a/include/remill/Arch/AArch32/Runtime/State.h +++ b/include/remill/Arch/AArch32/Runtime/State.h @@ -105,7 +105,7 @@ struct alignas(8) SR final { uint8_t _padding[2]; } __attribute__((packed)); -struct alignas(16) State final : public ArchState { +struct alignas(16) AArch32State : public ArchState { GPR gpr; // 528 bytes. @@ -115,6 +115,6 @@ struct alignas(16) State final : public ArchState { } __attribute__((packed)); -using AArch32State = State; +struct State : public AArch32State {}; #pragma clang diagnostic pop diff --git a/include/remill/Arch/AArch64/Runtime/State.h b/include/remill/Arch/AArch64/Runtime/State.h index 7aa8a0c72..18dd7b177 100644 --- a/include/remill/Arch/AArch64/Runtime/State.h +++ b/include/remill/Arch/AArch64/Runtime/State.h @@ -279,7 +279,7 @@ struct alignas(16) SIMD { static_assert(512 == sizeof(SIMD), "Invalid packing of `struct SIMD`."); -struct alignas(16) State final : public ArchState { +struct alignas(16) AArch64State : public ArchState { SIMD simd; // 512 bytes. uint64_t _0; @@ -300,9 +300,9 @@ struct alignas(16) State final : public ArchState { } __attribute__((packed)); -static_assert((1152 + 16) == sizeof(State), +static_assert((1152 + 16) == sizeof(AArch64State), "Invalid packing of `struct State`"); -using AArch64State = State; +struct State : public AArch64State {}; #pragma clang diagnostic pop diff --git a/include/remill/Arch/Arch.h b/include/remill/Arch/Arch.h index d345ab39a..3069c0808 100644 --- a/include/remill/Arch/Arch.h +++ b/include/remill/Arch/Arch.h @@ -124,6 +124,8 @@ struct Register { // The directly enclosed registers. std::vector children; + + void CompteGEPAccessors(const llvm::DataLayout &dl, llvm::Type *state_type); }; class Arch { @@ -174,7 +176,7 @@ class Arch { virtual std::string_view ProgramCounterRegisterName(void) const = 0; // Converts an LLVM module object to have the right triple / data layout - // information for the target architecture and ensures remill requied functions + // information for the target architecture and ensures remill required functions // have the appropriate prototype and internal variables void PrepareModule(llvm::Module *mod) const; @@ -281,11 +283,6 @@ class Arch { static ArchPtr Build(llvm::LLVMContext *context, OSName os, ArchName arch_name); - // Get the architecture of the modelled code. This is based on command-line - // flags. Rather use directly Build. - static ArchPtr GetTargetArch(llvm::LLVMContext &context) - __attribute__((deprecated)); - // Get the (approximate) architecture of the system library was built on. This may not // include all feature sets. static ArchPtr GetHostArch(llvm::LLVMContext &contex); @@ -293,6 +290,9 @@ class Arch { protected: Arch(llvm::LLVMContext *context_, OSName os_name_, ArchName arch_name_); + // Populate the table of register information. + virtual void PopulateRegisterTable(void) const = 0; + // Populate the `__remill_basic_block` function with variables. virtual void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const = 0; @@ -324,9 +324,10 @@ class Arch { static ArchPtr GetSPARC64(llvm::LLVMContext *context, OSName os, ArchName arch_name); - mutable std::unique_ptr impl; - Arch(void) = delete; + + protected: + mutable std::unique_ptr impl; }; } // namespace remill diff --git a/include/remill/Arch/SPARC32/Runtime/State.h b/include/remill/Arch/SPARC32/Runtime/State.h index ebccea28b..e11323ed9 100644 --- a/include/remill/Arch/SPARC32/Runtime/State.h +++ b/include/remill/Arch/SPARC32/Runtime/State.h @@ -319,7 +319,7 @@ struct RegisterWindow { RegisterWindow *prev_window; }; -struct alignas(16) State : public ArchState { +struct alignas(16) SPARC32State : public ArchState { FPURegs fpreg; // 512 bytes volatile uint64_t _0; GPR gpr; // 256 bytes @@ -349,6 +349,6 @@ struct alignas(16) State : public ArchState { #endif }; -using SPARCState = State; +struct State : public SPARC32State {}; #pragma clang diagnostic pop diff --git a/include/remill/Arch/SPARC64/Runtime/State.h b/include/remill/Arch/SPARC64/Runtime/State.h index ea36af7d1..319ecf905 100644 --- a/include/remill/Arch/SPARC64/Runtime/State.h +++ b/include/remill/Arch/SPARC64/Runtime/State.h @@ -328,7 +328,7 @@ struct RegisterWindow { RegisterWindow *prev_window; }; -struct alignas(16) State : public ArchState { +struct alignas(16) SPARC64State : public ArchState { FPURegs fpreg; // 512 bytes volatile uint64_t _0; GPR gpr; // 512 bytes @@ -358,6 +358,6 @@ struct alignas(16) State : public ArchState { #endif }; -using SPARCState = State; +struct State : public SPARC64State {}; #pragma clang diagnostic pop diff --git a/include/remill/Arch/X86/Runtime/State.h b/include/remill/Arch/X86/Runtime/State.h index a5b2f83e0..bbb26ad2a 100644 --- a/include/remill/Arch/X86/Runtime/State.h +++ b/include/remill/Arch/X86/Runtime/State.h @@ -758,7 +758,7 @@ static_assert(128 == sizeof(MMX), "Invalid structure packing of `MMX`."); enum : size_t { kNumVecRegisters = 32 }; -struct alignas(16) State final : public ArchState { +struct alignas(16) X86State : public ArchState { // ArchState occupies 16 bytes. @@ -781,10 +781,10 @@ struct alignas(16) State final : public ArchState { SegmentCaches seg_caches; // 96 bytes } __attribute__((packed)); -static_assert((96 + 3264 + 16) == sizeof(State), +static_assert((96 + 3264 + 16) == sizeof(X86State), "Invalid packing of `struct State`"); -using X86State = State; +struct State : public X86State {}; union CR0Reg { uint64_t flat; diff --git a/lib/Arch/AArch32/Arch.cpp b/lib/Arch/AArch32/Arch.cpp index 42c12ad9f..1d0b7a2f0 100644 --- a/lib/Arch/AArch32/Arch.cpp +++ b/lib/Arch/AArch32/Arch.cpp @@ -43,6 +43,8 @@ // clang-format on +#include "../Arch.h" // For `ArchImpl`. + namespace remill { AArch32Arch::AArch32Arch(llvm::LLVMContext *context_, OSName os_name_, @@ -112,41 +114,25 @@ std::string_view AArch32Arch::ProgramCounterRegisterName(void) const { return "PC"; } -// Populate the `__remill_basic_block` function with variables. -void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module, - llvm::Function *bb_func) const { - const auto &dl = module->getDataLayout(); - CHECK_EQ(sizeof(State), dl.getTypeAllocSize(StateStructType())) - << "Mismatch between size of State type for x86/amd64 and what is in " - << "the bitcode module"; +// Populate the table of register information. +void AArch32Arch::PopulateRegisterTable(void) const { + CHECK_NOTNULL(context); - auto &context = module->getContext(); - auto u8 = llvm::Type::getInt8Ty(context); + impl->reg_by_offset.resize(sizeof(AArch32State)); - // auto u16 = llvm::Type::getInt16Ty(context); - auto u32 = llvm::Type::getInt32Ty(context); + auto u8 = llvm::Type::getInt8Ty(*context); - // auto u64 = llvm::Type::getInt64Ty(context); - // auto f64 = llvm::Type::getDoubleTy(context); - // auto v128 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 128u / 8u); - // auto v256 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 256u / 8u); - // auto v512 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 512u / 8u); - auto addr = llvm::Type::getIntNTy(context, address_size); - - // auto zero_addr_val = llvm::Constant::getNullValue(addr); - - const auto entry_block = &bb_func->getEntryBlock(); - llvm::IRBuilder<> ir(entry_block); + auto u32 = llvm::Type::getInt32Ty(*context); #define OFFSET_OF(type, access) \ (reinterpret_cast(&reinterpret_cast( \ static_cast(nullptr)->access))) #define REG(name, access, type) \ - AddRegister(#name, type, OFFSET_OF(State, access), nullptr) + AddRegister(#name, type, OFFSET_OF(AArch32State, access), nullptr) #define SUB_REG(name, access, type, parent_reg_name) \ - AddRegister(#name, type, OFFSET_OF(State, access), #parent_reg_name) + AddRegister(#name, type, OFFSET_OF(AArch32State, access), #parent_reg_name) REG(R0, gpr.r0.dword, u32); REG(R1, gpr.r1.dword, u32); @@ -173,6 +159,26 @@ void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module, REG(C, sr.c, u8); REG(Z, sr.z, u8); REG(V, sr.v, u8); +} + + +// Populate the `__remill_basic_block` function with variables. +void AArch32Arch::PopulateBasicBlockFunction(llvm::Module *module, + llvm::Function *bb_func) const { + const auto &dl = module->getDataLayout(); + CHECK_EQ(sizeof(State), dl.getTypeAllocSize(StateStructType())) + << "Mismatch between size of State type for x86/amd64 and what is in " + << "the bitcode module"; + + auto &context = module->getContext(); + auto u8 = llvm::Type::getInt8Ty(context); + + // auto u16 = llvm::Type::getInt16Ty(context); + auto u32 = llvm::Type::getInt32Ty(context); + auto addr = llvm::Type::getIntNTy(context, address_size); + + const auto entry_block = &bb_func->getEntryBlock(); + llvm::IRBuilder<> ir(entry_block); const auto pc_arg = NthArgument(bb_func, kPCArgNum); const auto state_ptr_arg = NthArgument(bb_func, kStatePointerArgNum); diff --git a/lib/Arch/AArch32/Arch.h b/lib/Arch/AArch32/Arch.h index a7434fa41..905b7903c 100644 --- a/lib/Arch/AArch32/Arch.h +++ b/lib/Arch/AArch32/Arch.h @@ -16,7 +16,7 @@ #pragma once -#include "remill/Arch/Arch.h" +#include "../Arch.h" // For `Arch` and `ArchImpl`. namespace remill { class AArch32Arch final : public Arch { @@ -47,6 +47,9 @@ class AArch32Arch final : public Arch { // Default calling convention for this architecture. llvm::CallingConv::ID DefaultCallingConv(void) const final; + // Populate the table of register information. + void PopulateRegisterTable(void) const final; + // Populate the `__remill_basic_block` function with variables. void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const final; diff --git a/lib/Arch/AArch64/Arch.cpp b/lib/Arch/AArch64/Arch.cpp index 398b60394..ad1dfae7e 100644 --- a/lib/Arch/AArch64/Arch.cpp +++ b/lib/Arch/AArch64/Arch.cpp @@ -33,8 +33,9 @@ #define REMILL_AARCH_STRICT_REGNUM +#include "../Arch.h" // For `Arch` and `ArchImpl`. + #include "Decode.h" -#include "remill/Arch/Arch.h" #include "remill/Arch/Instruction.h" #include "remill/Arch/Name.h" #include "remill/BC/ABI.h" @@ -133,6 +134,9 @@ class AArch64Arch final : public Arch { // Default calling convention for this architecture. llvm::CallingConv::ID DefaultCallingConv(void) const final; + // Populate the table of register information. + void PopulateRegisterTable(void) const final; + // Populate the `__remill_basic_block` function with variables. void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const final; @@ -152,9 +156,10 @@ llvm::CallingConv::ID AArch64Arch::DefaultCallingConv(void) const { return llvm::CallingConv::C; } -// Populate the `__remill_basic_block` function with variables. -void AArch64Arch::PopulateBasicBlockFunction(llvm::Module *module, - llvm::Function *bb_func) const { +// Populate the table of register information. +void AArch64Arch::PopulateRegisterTable(void) const { + + impl->reg_by_offset.resize(sizeof(AArch64State)); #define OFFSET_OF(type, access) \ (reinterpret_cast(&reinterpret_cast( \ @@ -166,12 +171,11 @@ void AArch64Arch::PopulateBasicBlockFunction(llvm::Module *module, #define SUB_REG(name, access, type, parent_reg_name) \ AddRegister(#name, type, OFFSET_OF(AArch64State, access), #parent_reg_name) - auto &context = module->getContext(); - auto u8 = llvm::Type::getInt8Ty(context); - auto u16 = llvm::Type::getInt16Ty(context); - auto u32 = llvm::Type::getInt32Ty(context); - auto u64 = llvm::Type::getInt64Ty(context); - auto u128 = llvm::Type::getInt128Ty(context); + auto u8 = llvm::Type::getInt8Ty(*context); + auto u16 = llvm::Type::getInt16Ty(*context); + auto u32 = llvm::Type::getInt32Ty(*context); + auto u64 = llvm::Type::getInt64Ty(*context); + auto u128 = llvm::Type::getInt128Ty(*context); auto v128u8 = llvm::ArrayType::get(u8, 128u / 8u); auto v128u16 = llvm::ArrayType::get(u16, 128u / 16u); @@ -179,13 +183,6 @@ void AArch64Arch::PopulateBasicBlockFunction(llvm::Module *module, auto v128u64 = llvm::ArrayType::get(u64, 128u / 64u); auto v128u128 = llvm::ArrayType::get(u128, 128u / 128u); - auto addr = u64; - auto zero_u32 = llvm::Constant::getNullValue(u32); - auto zero_u64 = llvm::Constant::getNullValue(u64); - - const auto entry_block = &bb_func->getEntryBlock(); - llvm::IRBuilder<> ir(entry_block); - REG(X0, gpr.x0.qword, u64); REG(X1, gpr.x1.qword, u64); REG(X2, gpr.x2.qword, u64); @@ -459,6 +456,22 @@ void AArch64Arch::PopulateBasicBlockFunction(llvm::Module *module, REG(TPIDR_EL0, sr.tpidr_el0.qword, u64); REG(TPIDRRO_EL0, sr.tpidrro_el0.qword, u64); +} + +// Populate the `__remill_basic_block` function with variables. +void AArch64Arch::PopulateBasicBlockFunction(llvm::Module *module, + llvm::Function *bb_func) const { + + auto &context = module->getContext(); + auto u32 = llvm::Type::getInt32Ty(context); + auto u64 = llvm::Type::getInt64Ty(context); + + auto addr = u64; + auto zero_u32 = llvm::Constant::getNullValue(u32); + auto zero_u64 = llvm::Constant::getNullValue(u64); + + const auto entry_block = &bb_func->getEntryBlock(); + llvm::IRBuilder<> ir(entry_block); const auto pc_arg = NthArgument(bb_func, kPCArgNum); const auto state_ptr_arg = NthArgument(bb_func, kStatePointerArgNum); diff --git a/lib/Arch/Arch.cpp b/lib/Arch/Arch.cpp index 28f709d78..6c05ec9af 100644 --- a/lib/Arch/Arch.cpp +++ b/lib/Arch/Arch.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "remill/Arch/Arch.h" +#include "Arch.h" // For `Arch` and `ArchImpl`. #include #include @@ -48,29 +48,7 @@ DEFINE_string(arch, REMILL_ARCH, "Valid architectures: x86, amd64 (with or without " "`_avx` or `_avx512` appended), aarch64, aarch32"); -DECLARE_string(os); - namespace remill { - -class ArchImpl { - public: - // State type. - llvm::StructType *state_type{nullptr}; - - // Memory pointer type. - llvm::PointerType *memory_type{nullptr}; - - // Lifted function type. - llvm::FunctionType *lifted_function_type{nullptr}; - - // Metadata type ID for remill registers. - unsigned reg_md_id{0}; - - std::vector> registers; - std::vector reg_by_offset; - std::unordered_map reg_by_name; -}; - namespace { static unsigned AddressSize(ArchName arch_name) { @@ -156,7 +134,7 @@ llvm::Triple Arch::BasicTriple(void) const { auto Arch::Build(llvm::LLVMContext *context_, OSName os_name_, ArchName arch_name_) -> ArchPtr { - + ArchPtr ret; switch (arch_name_) { case kArchInvalid: LOG(FATAL) << "Unrecognized architecture."; @@ -164,54 +142,71 @@ auto Arch::Build(llvm::LLVMContext *context_, OSName os_name_, case kArchAArch64LittleEndian: { DLOG(INFO) << "Using architecture: AArch64, feature set: Little Endian"; - return GetAArch64(context_, os_name_, arch_name_); + ret = GetAArch64(context_, os_name_, arch_name_); + break; } case kArchAArch32LittleEndian: { DLOG(INFO) << "Using architecture: AArch32, feature set: Little Endian"; - return GetAArch32(context_, os_name_, arch_name_); + ret = GetAArch32(context_, os_name_, arch_name_); + break; } case kArchX86: { DLOG(INFO) << "Using architecture: X86"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchX86_AVX: { DLOG(INFO) << "Using architecture: X86, feature set: AVX"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchX86_AVX512: { DLOG(INFO) << "Using architecture: X86, feature set: AVX512"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchAMD64: { DLOG(INFO) << "Using architecture: AMD64"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchAMD64_AVX: { DLOG(INFO) << "Using architecture: AMD64, feature set: AVX"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchAMD64_AVX512: { DLOG(INFO) << "Using architecture: AMD64, feature set: AVX512"; - return GetX86(context_, os_name_, arch_name_); + ret = GetX86(context_, os_name_, arch_name_); + break; } case kArchSparc32: { DLOG(INFO) << "Using architecture: 32-bit SPARC"; - return GetSPARC(context_, os_name_, arch_name_); + ret = GetSPARC(context_, os_name_, arch_name_); + break; } case kArchSparc64: { DLOG(INFO) << "Using architecture: 64-bit SPARC"; - return GetSPARC64(context_, os_name_, arch_name_); + ret = GetSPARC64(context_, os_name_, arch_name_); + break; } } + + if (ret) { + ret->impl.reset(new ArchImpl); + ret->PopulateRegisterTable(); + } + + return ret; } auto Arch::Get(llvm::LLVMContext &context, std::string_view os, @@ -228,10 +223,6 @@ auto Arch::GetHostArch(llvm::LLVMContext &ctx) -> ArchPtr { return Arch::Build(&ctx, GetOSName(REMILL_OS), GetArchName(REMILL_ARCH)); } -auto Arch::GetTargetArch(llvm::LLVMContext &ctx) -> ArchPtr { - return Arch::Build(&ctx, GetOSName(FLAGS_os), GetArchName(FLAGS_arch)); -} - // Return the type of the state structure. llvm::StructType *Arch::StateStructType(void) const { CHECK(impl) @@ -489,7 +480,9 @@ static uint64_t TotalOffset(const llvm::DataLayout &dl, llvm::Value *base, static llvm::Value * FinishAddressOf(llvm::IRBuilder<> &ir, const llvm::DataLayout &dl, llvm::Type *state_ptr_type, size_t state_size, - const Register *reg, unsigned addr_space, llvm::Value *gep) { + const Register *reg, unsigned addr_space, + llvm::Value *gep) { + auto gep_offset = TotalOffset(dl, gep, state_ptr_type); auto gep_type_at_offset = gep->getType()->getPointerElementType(); @@ -557,6 +550,21 @@ FinishAddressOf(llvm::IRBuilder<> &ir, const llvm::DataLayout &dl, } // namespace +void Register::CompteGEPAccessors(const llvm::DataLayout &dl, + llvm::Type *state_type) { + if (gep_type_at_offset || !state_type) { + return; + } + + auto &context = state_type->getContext(); + + gep_index_list.push_back( + llvm::Constant::getNullValue(llvm::Type::getInt32Ty(context))); + + std::tie(gep_offset, gep_type_at_offset) = + BuildIndexes(dl, state_type, 0, offset, gep_index_list); +} + // Generate a GEP that will let us load/store to this register, given // a `State *`. llvm::Value *Register::AddressOf(llvm::Value *state_ptr, @@ -565,7 +573,6 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr, return AddressOf(state_ptr, ir); } - llvm::Value *Register::AddressOf(llvm::Value *state_ptr, llvm::IRBuilder<> &ir) const { auto &context = type->getContext(); @@ -582,6 +589,10 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr, const auto module = ir.GetInsertBlock()->getParent()->getParent(); const auto &dl = module->getDataLayout(); + if (!gep_type_at_offset) { + const_cast(this)->CompteGEPAccessors(dl, state_type); + } + llvm::Value *gep = nullptr; if (auto const_state_ptr = llvm::dyn_cast(state_ptr); const_state_ptr) { @@ -592,8 +603,8 @@ llvm::Value *Register::AddressOf(llvm::Value *state_ptr, } auto state_size = dl.getTypeAllocSize(state_type); - auto ret = FinishAddressOf(ir, dl, state_ptr_type, state_size, this, - addr_space, gep); + auto ret = FinishAddressOf( + ir, dl, state_ptr_type, state_size, this, addr_space, gep); // Add the metadata to `inst`. if (auto inst = llvm::dyn_cast(ret); inst) { @@ -648,6 +659,7 @@ void Arch::PrepareModule(llvm::Module *mod) const { const Register *Arch::AddRegister(const char *reg_name_, llvm::Type *val_type, size_t offset, const char *parent_reg_name) const { + CHECK_NOTNULL(val_type); const std::string reg_name(reg_name_); auto ® = impl->reg_by_name[reg_name]; @@ -663,23 +675,11 @@ const Register *Arch::AddRegister(const char *reg_name_, llvm::Type *val_type, parent_reg = impl->reg_by_name[parent_reg_name]; } - llvm::SmallVector gep_index_list; - gep_index_list.push_back( - llvm::Constant::getNullValue(llvm::Type::getInt32Ty(*context))); - - auto [gep_offset, gep_type_at_offset] = - BuildIndexes(dl, impl->state_type, 0, offset, gep_index_list); - - if (!val_type) { - CHECK_EQ(gep_offset, offset); - val_type = gep_type_at_offset; - } - auto reg_impl = new Register(reg_name, offset, dl.getTypeAllocSize(val_type), val_type, parent_reg, impl.get()); - reg_impl->gep_index_list = std::move(gep_index_list); - reg_impl->gep_offset = gep_offset; - reg_impl->gep_type_at_offset = gep_type_at_offset; + + reg_impl->CompteGEPAccessors(dl, impl->state_type); + reg = reg_impl; impl->registers.emplace_back(reg_impl); @@ -713,12 +713,13 @@ const Register *Arch::AddRegister(const char *reg_name_, llvm::Type *val_type, // Get all of the register information from the prepared module. void Arch::InitFromSemanticsModule(llvm::Module *module) const { - if (impl) { - return; + if (!impl) { + impl.reset(new ArchImpl); } - impl.reset(new ArchImpl); - CHECK(!impl->state_type); + if (impl->state_type) { + return; + } const auto &dl = module->getDataLayout(); const auto basic_block = BasicBlockFunction(module); diff --git a/lib/Arch/Arch.h b/lib/Arch/Arch.h new file mode 100644 index 000000000..a94078d7a --- /dev/null +++ b/lib/Arch/Arch.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Trail of Bits, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + + +#include + +#include +#include +#include + +namespace llvm { +class FunctionType; +class PointerType; +class StructType; +} // namespace llvm +namespace remill { + +struct Register; + +class ArchImpl { + public: + // State type. + llvm::StructType *state_type{nullptr}; + + // Memory pointer type. + llvm::PointerType *memory_type{nullptr}; + + // Lifted function type. + llvm::FunctionType *lifted_function_type{nullptr}; + + // Metadata type ID for remill registers. + unsigned reg_md_id{0}; + + std::vector> registers; + std::vector reg_by_offset; + std::unordered_map reg_by_name; +}; + +} // namespace remill diff --git a/lib/Arch/CMakeLists.txt b/lib/Arch/CMakeLists.txt index 3700f6fd7..1c6e84080 100644 --- a/lib/Arch/CMakeLists.txt +++ b/lib/Arch/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(remill_arch STATIC "${REMILL_INCLUDE_DIR}/remill/Arch/Name.h" Arch.cpp + Arch.h Instruction.cpp Name.cpp ) diff --git a/lib/Arch/SPARC32/Arch.cpp b/lib/Arch/SPARC32/Arch.cpp index 4a8c8d769..9643ea691 100644 --- a/lib/Arch/SPARC32/Arch.cpp +++ b/lib/Arch/SPARC32/Arch.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "remill/Arch/Arch.h" +#include "../Arch.h" // For `Arch` and `ArchImpl`. #include @@ -166,6 +166,9 @@ class SPARC32Arch final : public Arch { return llvm::CallingConv::C; } + // Populate the table of register information. + void PopulateRegisterTable(void) const final; + // Populate the `__remill_basic_block` function with variables. void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const override; @@ -193,33 +196,33 @@ class SPARC32Arch final : public Arch { bool branch_taken_path) const final; }; -// Populate the `__remill_basic_block` function with variables. -void SPARC32Arch::PopulateBasicBlockFunction(llvm::Module *module, - llvm::Function *bb_func) const { +// Populate the table of register information. +void SPARC32Arch::PopulateRegisterTable(void) const { + + impl->reg_by_offset.resize(sizeof(SPARC32State)); #define OFFSET_OF(type, access) \ (reinterpret_cast(&reinterpret_cast( \ static_cast(nullptr)->access))) #define REG(name, access, type) \ - AddRegister(#name, type, OFFSET_OF(SPARCState, access), nullptr) + AddRegister(#name, type, OFFSET_OF(SPARC32State, access), nullptr) #define SUB_REG(name, access, type, parent_reg_name) \ - AddRegister(#name, type, OFFSET_OF(SPARCState, access), #parent_reg_name) + AddRegister(#name, type, OFFSET_OF(SPARC32State, access), #parent_reg_name) - auto &context = module->getContext(); - auto u8 = llvm::Type::getInt8Ty(context); - auto u32 = llvm::Type::getInt32Ty(context); - auto u64 = llvm::Type::getInt64Ty(context); - auto u128 = llvm::Type::getInt128Ty(context); - auto f32 = llvm::Type::getFloatTy(context); - auto f64 = llvm::Type::getDoubleTy(context); - - auto zero_u8 = llvm::Constant::getNullValue(u8); - auto zero_u32 = llvm::Constant::getNullValue(u32); + auto u8 = llvm::Type::getInt8Ty(*context); + auto u32 = llvm::Type::getInt32Ty(*context); + auto u64 = llvm::Type::getInt64Ty(*context); + auto u128 = llvm::Type::getInt128Ty(*context); + auto f32 = llvm::Type::getFloatTy(*context); + auto f64 = llvm::Type::getDoubleTy(*context); - const auto entry_block = &bb_func->getEntryBlock(); - llvm::IRBuilder<> ir(entry_block); + std::vector window_types(33, u64); + auto window_type = llvm::StructType::create(*context, "RegisterWindow"); + auto window_ptr_type = llvm::PointerType::get(window_type, 0); + window_types.push_back(window_ptr_type); + window_type->setBody(window_types, false); REG(pc, pc.dword, u32); SUB_REG(PC, pc.dword, u32, pc); @@ -258,10 +261,6 @@ void SPARC32Arch::PopulateBasicBlockFunction(llvm::Module *module, SUB_REG(o6, gpr.o6.dword, u32, sp); REG(o7, gpr.o7.dword, u32); - ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "g0"), false); - ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "ignore_write_to_g0"), - false); - REG(g1, gpr.g1.dword, u32); REG(g2, gpr.g2.dword, u32); REG(g3, gpr.g3.dword, u32); @@ -281,9 +280,6 @@ void SPARC32Arch::PopulateBasicBlockFunction(llvm::Module *module, REG(stick_cmpr, asr.stick_cmpr, u64); REG(cfr, asr.cfr, u64); - // this is for unknown asr to avoid crash. - ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "asr"), false); - REG(icc_c, asr.ccr.icc.c, u8); REG(icc_v, asr.ccr.icc.v, u8); REG(icc_z, asr.ccr.icc.z, u8); @@ -375,10 +371,34 @@ void SPARC32Arch::PopulateBasicBlockFunction(llvm::Module *module, SUB_REG(q24, fpreg.v[6].doubles.elems[0], f64, v6); SUB_REG(q28, fpreg.v[7].doubles.elems[0], f64, v7); + REG(PREV_WINDOW_LINK, window, window_ptr_type); +} + + +// Populate the `__remill_basic_block` function with variables. +void SPARC32Arch::PopulateBasicBlockFunction(llvm::Module *module, + llvm::Function *bb_func) const { + auto &context = module->getContext(); + auto u8 = llvm::Type::getInt8Ty(context); + auto u32 = llvm::Type::getInt32Ty(context); + + auto zero_u8 = llvm::Constant::getNullValue(u8); + auto zero_u32 = llvm::Constant::getNullValue(u32); + + const auto entry_block = &bb_func->getEntryBlock(); + llvm::IRBuilder<> ir(entry_block); + + ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "g0"), false); + ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "ignore_write_to_g0"), + false); + + // this is for unknown asr to avoid crash. + ir.CreateStore(zero_u32, ir.CreateAlloca(u32, nullptr, "asr"), false); + // NOTE(pag): Passing `nullptr` as the type will force `Arch::AddRegister` // to infer the type based on what it finds. It's a pointer to // a structure type, so we can check that. - const auto prev_window_link = REG(PREV_WINDOW_LINK, window, nullptr); + const auto prev_window_link = RegisterByName("PREV_WINDOW_LINK"); CHECK(prev_window_link->type->isPointerTy()); const auto window_type = prev_window_link->type->getPointerElementType(); CHECK(window_type->isStructTy()); diff --git a/lib/Arch/SPARC64/Arch.cpp b/lib/Arch/SPARC64/Arch.cpp index 0fb4d5114..00eb4c192 100644 --- a/lib/Arch/SPARC64/Arch.cpp +++ b/lib/Arch/SPARC64/Arch.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "remill/Arch/Arch.h" +#include "../Arch.h" // For `Arch` and `ArchImpl`. #include @@ -74,6 +74,9 @@ class SPARC64Arch final : public Arch { return llvm::CallingConv::C; } + // Populate the table of register information. + void PopulateRegisterTable(void) const final; + // Populate the `__remill_basic_block` function with variables. void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const override; @@ -101,34 +104,32 @@ class SPARC64Arch final : public Arch { bool branch_taken_path) const final; }; -// Populate the `__remill_basic_block` function with variables. -void SPARC64Arch::PopulateBasicBlockFunction(llvm::Module *module, - llvm::Function *bb_func) const { +// Populate the table of register information. +void SPARC64Arch::PopulateRegisterTable(void) const { + + impl->reg_by_offset.resize(sizeof(SPARC64State)); #define OFFSET_OF(type, access) \ (reinterpret_cast(&reinterpret_cast( \ static_cast(nullptr)->access))) #define REG(name, access, type) \ - AddRegister(#name, type, OFFSET_OF(SPARCState, access), nullptr) + AddRegister(#name, type, OFFSET_OF(SPARC64State, access), nullptr) #define SUB_REG(name, access, type, parent_reg_name) \ - AddRegister(#name, type, OFFSET_OF(SPARCState, access), #parent_reg_name) - - auto &context = module->getContext(); - auto u8 = llvm::Type::getInt8Ty(context); - auto u32 = llvm::Type::getInt32Ty(context); - auto u64 = llvm::Type::getInt64Ty(context); - auto u128 = llvm::Type::getInt128Ty(context); - auto f32 = llvm::Type::getFloatTy(context); - auto f64 = llvm::Type::getDoubleTy(context); + AddRegister(#name, type, OFFSET_OF(SPARC64State, access), #parent_reg_name) - auto zero_u8 = llvm::Constant::getNullValue(u8); - auto zero_u32 = llvm::Constant::getNullValue(u32); - auto zero_u64 = llvm::Constant::getNullValue(u64); + auto u8 = llvm::Type::getInt8Ty(*context); + auto u64 = llvm::Type::getInt64Ty(*context); + auto u128 = llvm::Type::getInt128Ty(*context); + auto f32 = llvm::Type::getFloatTy(*context); + auto f64 = llvm::Type::getDoubleTy(*context); - const auto entry_block = &bb_func->getEntryBlock(); - llvm::IRBuilder<> ir(entry_block); + std::vector window_types(33, u64); + auto window_type = llvm::StructType::create(*context, "RegisterWindow"); + auto window_ptr_type = llvm::PointerType::get(window_type, 0); + window_types.push_back(window_ptr_type); + window_type->setBody(window_types, false); REG(pc, pc.qword, u64); SUB_REG(PC, pc.qword, u64, pc); @@ -167,10 +168,6 @@ void SPARC64Arch::PopulateBasicBlockFunction(llvm::Module *module, SUB_REG(o6, gpr.o6.qword, u64, sp); REG(o7, gpr.o7.qword, u64); - ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "g0"), false); - ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "ignore_write_to_g0"), - false); - REG(g1, gpr.g1.qword, u64); REG(g2, gpr.g2.qword, u64); REG(g3, gpr.g3.qword, u64); @@ -190,9 +187,6 @@ void SPARC64Arch::PopulateBasicBlockFunction(llvm::Module *module, REG(stick_cmpr, asr.stick_cmpr, u64); REG(cfr, asr.cfr, u64); - // this is for unknown asr to avoid crash. - ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "asr"), false); - REG(icc_c, asr.ccr.icc.c, u8); REG(icc_v, asr.ccr.icc.v, u8); REG(icc_z, asr.ccr.icc.z, u8); @@ -348,10 +342,36 @@ void SPARC64Arch::PopulateBasicBlockFunction(llvm::Module *module, SUB_REG(q56, fpreg.v[14].doubles.elems[0], f64, v14); SUB_REG(q60, fpreg.v[15].doubles.elems[0], f64, v15); + REG(PREV_WINDOW_LINK, window, window_ptr_type); +} + +// Populate the `__remill_basic_block` function with variables. +void SPARC64Arch::PopulateBasicBlockFunction(llvm::Module *module, + llvm::Function *bb_func) const { + + auto &context = module->getContext(); + auto u8 = llvm::Type::getInt8Ty(context); + auto u32 = llvm::Type::getInt32Ty(context); + auto u64 = llvm::Type::getInt64Ty(context); + + auto zero_u8 = llvm::Constant::getNullValue(u8); + auto zero_u32 = llvm::Constant::getNullValue(u32); + auto zero_u64 = llvm::Constant::getNullValue(u64); + + const auto entry_block = &bb_func->getEntryBlock(); + llvm::IRBuilder<> ir(entry_block); + + ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "g0"), false); + ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "ignore_write_to_g0"), + false); + + // this is for unknown asr to avoid crash. + ir.CreateStore(zero_u64, ir.CreateAlloca(u64, nullptr, "asr"), false); + // NOTE(pag): Passing `nullptr` as the type will force `Arch::AddRegister` // to infer the type based on what it finds. It's a pointer to // a structure type, so we can check that. - const auto prev_window_link = REG(PREV_WINDOW_LINK, window, nullptr); + const auto prev_window_link = this->RegisterByName("PREV_WINDOW_LINK"); CHECK(prev_window_link->type->isPointerTy()); const auto window_type = prev_window_link->type->getPointerElementType(); CHECK(window_type->isStructTy()); diff --git a/lib/Arch/X86/Arch.cpp b/lib/Arch/X86/Arch.cpp index a8306cdfe..22917283c 100644 --- a/lib/Arch/X86/Arch.cpp +++ b/lib/Arch/X86/Arch.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "remill/Arch/Arch.h" +#include "../Arch.h" // For `Arch` and `ArchImpl`. #include #include @@ -815,6 +815,9 @@ class X86Arch final : public Arch { // Default calling convention for this architecture. llvm::CallingConv::ID DefaultCallingConv(void) const final; + // Populate the table of register information. + void PopulateRegisterTable(void) const final; + // Populate the `__remill_basic_block` function with variables. void PopulateBasicBlockFunction(llvm::Module *module, llvm::Function *bb_func) const final; @@ -1360,13 +1363,12 @@ std::string_view X86Arch::ProgramCounterRegisterName(void) const { return kPCNames[IsX86()]; } -// Populate the `__remill_basic_block` function with variables. -void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, - llvm::Function *bb_func) const { - const auto &dl = module->getDataLayout(); - CHECK_EQ(sizeof(State), dl.getTypeAllocSize(StateStructType())) - << "Mismatch between size of State type for x86/amd64 and what is in " - << "the bitcode module"; +// Populate the table of register information. +void X86Arch::PopulateRegisterTable(void) const { + + impl->reg_by_offset.resize(sizeof(X86State)); + + CHECK_NOTNULL(context); bool has_avx = false; bool has_avx512 = false; @@ -1381,30 +1383,25 @@ void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, default: break; } - auto &context = module->getContext(); - auto u8 = llvm::Type::getInt8Ty(context); - auto u16 = llvm::Type::getInt16Ty(context); - auto u32 = llvm::Type::getInt32Ty(context); - auto u64 = llvm::Type::getInt64Ty(context); - auto f80 = llvm::Type::getX86_FP80Ty(context); - auto v128 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 128u / 8u); - auto v256 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 256u / 8u); - auto v512 = llvm::ArrayType::get(llvm::Type::getInt8Ty(context), 512u / 8u); - auto addr = llvm::Type::getIntNTy(context, address_size); - auto zero_addr_val = llvm::Constant::getNullValue(addr); - - const auto entry_block = &bb_func->getEntryBlock(); - llvm::IRBuilder<> ir(entry_block); + auto u8 = llvm::Type::getInt8Ty(*context); + auto u16 = llvm::Type::getInt16Ty(*context); + auto u32 = llvm::Type::getInt32Ty(*context); + auto u64 = llvm::Type::getInt64Ty(*context); + auto f80 = llvm::Type::getX86_FP80Ty(*context); + auto v128 = llvm::ArrayType::get(llvm::Type::getInt8Ty(*context), 128u / 8u); + auto v256 = llvm::ArrayType::get(llvm::Type::getInt8Ty(*context), 256u / 8u); + auto v512 = llvm::ArrayType::get(llvm::Type::getInt8Ty(*context), 512u / 8u); + auto addr = llvm::Type::getIntNTy(*context, address_size); #define OFFSET_OF(type, access) \ (reinterpret_cast(&reinterpret_cast( \ static_cast(nullptr)->access))) #define REG(name, access, type) \ - AddRegister(#name, type, OFFSET_OF(State, access), nullptr) + AddRegister(#name, type, OFFSET_OF(X86State, access), nullptr) #define SUB_REG(name, access, type, parent_reg_name) \ - AddRegister(#name, type, OFFSET_OF(State, access), #parent_reg_name) + AddRegister(#name, type, OFFSET_OF(X86State, access), #parent_reg_name) #define SUB_REG64(name, access, type, parent_reg_name) \ if (64 == address_size) { \ @@ -1509,18 +1506,12 @@ void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, SUB_REG(R15B, gpr.r15.byte.low, u8, R15W); } - const auto pc_arg = NthArgument(bb_func, kPCArgNum); - const auto state_ptr_arg = NthArgument(bb_func, kStatePointerArgNum); - ir.CreateStore(pc_arg, ir.CreateAlloca(addr, nullptr, "NEXT_PC")); - if (64 == address_size) { SUB_REG(PC, gpr.rip.qword, u64, RIP); } else { SUB_REG(PC, gpr.rip.dword, u32, EIP); } - (void) this->RegisterByName("PC")->AddressOf(state_ptr_arg, ir); - REG(SS, seg.ss.flat, u16); REG(ES, seg.es.flat, u16); REG(GS, seg.gs.flat, u16); @@ -1528,12 +1519,7 @@ void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, REG(DS, seg.ds.flat, u16); REG(CS, seg.cs.flat, u16); - ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "CSBASE")); - if (64 == address_size) { - ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "SSBASE")); - ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "ESBASE")); - ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "DSBASE")); REG(GSBASE, addr.gs_base.qword, addr); REG(FSBASE, addr.fs_base.qword, addr); @@ -1731,6 +1717,36 @@ void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, //#endif } +// Populate the `__remill_basic_block` function with variables. +void X86Arch::PopulateBasicBlockFunction(llvm::Module *module, + llvm::Function *bb_func) const { + const auto &dl = module->getDataLayout(); + CHECK_EQ(sizeof(State), dl.getTypeAllocSize(StateStructType())) + << "Mismatch between size of State type for x86/amd64 and what is in " + << "the bitcode module"; + + auto &context = module->getContext(); + auto addr = llvm::Type::getIntNTy(context, address_size); + auto zero_addr_val = llvm::Constant::getNullValue(addr); + + const auto entry_block = &bb_func->getEntryBlock(); + llvm::IRBuilder<> ir(entry_block); + + const auto pc_arg = NthArgument(bb_func, kPCArgNum); + const auto state_ptr_arg = NthArgument(bb_func, kStatePointerArgNum); + ir.CreateStore(pc_arg, ir.CreateAlloca(addr, nullptr, "NEXT_PC")); + + (void) this->RegisterByName("PC")->AddressOf(state_ptr_arg, ir); + + ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "CSBASE")); + + if (64 == address_size) { + ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "SSBASE")); + ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "ESBASE")); + ir.CreateStore(zero_addr_val, ir.CreateAlloca(addr, nullptr, "DSBASE")); + } +} + } // namespace // TODO(pag): We pretend that these are singletons, but they aren't really! diff --git a/tests/AArch64/Run.cpp b/tests/AArch64/Run.cpp index cd1988083..f62a4180f 100644 --- a/tests/AArch64/Run.cpp +++ b/tests/AArch64/Run.cpp @@ -86,20 +86,20 @@ extern "C" { // Native state before we run the native test case. We then use this as the // initial state for the lifted testcase. The lifted test case code mutates -// this, and we require that after running the lifted testcase, `gAArch64StateBefore` -// matches `gAArch64StateAfter`, -std::aligned_storage::type +// this, and we require that after running the lifted testcase, `gStateBefore` +// matches `gStateAfter`, +std::aligned_storage::type gLiftedState; // Native state after running the native test case. -std::aligned_storage::type +std::aligned_storage::type gNativeState; // Address of the native test to run. The `InvokeTestCase` function saves // the native program state but then needs a way to figure out where to go // without storing that information in any register. So what we do is we // store it here and indirectly `JMP` into the native test case code after -// saving the machine state to `gAArch64StateBefore`. +// saving the machine state to `gStateBefore`. uintptr_t gTestToRun = 0; // Used for swapping the stack pointer between `gStack` and the normal @@ -110,8 +110,8 @@ uint8_t *gStackSwitcher = nullptr; uint64_t gStackSaveSlots[2] = {0, 0}; // Invoke a native test case addressed by `gTestToRun` and store the machine -// state before and after executing the test in `gAArch64StateBefore` and -// `gAArch64StateAfter`, respectively. +// state before and after executing the test in `gStateBefore` and +// `gStateAfter`, respectively. extern void InvokeTestCase(uint64_t, uint64_t, uint64_t); #define MAKE_RW_MEMORY(size) \ @@ -250,15 +250,15 @@ Memory *__remill_delay_slot_end(Memory *) { void __remill_defer_inlining(void) {} -Memory *__remill_error(AArch64State &, addr_t, Memory *) { +Memory *__remill_error(State &, addr_t, Memory *) { siglongjmp(gJmpBuf, 0); } -Memory *__remill_missing_block(AArch64State &, addr_t, Memory *memory) { +Memory *__remill_missing_block(State &, addr_t, Memory *memory) { return memory; } -Memory *__remill_sync_hyper_call(AArch64State &, Memory *, +Memory *__remill_sync_hyper_call(State &, Memory *, SyncHyperCall::Name) { abort(); } @@ -287,19 +287,19 @@ Memory *__remill_write_io_port_32(Memory *, addr_t, uint32_t) { abort(); } -Memory *__remill_function_call(AArch64State &, addr_t, Memory *) { +Memory *__remill_function_call(State &, addr_t, Memory *) { abort(); } -Memory *__remill_function_return(AArch64State &, addr_t, Memory *) { +Memory *__remill_function_return(State &, addr_t, Memory *) { abort(); } -Memory *__remill_jump(AArch64State &, addr_t, Memory *) { +Memory *__remill_jump(State &, addr_t, Memory *) { abort(); } -Memory *__remill_async_hyper_call(AArch64State &, addr_t, Memory *) { +Memory *__remill_async_hyper_call(State &, addr_t, Memory *) { abort(); } @@ -344,7 +344,7 @@ void __remill_mark_as_used(void *mem) { } // extern C -typedef Memory *(LiftedFunc)(AArch64State &, addr_t, Memory *); +typedef Memory *(LiftedFunc)(State &, addr_t, Memory *); // Mapping of test name to translated function. static std::map gTranslatedFuncs; @@ -378,8 +378,8 @@ static void RunWithFlags(const test::TestInfo *info, NZCV flags, memset(&gLiftedState, 0, sizeof(gLiftedState)); memset(&gNativeState, 0, sizeof(gNativeState)); - auto lifted_state = reinterpret_cast(&gLiftedState); - auto native_state = reinterpret_cast(&gNativeState); + auto lifted_state = reinterpret_cast(&gLiftedState); + auto native_state = reinterpret_cast(&gNativeState); // Set up the run's info. gTestToRun = info->test_begin; @@ -559,10 +559,10 @@ INSTANTIATE_TEST_CASE_P(GeneralInstrTest, InstrTest, testing::ValuesIn(gTests)); // Recover from a signal. static void RecoverFromError(int sig_num, siginfo_t *, void *context_) { if (gInNativeTest) { - memcpy(&gNativeState, &gLiftedState, sizeof(AArch64State)); + memcpy(&gNativeState, &gLiftedState, sizeof(State)); auto context = reinterpret_cast(context_); - auto native_state = reinterpret_cast(&gNativeState); + auto native_state = reinterpret_cast(&gNativeState); auto &gpr = native_state->gpr; #ifdef __APPLE__ diff --git a/tests/X86/Run.cpp b/tests/X86/Run.cpp index 5c2ca677c..36c217729 100644 --- a/tests/X86/Run.cpp +++ b/tests/X86/Run.cpp @@ -96,10 +96,10 @@ extern "C" { // initial state for the lifted testcase. The lifted test case code mutates // this, and we require that after running the lifted testcase, `gLiftedState` // matches `gNativeState`, -std::aligned_storage::type gLiftedState; +std::aligned_storage::type gLiftedState; // Native state after running the native test case. -std::aligned_storage::type gNativeState; +std::aligned_storage::type gNativeState; // The RFLAGS to run the test with. Flags gRflagsForTest = {}; @@ -315,15 +315,15 @@ Memory *__remill_delay_slot_end(Memory *) { } void __remill_defer_inlining(void) {} -Memory *__remill_error(X86State &, addr_t, Memory *) { +Memory *__remill_error(State &, addr_t, Memory *) { siglongjmp(gJmpBuf, 0); } -Memory *__remill_missing_block(X86State &, addr_t, Memory *memory) { +Memory *__remill_missing_block(State &, addr_t, Memory *memory) { return memory; } -Memory *__remill_sync_hyper_call(X86State &state, Memory *mem, +Memory *__remill_sync_hyper_call(State &state, Memory *mem, SyncHyperCall::Name call) { switch (call) { case SyncHyperCall::kX86CPUID: @@ -378,19 +378,19 @@ Memory *__remill_write_io_port_32(Memory *, addr_t, uint32_t) { abort(); } -Memory *__remill_function_call(X86State &, addr_t, Memory *) { +Memory *__remill_function_call(State &, addr_t, Memory *) { abort(); } -Memory *__remill_function_return(X86State &, addr_t, Memory *) { +Memory *__remill_function_return(State &, addr_t, Memory *) { abort(); } -Memory *__remill_jump(X86State &, addr_t, Memory *) { +Memory *__remill_jump(State &, addr_t, Memory *) { abort(); } -Memory *__remill_async_hyper_call(X86State &, addr_t, Memory *) { +Memory *__remill_async_hyper_call(State &, addr_t, Memory *) { abort(); } @@ -431,7 +431,7 @@ void __remill_mark_as_used(void *mem) { } // extern C -typedef Memory *(LiftedFunc) (X86State &, addr_t, Memory *); +typedef Memory *(LiftedFunc) (State &, addr_t, Memory *); // Mapping of test name to translated function. static std::map gTranslatedFuncs; @@ -477,9 +477,9 @@ static bool AreFCSAndFDSDeprecated(void) { #endif // 32 == ADDRESS_SIZE_BITS -// Convert some native state, stored in various ways, into the `X86State` structure +// Convert some native state, stored in various ways, into the `State` structure // type. -static void ImportX87X86State(X86State *state) { +static void ImportX87State(State *state) { auto &fpu = state->x87; // Looks like MMX state. @@ -587,8 +587,8 @@ static void RunWithFlags(const test::TestInfo *info, Flags flags, memset(&gLiftedState, 0, sizeof(gLiftedState)); memset(&gNativeState, 0, sizeof(gNativeState)); - auto lifted_state = reinterpret_cast(&gLiftedState); - auto native_state = reinterpret_cast(&gNativeState); + auto lifted_state = reinterpret_cast(&gLiftedState); + auto native_state = reinterpret_cast(&gNativeState); // Set up the run's info. gTestToRun = info->test_begin; @@ -609,7 +609,7 @@ static void RunWithFlags(const test::TestInfo *info, Flags flags, native_test_faulted = true; } - ImportX87X86State(native_state); + ImportX87State(native_state); ResetFlags(); // Set up the RIP correctly. @@ -970,10 +970,10 @@ INSTANTIATE_TEST_SUITE_P(GeneralInstrTest, InstrTest, // Recover from a signal. static void RecoverFromError(int sig_num, siginfo_t *, void *context_) { if (gInNativeTest) { - memcpy(&gNativeState, &gLiftedState, sizeof(X86State)); + memcpy(&gNativeState, &gLiftedState, sizeof(State)); auto context = reinterpret_cast(context_); - auto native_state = reinterpret_cast(&gNativeState); + auto native_state = reinterpret_cast(&gNativeState); auto &gpr = native_state->gpr; auto &fpu = native_state->x87; #ifdef __APPLE__