PatchDSL

Language Concepts

Type System

The PatchDSL nomenclature is formalized in function of where information belongs using two dichotomies:

  • A physical dichotomy is made between data stored in the machine registers and data stored in memory.
  • A conceptual dichotomy is made between data belonging or generated by the target program and data belonging or generated by QBDI.

This creates four main categories of data being manipulated by the PatchDSL. These categories and the nomenclature for their interaction are represented below.

_images/patchdsl_concepts.svg
Reg:
They represent machine registers storing data created and used by the target program.
Temp:
They represent machine registers storing data used by the instrumentation. Those are temporary scratch registers which were allocated by saving a Reg into the context and are bound to be deallocated by restoring the Reg value from the context.
Context:
The context stores in memory the processor state associated with the target program. It is mostly used for context switching between the target program and the instrumentation process and also for allocating temporary registers.
Shadows:
They represent shadow data associated with a patch and instrumented instruction. They can be used by QBDI to store constants or Tagged Shadows.
Metadata:
Any data regarding the execution which can be generated by QBDI. For examples obtaining instruction operand values or memory access addresses.

The main objective of this strict naming convention is to make the distinction between pure (no side effects) operations and operations affecting the program state as clear as possible. To make this distinction even more apparent the DSL is strongly typed forcing variables to be declared by allocating one of the typed structures below with its constructor. Because some of those structures simply alias an integer value it can be tempting to directly use the integer value, letting the compiler do the implicit type conversion. However the point of those structures is to give a context to what those integer constants represent and the best practice is to use them everywhere possible.

struct QBDI::Reg

Structure representing a register variable in PatchDSL.

Public Functions

Reg(unsigned int id)

Create a new register variable.

Parameters
  • id: The id of the register to represent.

operator unsigned int()

Convert this structure to an LLVM register id.

Return
LLVM register id.

rword offset()

Return the offset of this register storage in the context part of the data block.

Return
The offset.

struct QBDI::Temp

Structure representing a temporary register variable in PatchDSL.

Public Functions

Temp(unsigned int id)

Represent a temporary register variable idenified by a unique ID. Inside a patch rules or a instrumentation rules, Temp with identical ids point to the same physical register. The id 0xFFFFFFFF is reserved for internal uses. The mapping from id to physical register is determined at generation time and the allocation and deallocation instructions are automatically added to the patch.

Parameters
  • id: The id of the temp to represent.

operator unsigned int()

Convert this Temp to its id.

Return
This Temp id.

struct QBDI::Shadow

Structure representing a shadow variable in PatchDSL.

Public Functions

Shadow(uint16_t tag)

Allocate a new shadow variable in the data block with the corresponding tag.

Parameters
  • tag: The tag of the new shadow variable.

rword getTag()

Return the tag associated with this shadow variable.

Return
The tag of the shadow variable.

struct QBDI::Constant

Structure representing a constant value in PatchDSL.

Public Functions

Constant(rword v)

Represent a constant value.

Parameters
  • v: The represented value.

operator rword()

Convert this structure to its value.

Return
This constant value.

struct QBDI::Offset

Structure representing a memory offset variable in PatchDSL.

Public Functions

Offset(int64_t offset)

Allocate a new offset variable with its offset value.

Parameters
  • offset: The offset value

Offset(Reg reg)

Allocate a new offset variable with the offset in the context of a specific register.

Parameters
  • reg: The register whose offset to represent.

operator int64_t()

Convert this structure to its value.

Return
This offset value.

struct QBDI::Operand

Structure representing an operand instruction variable in PatchDSL.

Public Functions

Operand(unsigned int idx)

Represent an operand instruction identified by its index in the LLVM MCInst representation of the instruction.

Parameters
  • idx: The operand index.

operator unsigned int()

Convert this Operand to its idx.

Return
This Operand idx.

Statements

There are three main categories of statements composing PatchDSL, each characterized by a different virtual base classes. The specialization of those base classes are PatchDSL statements.

QBDI::PatchCondition
They are used to match specific instructions. They take the instruction and its context as an input and return a boolean.
QBDI::PatchGenerator
They represent operations generating new instructions. They take the instruction and its context as an input and return a list of QBDI::RelocatableInst constituting the patch. In some exceptional cases no output is generated.
QBDI::InstTransform
They represent operations transforming an instruction. They only manipulate an instruction and need to be used with a QBDI::PatchGenerator to output a QBDI::RelocatableInst.

