Skip to content

Commit 854c73e

Browse files
authored
Ian/instruction carry lifter (#615)
* add lifter field * arch has intrinsics * use insn lifter in trace lifter * limit default lifters to ops only * init lifters * pass arch in tests * fix bug in swap * stop using archbase decode in sleigh arches
1 parent 5f79f40 commit 854c73e

File tree

23 files changed

+195
-127
lines changed

23 files changed

+195
-127
lines changed

bin/lift/Lift.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ int main(int argc, char *argv[]) {
269269

270270
auto inst_lifter = arch->DefaultLifter(intrinsics);
271271

272-
remill::TraceLifter trace_lifter(*inst_lifter.get(), manager);
272+
remill::TraceLifter trace_lifter(arch.get(), manager);
273273

274274
// Lift all discoverable traces starting from `--entry_address` into
275275
// `module`.

include/remill/Arch/Arch.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <llvm/IR/DataLayout.h>
3030
#include <llvm/IR/IRBuilder.h>
3131
#include <remill/BC/InstructionLifter.h>
32+
#include <remill/BC/IntrinsicTable.h>
3233

3334
#pragma clang diagnostic pop
3435

@@ -200,6 +201,8 @@ class Arch {
200201
virtual llvm::StructType *RegisterWindowType(void) const = 0;
201202

202203

204+
virtual const IntrinsicTable *GetInstrinsicTable(void) const = 0;
205+
203206
virtual unsigned RegMdID(void) const = 0;
204207

205208
// Apply `cb` to every register.
@@ -257,9 +260,9 @@ class Arch {
257260
void PrepareModuleDataLayout(llvm::Module *mod) const;
258261

259262

260-
// TODO(Ian): This is kinda messy but only an arch currently knows if it is
261-
// sleigh or not and sleigh needs different lifting context etc.
262-
virtual InstructionLifter::LifterPtr
263+
// A default lifter does not know how to lift instructions. The default lifter allows
264+
// the user to perform instruction/context independent lifting operations.
265+
virtual OperandLifter::OpLifterPtr
263266
DefaultLifter(const remill::IntrinsicTable &intrinsics) const = 0;
264267

265268
inline void

include/remill/Arch/ArchBase.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ struct Register;
3333

3434
// Internal base architecture for all Remill-internal architectures.
3535
class ArchBase : public remill::Arch {
36+
protected:
37+
virtual bool ArchDecodeInstruction(uint64_t address,
38+
std::string_view instr_bytes,
39+
Instruction &inst) const = 0;
40+
3641
public:
3742
using ArchPtr = std::unique_ptr<const Arch>;
3843

@@ -64,11 +69,14 @@ class ArchBase : public remill::Arch {
6469
// Return information about a register, given its name.
6570
const Register *RegisterByName(std::string_view name) const final;
6671

72+
const IntrinsicTable *GetInstrinsicTable(void) const final;
73+
6774
unsigned RegMdID(void) const final;
6875

69-
// TODO(Ian): This is kinda messy but only an arch currently knows if it is
70-
// sleigh or not and sleigh needs different lifting context etc.
71-
InstructionLifter::LifterPtr
76+
virtual bool DecodeInstruction(uint64_t address, std::string_view instr_bytes,
77+
Instruction &inst) const override;
78+
79+
OperandLifter::OpLifterPtr
7280
DefaultLifter(const remill::IntrinsicTable &intrinsics) const override;
7381

7482
// Get the state pointer and various other types from the `llvm::LLVMContext`
@@ -103,6 +111,7 @@ class ArchBase : public remill::Arch {
103111
mutable std::vector<std::unique_ptr<Register>> registers;
104112
mutable std::vector<const Register *> reg_by_offset;
105113
mutable std::unordered_map<std::string, const Register *> reg_by_name;
114+
mutable std::unique_ptr<IntrinsicTable> instrinsics{nullptr};
106115
};
107116

108117
} // namespace remill

include/remill/Arch/Instruction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#pragma once
1818

19+
#include <remill/BC/InstructionLifter.h>
20+
1921
#include <string>
2022
#include <variant>
2123
#include <vector>
@@ -349,7 +351,13 @@ class Instruction {
349351
Operand &EmplaceOperand(const Operand::ShiftRegister &op);
350352
Operand &EmplaceOperand(const Operand::Address &op);
351353

354+
355+
const InstructionLifter::LifterPtr &GetLifter();
356+
357+
void SetLifter(InstructionLifter::LifterPtr lifter);
358+
352359
private:
360+
InstructionLifter::LifterPtr lifter;
353361
static constexpr auto kMaxNumExpr = 64u;
354362
OperandExpression exprs[kMaxNumExpr];
355363
unsigned next_expr_index{0};

include/remill/BC/InstructionLifter.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,30 @@ enum LiftStatus {
5151
kLiftedInstruction
5252
};
5353

54+
// Instruction independent lifting
55+
class OperandLifter {
56+
public:
57+
using OpLifterPtr = std::shared_ptr<OperandLifter>;
58+
59+
// Load the address of a register.
60+
virtual std::pair<llvm::Value *, llvm::Type *>
61+
LoadRegAddress(llvm::BasicBlock *block, llvm::Value *state_ptr,
62+
std::string_view reg_name) const = 0;
63+
64+
// Load the value of a register.
65+
virtual llvm::Value *LoadRegValue(llvm::BasicBlock *block,
66+
llvm::Value *state_ptr,
67+
std::string_view reg_name) const = 0;
68+
69+
virtual llvm::Type *GetMemoryType() = 0;
70+
};
71+
5472
// Wraps the process of lifting an instruction into a block. This resolves
5573
// the intended instruction target to a function, and ensures that the function
5674
// is called with the appropriate arguments.
57-
class InstructionLifter {
75+
class InstructionLifter : public OperandLifter {
5876
public:
59-
using LifterPtr = std::unique_ptr<InstructionLifter>;
77+
using LifterPtr = std::shared_ptr<InstructionLifter>;
6078

6179
virtual ~InstructionLifter(void);
6280

@@ -83,17 +101,17 @@ class InstructionLifter {
83101
// Load the address of a register.
84102
std::pair<llvm::Value *, llvm::Type *>
85103
LoadRegAddress(llvm::BasicBlock *block, llvm::Value *state_ptr,
86-
std::string_view reg_name) const;
104+
std::string_view reg_name) const override final;
87105

88106
// Load the value of a register.
89107
llvm::Value *LoadRegValue(llvm::BasicBlock *block, llvm::Value *state_ptr,
90-
std::string_view reg_name) const;
108+
std::string_view reg_name) const override final;
91109

92110
// Clear out the cache of the current register values/addresses loaded.
93111
void ClearCache(void) const;
94112

95113

96-
llvm::Type *GetMemoryType();
114+
virtual llvm::Type *GetMemoryType() override final;
97115

98116
protected:
99117
// Lift an operand to an instruction.

include/remill/BC/TraceLifter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ class TraceLifter {
8686
public:
8787
~TraceLifter(void);
8888

89-
inline TraceLifter(InstructionLifter &inst_lifter_, TraceManager &manager_)
90-
: TraceLifter(&inst_lifter_, &manager_) {}
89+
inline TraceLifter(const Arch *arch_, TraceManager &manager_)
90+
: TraceLifter(arch_, &manager_) {}
9191

92-
TraceLifter(InstructionLifter *inst_lifter_, TraceManager *manager_);
92+
TraceLifter(const Arch *arch_, TraceManager *manager_);
9393

9494
static void NullCallback(uint64_t, llvm::Function *);
9595

lib/Arch/AArch32/Arch.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class AArch32Arch final : public AArch32ArchBase {
2626

2727
virtual ~AArch32Arch(void);
2828

29-
bool DecodeInstruction(uint64_t address, std::string_view inst_bytes,
30-
Instruction &inst) const override;
29+
bool ArchDecodeInstruction(uint64_t address, std::string_view inst_bytes,
30+
Instruction &inst) const override;
3131

3232
private:
3333
AArch32Arch(void) = delete;

0 commit comments

Comments
 (0)