Skip to content

Commit

Permalink
Populate the register table even in the absence of semantics (#558)
Browse files Browse the repository at this point in the history
* Populate the register table even in the absence of semantics

* Modify the test suite
  • Loading branch information
Peter Goodman authored Nov 2, 2021
1 parent 1efcf89 commit 769c280
Show file tree
Hide file tree
Showing 17 changed files with 382 additions and 247 deletions.
4 changes: 2 additions & 2 deletions include/remill/Arch/AArch32/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -115,6 +115,6 @@ struct alignas(16) State final : public ArchState {

} __attribute__((packed));

using AArch32State = State;
struct State : public AArch32State {};

#pragma clang diagnostic pop
6 changes: 3 additions & 3 deletions include/remill/Arch/AArch64/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
17 changes: 9 additions & 8 deletions include/remill/Arch/Arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ struct Register {

// The directly enclosed registers.
std::vector<const Register *> children;

void CompteGEPAccessors(const llvm::DataLayout &dl, llvm::Type *state_type);
};

class Arch {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -281,18 +283,16 @@ 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);

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;
Expand Down Expand Up @@ -324,9 +324,10 @@ class Arch {
static ArchPtr GetSPARC64(llvm::LLVMContext *context, OSName os,
ArchName arch_name);

mutable std::unique_ptr<ArchImpl> impl;

Arch(void) = delete;

protected:
mutable std::unique_ptr<ArchImpl> impl;
};

} // namespace remill
4 changes: 2 additions & 2 deletions include/remill/Arch/SPARC32/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -349,6 +349,6 @@ struct alignas(16) State : public ArchState {
#endif
};

using SPARCState = State;
struct State : public SPARC32State {};

#pragma clang diagnostic pop
4 changes: 2 additions & 2 deletions include/remill/Arch/SPARC64/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -358,6 +358,6 @@ struct alignas(16) State : public ArchState {
#endif
};

using SPARCState = State;
struct State : public SPARC64State {};

#pragma clang diagnostic pop
6 changes: 3 additions & 3 deletions include/remill/Arch/X86/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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;
Expand Down
54 changes: 30 additions & 24 deletions lib/Arch/AArch32/Arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@

// clang-format on

#include "../Arch.h" // For `ArchImpl`.

namespace remill {

AArch32Arch::AArch32Arch(llvm::LLVMContext *context_, OSName os_name_,
Expand Down Expand Up @@ -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<uintptr_t>(&reinterpret_cast<const volatile char &>( \
static_cast<type *>(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);
Expand All @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion lib/Arch/AArch32/Arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
47 changes: 30 additions & 17 deletions lib/Arch/AArch64/Arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -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<uintptr_t>(&reinterpret_cast<const volatile char &>( \
Expand All @@ -166,26 +171,18 @@ 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);
auto v128u32 = llvm::ArrayType::get(u32, 128u / 32u);
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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 769c280

Please sign in to comment.