Those statements are all evaluated on an implicit context. In the case of QBDI::InstTransform the context is the instruction to modify which is determined by the QBDI::PatchGenerator which use it. In the case of QBDI::PatchCondition and QBDI::PatchGenerator this context is made of:

  • the current instruction
  • the current instruction size
  • the current address

The output of each statement thus depends on the statement parameters and this implicit context.

Rules

PatchDSL is used to write short sequence of statements called rules. There exists two variants of rules, patching rules (QBDI::PatchRule) and instrumentation rules (QBDI::InstrRule), but they both relies on the same principle. A rule is composed of two parts:

Condition:
A QBDI::PatchCondition statement which express the condition under which the rule should be applied. Multiple statements can be combined in a boolean expression using QBDI::Or and QBDI::And. If the evaluation of this expression returns true then the generation part of the rule is evaluated.
Generation:
A list of QBDI::PatchGenerator statements which will generate the patch rule. Each statement can output one or several QBDI::RelocatableInst, the resulting patch being the aggregation of all those statement outputs.
class QBDI::PatchRule

A patch rule written in PatchDSL.

Inherits from QBDI::AutoAlloc< PatchRule, PatchRule >

Public Functions

PatchRule(PatchCondition::SharedPtr condition, PatchGenerator::SharedPtrVec generators)

Allocate a new patch rule with a condition and a list of generators.

Parameters
  • condition: A PatchCondition which determine wheter or not this PatchRule applies.
  • generators: A vector of PatchGenerator which will produce the patch instructions.

bool canBeApplied(const llvm::MCInst *inst, rword address, rword instSize, llvm::MCInstrInfo *MCII)

Determine wheter this rule applies by evaluating this rule condition on the current context.

Return
True if this patch condition evaluate to true on this context.
Parameters
  • inst: The current instruction.
  • address: The current instruction address.
  • instSize: The current instruction size.
  • MCII: An LLVM MC instruction info context.

Patch generate(const llvm::MCInst *inst, rword address, rword instSize, llvm::MCInstrInfo *MCII, llvm::MCRegisterInfo *MRI, const Patch *toMerge = nullptr)

Generate this rule output patch by evaluating its generators on the current context. Also handles the temporary register management for this patch.

Return
A Patch which is composed of the input context and a series of RelocatableInst.
Parameters
  • inst: The current instruction.
  • address: The current instruction address.
  • instSize: The current instruction size.
  • MCII: A LLVM::MCInstrInfo classes used for internal architecture specific queries.
  • MRI: A LLVM::MCRegisterInfo classes used for internal architecture specific queries.
  • toMerge: An eventual previous patch which is to be merged with the current instruction.

class QBDI::InstrRule

An instrumentation rule written in PatchDSL.

Inherits from QBDI::AutoAlloc< InstrRule, InstrRule >

Public Functions

InstrRule(PatchCondition::SharedPtr condition, PatchGenerator::SharedPtrVec patchGen, InstPosition position, bool breakToHost)

Allocate a new instrumentation rule with a condition, a list of generators, an instrumentation position and a breakToHost request.

Parameters
  • condition: A PatchCondition which determine wheter or not this PatchRule applies.
  • patchGen: A vector of PatchGenerator which will produce the patch instructions.
  • position: An enum indicating wether this instrumentation should be positioned before the instruction or after it.
  • breakToHost: A boolean determining whether this instrumentation should end with a break to host (in the case of a callback for example).

bool canBeApplied(const Patch &patch, llvm::MCInstrInfo *MCII)

Determine wheter this rule applies by evaluating this rule condition on the current context.

Return
True if this instrumentation condition evaluate to true on this patch.
Parameters
  • patch: A patch containing the current context.
  • MCII: An LLVM MC instruction info context.

void instrument(Patch &patch, llvm::MCInstrInfo *MCII, llvm::MCRegisterInfo *MRI)

Instrument a patch by evaluating its generators on the current context. Also handles the temporary register management for this patch.

Parameters
  • patch: The current patch to instrument.
  • MCII: A LLVM::MCInstrInfo classes used for internal architecture specific queries.
  • MRI: A LLVM::MCRegisterInfo classes used for internal architecture specific queries.

Transforms

Transform statements, with the QBDI::InstTransform virtual base class, are a bit more subtle than other statements.

Currently their operation is limited to the QBDI::ModifyInstruction generators which always operate on the instruction of the implicit context of a patch or instrumentation rule. However their usage could be extended in the future.

Their purpose is to allow to write more generic rules by allowing modifications which can operate on a class of instructions. Using instruction transforms requires to understand the underlying LLVM MCInst representation of an instruction and llvm-mc -show-inst is an helpful tool for this task.

PatchDSL Examples

Below some real examples of patch and instrumentation rules are shown.

Basic Patching

Generic PC Substitution Patch Rule

Instructions using the Program Counter (PC) in their computations are problematic because QBDI will reassemble and execute the code at another address than the original code location and thus the value of the PC will change. This kind of computation using the PC is often found when using relative memory addressing.

Some cases can be more difficult to handle, but most of these instructions can be patched using a very simple generic rule performing the following steps:

  1. Allocate a scratch register by saving a register value in the context part of the data block.
  2. Load the value the PC register should have, into the scratch register.
  3. Perform the original instruction but with PC replaced by the scratch register.
  4. Deallocate the scratch register by restoring the register value from context part of the data block.

The PatchDSL QBDI::PatchRule handles step 1 and 4 automatically for us. Expressing step 2 and 3 is relatively simple:

PatchRule(
    // Condition: Applies on every instruction using the register REG_PC
    UseReg(Reg(REG_PC)),
    // Generators: list of statements generating the patch
    {
        // Compute PC + 0 and store it in a new temp with id 0
        GetPCOffset(Temp(0), Constant(0)),
        // Modify the instruction by substituting REG_PC with the temp having id 0
        ModifyInstruction({
            SubstituteWithTemp(Reg(REG_PC), Temp(0))
        })
    }
)

This rule is generic and works under X86_64 as well as ARM. Some more complex cases of instructions using PC need to be handled another way though.

Simple Branching Instruction Patch

Another simple case which needs to be handled using a patch rule is branching instructions. They cannot be executed because that would mean DBI process would lose the hand on the execution. Instead of executing the branch operation, the branch target is computed and used to overwrite the value of the PC in the context part of the data block. This is followed by a context switch back to the VM which will use this target as the address where to continue the execution.

The simplest cases are the “branch to an address stored in a register” instructions. Again the temporary register allocation is automatically taken care of by the QBDI::PatchRule and we only need to write the patching logic:

PatchRule(
    // Condition: only on BX or BX_pred LLVM MCInst
    Or({
        OpIs(llvm::ARM::BX),
        OpIs(llvm::ARM::BX_pred)
    }),
    // Generators
    {
        // Obtain the value of the operand with index 0 and store it in a new temp with id 0
        GetOperand(Temp(0), Operand(0)),
        // Write the temp with id 0 at the offset in the data block of the context value of REG_PC.
        WriteTemp(Temp(0), Offset(Reg(REG_PC)))
    }
)

Two things are important to notice here. First we use QBDI::Or to combine multiple QBDI::PatchCondition. Second the fact we need to stop the execution here and switch back to the context of the VM is not expressed in the patch. Indeed the patching engine simply notices that this patch overwrites the value of the PC and thus needs to end the basic block after it.

Advanced Patching

Conditional Branching Instruction Patch

The previous section dealt with simple patching cases where the rule does not need to be very complex. Conditional instructions can add a significant amount of complexity to the writing of a patch rules and requires some tricks. Below is the patch for the ARM conditional branching instruction:

PatchRule(
    // Condition: every Bcc instructions (e.g. BNE, BEQ, etc.)
    OpIs(llvm::ARM::Bcc),
    // Generators
    {
        // Compute the Bcc target (which is PC relative) and store it in a new temp with id 0
        GetPCOffset(Temp(0), Operand(0)),
        // Modify the jump target such as it potentially skips the next generator
        ModifyInstruction({
            SetOperand(Operand(0), Constant(0))
        }),
        // Compute the next instruction address and store it in temp with id 0
        GetPCOffset(Temp(0), Constant(-4)),
        // At this point either:
        //  * The jump was not taken and Temp(0) stores the next instruction address.
        //  * The jump was taken and Temp(0) stores the Bcc target
        // We thus write Temp(0) which has the correct next address to execute in the REG_PC
        // value in the context part of the data block.
        WriteTemp(Temp(0), Offset(Reg(REG_PC)))
    }
)

As we can see, this code reuses the original conditional branching instruction to create a conditional move. While this is a trick, it is an architecture independent trick which is also used under X86_64. Some details can be noted though. First the next instruction address is PC - 4 which is an ARM specificity. Secondly, the constant used to overwrite the jump target needs to be determined by hand as QBDI does not have the capacity to compute it automatically.

Complex InstTransform

The patch below is used to patch instructions which load their branching target from a memory address under X86_64. It exploits QBDI::InstTransform to convert the instruction into a load from memory to obtain this branching target:

PatchRule(
    // Condition: applies on CALL where the target is at a relative memory location (thus uses REG_PC)
    And({
        OpIs(llvm::X86::CALL64m),
        UseReg(Reg(REG_PC))
    }),
    // Generators
    {
        // First compute PC + 0 and stores it into a new temp with id 0
        GetPCOffset(Temp(0), Constant(0)),
        // Transforms the CALL *[RIP + ...] into MOV Temp(1), *[Temp(0) + ...]
        ModifyInstruction({
            // RIP is replaced with Temp(0)
            SubstituteWithTemp(Reg(REG_PC), Temp(0)),
            // The opcode is changed to a 64 bits MOV from memory to a register
            SetOpcode(llvm::X86::MOV64rm),
            // We insert the destination register, a new temp with id 1,  at the beginning of
            // the operand list
            AddOperand(Operand(0), Temp(1))
        }),
        // Temp(1) thus contains the CALL target.
        // We use the X86_64 specific SimulateCall with this target.
        SimulateCall(Temp(1))
    }
)

A few things need to be noted. First the sequence of QBDI::InstTransform is complex because it substitutes RIP and it mutates the CALL into a MOV. Secondly, new QBDI::Temp can be instantiated and used anywhere in the program. Lastly, some complex architecture specific mechanisms have been abstracted in single QBDI::PatchGenerator, like QBDI::SimulateCall.

Instrumentation Callbacks

QBDI::InstrRule allows to insert inline instrumentation inside the patch with a concept similar to the rules shown previously. Callbacks to host code are triggered by a break to host with specific variables set correctly in the host state part of the context:

  • the hostState.callback should be set to the callback function address to call.
  • the hostState.data should be set to the callback function data parameter.
  • the hostState.origin should be set to the ID of the current instruction (see QBDI::GetInstId).

In practice, there exists a function which can generate the PatchGenerator needed to setup those variables correctly:

PatchGenerator::SharedPtrVec QBDI::getCallbackGenerator(InstCallback cbk, void *data)

Output a list of PatchGenerator which would set up the host state part of the context for a callback.

Return
A list of PatchGenerator to set up this callback call.
Parameters
  • cbk: The callback function to call.
  • data: The data to pass as an argument to the callback function.

Thus, in practice, a QBDI::InstrRule which would set up a callback on every instruction writing data in memory would look like this:

InstrRule(
    // Condition: on every instruction making write access
    DoesWriteAccess(),
    // Generators: set up a callback to someCallbackFunction with someParameter
    getCallbackGenerator(someCallbackFunction, someParameter),
    // Position this instrumentation after the instruction
    InstPosition::POSTINST,
    // Break to the host after the instrumentation (required for the callback to be made)
    true
));

However the callback generator can be written directly in PatchDSL for more advantageous usages. The instrumentation rules below pass directly the written data as the callback parameter:

InstrRule(
    // Condition: on every instruction making write access
    DoesWriteAccess(),
    // Generators: set up a callback to someCallbackFunction with someParameter
    {
        // Set hostState.callback to the callback function address
        GetConstant(Temp(0), Constant((rword) someCallbackFunction)),
        WriteTemp(Temp(0), Offset(offsetof(Context, hostState.callback))),
        // Set hostState.data as the written value
        GetWriteValue(Temp(0)),
        WriteTemp(Temp(0), Offset(offsetof(Context, hostState.data))),
        // Set hostState.origin as the current instID
        GetInstId(Temp(0)),
        WriteTemp(Temp(0), Offset(offsetof(Context, hostState.origin)))
    }
    // Position this instrumentation after the instruction
    QBDI::InstPosition::POSTINST,
    // Break to the host after the instrumentation (required for the callback to be made)
    true
));

PatchDSL Reference

PatchConditions

Boolean Arithmetic Operators

  • QBDI::And
  • QBDI::Or
  • QBDI::Not
  • QBDI::True
QBDI::And::And(PatchCondition::SharedPtrVec conditions)

Return true if every PatchCondition of the list conditions return true (lazy evaluation).

Parameters
  • conditions: List of conditions to evaluate.

QBDI::Or::Or(PatchCondition::SharedPtrVec conditions)

Return true if one of the PatchCondition of the list conditions return true (lazy evaluation).

Parameters
  • conditions: List of conditions to evaluate.

QBDI::Not::Not(PatchCondition::SharedPtr condition)

Return the logical inverse of condition.

Parameters
  • condition: Condition to evaluate.

QBDI::True::True()

Return true.

Instruction Conditions

  • QBDI::OpIs
  • QBDI::RegIs
  • QBDI::UseReg
  • QBDI::AddressInRange
  • QBDI::OperandIsReg
  • QBDI::OperandIsImm
QBDI::OpIs::OpIs(unsigned int op)

Return true if the instruction opcode is equal to op.

Parameters
  • op: LLVM instruction opcode ID.

QBDI::RegIs::RegIs(Operand opn, Reg reg)

Return true if the instruction operand with index opn is a register equal to reg.

Parameters
  • opn: The instruction operand.
  • reg: The register to compare with.

QBDI::UseReg::UseReg(Reg reg)

Return true if the instruction uses reg as one of its operand.

Parameters
  • reg: The register to compare with.

QBDI::InstructionInRange::InstructionInRange(Constant start, Constant end)

Return true if the instruction address is in the range [start, end[ (end not included).

Parameters
  • start: Start of the range.
  • end: End of the range (not included).

QBDI::OperandIsReg::OperandIsReg(Operand opn)

Return true if the instruction operand opn is a register.

Parameters
  • opn: The instruction operand.

QBDI::OperandIsImm::OperandIsImm(Operand opn)

Return true if the instruction operand opn is an immediate.

Parameters
  • opn: The instruction operand.

Memory Access Conditions

  • QBDI::DoesReadAccess
  • QBDI::DoesWriteAccess
  • QBDI::ReadAccessSizeIs
  • QBDI::WriteAccessSizeIs
  • QBDI::IsStackRead
  • QBDI::IsStackWrite
QBDI::DoesReadAccess::DoesReadAccess()

Return true if the instruction read data from memory.

QBDI::DoesWriteAccess::DoesWriteAccess()

Return true if the instruction write data to memory.

QBDI::ReadAccessSizeIs::ReadAccessSizeIs(Constant size)

Return true if the instruction read access size equal to size.

Parameters
  • size: Size to compare with.

QBDI::WriteAccessSizeIs::WriteAccessSizeIs(Constant size)

Return true if the instruction write access size equal to size.

Parameters
  • size: Size to compare with.

QBDI::IsStackRead::IsStackRead()

Return true if the instruction is reading data from the stack.

QBDI::IsStackWrite::IsStackWrite()

Return true if the instruction is writing data to the stack.

PatchGenerators

Registry and Temporary Operations

  • QBDI::LoadReg
  • QBDI::SaveReg
  • QBDI::CopyReg
  • QBDI::WriteTemp
QBDI::LoadReg::LoadReg(Reg reg, Offset offset)

Load a register from the data block at the specified offset. This can be used to load register values from the context part of the data block.

Parameters
  • reg: A register where the value will be loaded.
  • offset: The offset in the data block from where the value will be loaded.

QBDI::SaveReg::SaveReg(Reg reg, Offset offset)

Save a register in the data block at the specified offset. This can be used to save register values in the context part of the data block.

Parameters
  • reg: A register which will be saved.
  • offset: The offset in the data block where the register will be written.

QBDI::CopyReg::CopyReg(Temp temp, Reg reg)

Copy a register in a temporary.

Parameters
  • temp: A temporary where the register will be copied.
  • reg: The register which will be copied

QBDI::WriteTemp::WriteTemp(Temp temp, Offset offset)

Write a temporary value in the data block at the specified offset. This can be used to overwrite register values in the context part of the data block.

Parameters
  • temp: A temporary which will be written.
  • offset: The offset in the data block where the temporary will be written.

QBDI::WriteTemp::WriteTemp(Temp temp, Shadow shadow)

Write a temporary value in a shadow in the data block.

Parameters
  • temp: A temporary which will be written.
  • shadow: The shadow use to store the value.

Instruction Information Queries

  • QBDI::GetOperand
  • QBDI::GetConstant
  • QBDI::GetPCOffset
QBDI::GetOperand::GetOperand(Temp temp, Operand op)

Obtain the value of the operand op and copy it’s value in a temporary. If op is an immediate the immediate value is copied, if op is a register the register value is copied.

Parameters
  • temp: A temporary where the value will be copied.
  • op: The operand index (relative to the instruction LLVM MCInst representation) to be copied.

QBDI::GetConstant::GetConstant(Temp temp, Constant cst)

Copy a constant in a temporary.

Parameters
  • temp: A temporary where the value will be copied.
  • cst: The constant to copy.

QBDI::GetPCOffset::GetPCOffset(Temp temp, Constant cst)

Interpret a constant as a PC relative offset and copy it in a temporary. It can be used to obtain the current value of PC by using a constant of 0.

Parameters
  • temp: A temporary where the value will be copied.
  • cst: The constant to be used.

QBDI::GetPCOffset::GetPCOffset(Temp temp, Operand op)

Interpret an operand as a PC relative offset and copy it in a temporary. It can be used to obtain jump/call targets or relative memory access addresses.

Parameters
  • temp: A temporary where the value will be copied.
  • op: The operand index (relative to the instruction LLVM MCInst representation) to be used.

Memory Access Information Queries

  • QBDI::GetReadAddress
  • QBDI::GetWriteAddress
  • QBDI::GetReadValue
  • QBDI::GetWriteValue
QBDI::GetReadAddress::GetReadAddress(Temp temp)

Resolve the memory address where the instructions will read its value and copy the address in a temporary. This PatchGenerator is only guaranteed to work before the instruction has been executed.

Parameters
  • temp: A temporary where the memory address will be copied.

QBDI::GetWriteAddress::GetWriteAddress(Temp temp)

Resolve the memory address where the instructions will write its value and copy the address in a temporary. This PatchGenerator is only guaranteed to work before the instruction has been executed.

Parameters
  • temp: A temporary where the memory address will be copied.

QBDI::GetReadValue::GetReadValue(Temp temp)

Resolve the memory address where the instructions will read its value and copy the value in a temporary. This PatchGenerator is only guaranteed to work before the instruction has been executed.

Parameters
  • temp: A temporary where the memory value will be copied.

QBDI::GetWriteValue::GetWriteValue(Temp temp)

Resolve the memory address where the instructions has written its value and copy back the value in a temporary. This PatchGenerator is only guaranteed to work after the instruction has been executed.

Parameters
  • temp: A temporary where the memory value will be copied.

Special

  • QBDI::ModifyInstruction
  • QBDI::DoNotInstrument
QBDI::ModifyInstruction::ModifyInstruction(InstTransform::SharedPtrVec transforms)

Apply a list of InstTransform to the current instruction and output the result.

Parameters
  • transforms: Vector of InstTransform to be applied.

QBDI::DoNotInstrument::DoNotInstrument()

Adds a “do not instrument” flag to the resulting patch which allows it to skip the instrumentation process of the engine.

X86_64 Specific

  • QBDI::SimulateCall
  • QBDI::SimulateRet
QBDI::SimulateCall::SimulateCall(Temp temp)

Simulate the effects of a call to the address stored in a temporary. The target address overwrites the stored value of RIP in the context part of the data block and the return address is pushed onto the stack. This generator signals a PC modification and triggers and end of basic block.

Parameters
  • temp: Stores the call target address. Overwritten by this generator.

QBDI::SimulateRet::SimulateRet(Temp temp)

Simulate the effects of a return instruction. First the return address is popped from the stack into a temporary, then an optional stack deallocation is performed and finally the return address is written in the stored value of RIP in the context part of the data block. This generator signals a PC modification and triggers an end of basic block.

The optional deallocation is performed if the current instruction has one single immediate operand (which is the case of RETIQ and RETIW).

Parameters
  • temp: Any unused temporary, overwritten by this generator.

ARM Specific

  • QBDI::SimulateLink
  • QBDI::SimulatePopPC
QBDI::SimulateLink::SimulateLink(Temp temp)

Simulate the effects of the link operation performed by BL and BLX instructions: the address of the next instruction is copied into the LR register. A temp and a shadow are needed to compute this address.

Parameters
  • temp: Any unused temporary, overwritten by this generator.

QBDI::SimulatePopPC::SimulatePopPC(Temp temp)

Simulate an (eventually conditional) return instruction (POPcc PC). The conditional code of the current instruction is used by this generator. This generator signals a PC modification and triggers an end of basic block.

Parameters
  • temp: Any unused temporary, overwritten by this generator.

Internals

  • QBDI::GetInstId
  • QBDI::JmpEpilogue
QBDI::GetInstId::GetInstId(Temp temp)

Copy an ExecBlock specific id for the current instruction in a temporary. This id is used to identify the instruction responsible for a callback in the engine and is only meant for internal use.

Parameters
  • temp: A temporary where the id will be copied.

QBDI::JmpEpilogue::JmpEpilogue()

Generate a jump instruction which target the epilogue of the ExecBlock.

InstTransform

  • QBDI::SetOperand
  • QBDI::AddOperand
  • QBDI::SubstituteWithTemp
  • QBDI::RemoveOperand
  • QBDI::SetOpcode
QBDI::SetOperand::SetOperand(Operand opn, Temp temp)

Set the operand opn of the instruction as the Temp temp.

Parameters
  • opn: Operand index in the LLVM MCInst representation.
  • temp: Temporary register which will be set as the new operand

QBDI::SetOperand::SetOperand(Operand opn, Reg reg)

Set the operand opn of the instruction as the Reg reg.

Parameters
  • opn: Operand index in the LLVM MCInst representation.
  • reg: Register which will be set as the new operand.

QBDI::SetOperand::SetOperand(Operand opn, Constant imm)

Set the operand opn of the instruction as the immediate imm.

Parameters
  • opn: Operand index in the LLVM MCInst representation.
  • imm: Constant which will be set as the new immediate operand.

QBDI::AddOperand::AddOperand(Operand opn, Temp temp)

Add a new temporary register operand to the instruction by inserting it at operand index opn.

Parameters
  • opn: Operand index in LLVM MCInst representation.
  • temp: Temp to be inserted as a new operand.

QBDI::AddOperand::AddOperand(Operand opn, Reg reg)

Add a new register operand to the instruction by inserting it at operand index opn.

Parameters
  • opn: Operand index in LLVM MCInst representation.
  • reg: Register to be inserted as a new operand.

QBDI::AddOperand::AddOperand(Operand opn, Constant imm)

Add a new immediate operand to the instruction by inserting it at operand index opn.

Parameters
  • opn: Operand index in LLVM MCInst representation.
  • imm: Constant to be inserted as a new immediate operand.

QBDI::SubstituteWithTemp::SubstituteWithTemp(Reg reg, Temp temp)

Substitute every reference to reg in the operands of the instruction with temp.

Parameters
  • reg: Register which will be substituted.
  • temp: Temporary register which will be substituted with.

QBDI::RemoveOperand::RemoveOperand(Reg reg)

Remove the first occurence of reg in the operands of the instruction.

Parameters
  • reg: Register to remove from the operand list.

QBDI::SetOpcode::SetOpcode(unsigned int opcode)

Set the opcode of the instruction.

Parameters
  • opcode: New opcode to set as the instruction opcode.