Skip to content

Commit

Permalink
Add partial support for an ultra-lightweight profile
Browse files Browse the repository at this point in the history
Where Capstone only understands the small subset of instructions that
Frida needs for its relocators.
  • Loading branch information
oleavr committed Jan 18, 2024
1 parent b2d7ab1 commit cc7d686
Show file tree
Hide file tree
Showing 22 changed files with 320 additions and 24 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@ android-ndk-*

# python virtual env
.venv/

# Meson
/subprojects/fadec/
22 changes: 22 additions & 0 deletions arch/AArch64/AArch64Disassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#include "AArch64Linkage.h"
#include "AArch64Mapping.h"

#ifndef CAPSTONE_TINY

#define GET_INSTRINFO_MC_DESC
#include "AArch64GenInstrInfo.inc"

Expand Down Expand Up @@ -2157,3 +2159,23 @@ static DecodeStatus DecodePRFMRegInstruction(MCInst *Inst, uint32_t insn,

return Success;
}

#else

DecodeStatus AArch64_LLVM_getInstruction(csh handle, const uint8_t *Bytes,
size_t ByteLen, MCInst *MI, uint16_t *Size, uint64_t Address,
void *Info)
{
if (ByteLen < 4) {
// not enough data
*Size = 0;
return MCDisassembler_Fail;
}

MCInst_setOpcode(MI, AArch64_INS_ALIAS_END);
*Size = 4;

return MCDisassembler_Success;
}

#endif
13 changes: 13 additions & 0 deletions arch/AArch64/AArch64InstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "AArch64Linkage.h"
#include "AArch64Mapping.h"

#ifndef CAPSTONE_TINY

#define GET_BANKEDREG_IMPL
#include "AArch64GenSystemOperands.inc"

Expand Down Expand Up @@ -2792,3 +2794,14 @@ const char *AArch64_LLVM_getRegisterName(unsigned RegNo, unsigned AltIdx) {
void AArch64_LLVM_printInstruction(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) {
printInst(MI, MI->address, "", O);
}

#else

const char *AArch64_LLVM_getRegisterName(unsigned RegNo, unsigned AltIdx) {
return NULL;
}

void AArch64_LLVM_printInstruction(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) {
}

#endif
35 changes: 32 additions & 3 deletions arch/AArch64/AArch64Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "AArch64Linkage.h"
#include "AArch64Mapping.h"

#ifndef CAPSTONE_TINY

#ifndef CAPSTONE_DIET
static aarch64_reg aarch64_flag_regs[] = {
AArch64_REG_NZCV,
Expand Down Expand Up @@ -86,7 +88,7 @@ void AArch64_init_mri(MCRegisterInfo *MRI)
AArch64RegDiffLists, 0, AArch64SubRegIdxLists, ARR_SIZE(AArch64SubRegIdxLists), 0);
}

const insn_map aarch64_insns[] = {
static const insn_map aarch64_insns[] = {
#include "AArch64GenCSMappingInsn.inc"
};

Expand Down Expand Up @@ -223,6 +225,8 @@ const char *AArch64_reg_name(csh handle, unsigned int reg)
return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);
}

#endif

void AArch64_setup_op(cs_aarch64_op *op)
{
memset(op, 0, sizeof(cs_aarch64_op));
Expand All @@ -241,6 +245,8 @@ void AArch64_init_cs_detail(MCInst *MI)
}
}

#ifndef CAPSTONE_TINY

/// Unfortunately, the AArch64 definitions do not indicate in any way
/// (exception are the instruction identifiers), if memory accesses
/// is post- or pre-indexed.
Expand Down Expand Up @@ -625,12 +631,12 @@ aarch64_insn AArch64_map_insn(const char *name)
return AArch64_INS_INVALID;
}

#ifndef CAPSTONE_DIET

static const map_insn_ops insn_operands[] = {
#include "AArch64GenCSMappingInsnOp.inc"
};

#ifndef CAPSTONE_DIET

void AArch64_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count)
Expand Down Expand Up @@ -1420,7 +1426,9 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
}
AArch64_get_detail_op(MI, 0)->type = AArch64_OP_IMM;
AArch64_get_detail_op(MI, 0)->imm = prfop;
#ifndef CAPSTONE_DIET
AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
#endif
AArch64_inc_op_count(MI);
break;
}
Expand Down Expand Up @@ -2300,4 +2308,25 @@ void AArch64_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Imm)
insert_op(MI, index, op);
}

#else

void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
{
}

void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
{
}

bool AArch64_getInstruction(csh handle, const uint8_t *code, size_t code_len,
MCInst *MI, uint16_t *size, uint64_t address,
void *info)
{
AArch64_init_cs_detail(MI);
return AArch64_LLVM_getInstruction(handle, code, code_len, MI, size, address,
info) != MCDisassembler_Fail;
}

#endif

#endif
8 changes: 5 additions & 3 deletions arch/AArch64/AArch64Module.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@

cs_err AArch64_global_init(cs_struct *ud)
{
#ifndef CAPSTONE_TINY
MCRegisterInfo *mri;
mri = cs_mem_malloc(sizeof(*mri));

AArch64_init_mri(mri);
ud->printer = AArch64_printer;
ud->printer_info = mri;
ud->getinsn_info = mri;
ud->disasm = AArch64_getInstruction;
ud->reg_name = AArch64_reg_name;
ud->insn_id = AArch64_get_insn_id;
ud->insn_name = AArch64_insn_name;
ud->group_name = AArch64_group_name;
ud->post_printer = NULL;
#endif
ud->printer = AArch64_printer;
ud->disasm = AArch64_getInstruction;
ud->insn_id = AArch64_get_insn_id;
#ifndef CAPSTONE_DIET
ud->reg_access = AArch64_reg_access;
#endif
Expand Down
79 changes: 79 additions & 0 deletions arch/ARM/ARMDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "ARMDisassemblerExtension.h"
#include "ARMMapping.h"

#ifndef CAPSTONE_TINY

#define GET_INSTRINFO_MC_DESC
#include "ARMGenInstrInfo.inc"

Expand Down Expand Up @@ -1200,11 +1202,15 @@ DecodeStatus getThumbInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen,
return MCDisassembler_Fail;
}

#endif

static const uint16_t GPRDecoderTable[] = { ARM_R0, ARM_R1, ARM_R2, ARM_R3,
ARM_R4, ARM_R5, ARM_R6, ARM_R7,
ARM_R8, ARM_R9, ARM_R10, ARM_R11,
ARM_R12, ARM_SP, ARM_LR, ARM_PC };

#ifndef CAPSTONE_TINY

static const uint16_t CLRMGPRDecoderTable[] = {
ARM_R0, ARM_R1, ARM_R2, ARM_R3, ARM_R4, ARM_R5, ARM_R6, ARM_R7,
ARM_R8, ARM_R9, ARM_R10, ARM_R11, ARM_R12, 0, ARM_LR, ARM_APSR
Expand Down Expand Up @@ -7344,3 +7350,76 @@ DecodeStatus ARM_LLVM_getInstruction(csh handle, const uint8_t *code,
return getInstruction(handle, code, code_len, instr, size, address,
info);
}

#else

DecodeStatus ARM_LLVM_getInstruction(csh handle, const uint8_t *code,
size_t code_len, MCInst *instr,
uint16_t *size, uint64_t address,
void *info)
{
cs_struct *ud = (cs_struct *)handle;
cs_insn *ci = instr->flat_insn;
cs_arm *arm = ci->detail ? &ci->detail->arm : NULL;
uint32_t insn;

*size = 0;

if (instr->csh->mode & CS_MODE_THUMB)
return MCDisassembler_Fail;

if (code_len < 4)
return MCDisassembler_Fail;

if (MODE_IS_BIG_ENDIAN(ud->mode))
insn = (code[3] << 0) | (code[2] << 8) |
(code[1] << 16) | ((uint32_t) code[0] << 24);
else
insn = ((uint32_t) code[3] << 24) | (code[2] << 16) |
(code[1] << 8) | (code[0] << 0);

MCInst_setOpcode(instr, ARM_INS_ENDING);
*size = 4;

//
// LDR (literal)
//
// E.g. e51fc01c => LDR r12, [pc, #-28]
//
// Cond P U W Rt Imm12
// 1110 010 1 0 0 0 11111 1100 000000011100
//
// => Pattern
// 0000 010 1 0 0 0 11111 0000 000000000000
//
// => Mask
// 0000 111 1 0 1 1 11111 0000 000000000000
//
if ((insn & 0xf7f0000) == 0x51f0000) {
MCInst_setOpcode(instr, ARM_INS_LDR);

if (arm) {
unsigned u, rt;
int imm12;
cs_arm_op *dst = &arm->operands[0];
cs_arm_op *src = &arm->operands[1];

u = (insn >> 23) & 1;
rt = (insn >> 12) & 0xf;
imm12 = insn & 0xfff;

arm->op_count = 2;

dst->type = ARM_OP_REG;
dst->reg = GPRDecoderTable[rt];

src->type = ARM_OP_MEM;
src->mem.base = ARM_REG_PC;
src->mem.disp = (u == 1) ? imm12 : -imm12;
}
}

return true;
}

#endif
11 changes: 11 additions & 0 deletions arch/ARM/ARMInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#include "ARMLinkage.h"
#include "ARMMapping.h"

#ifndef CAPSTONE_TINY

#define GET_BANKEDREG_IMPL
#include "ARMGenSystemRegister.inc"

Expand Down Expand Up @@ -1973,3 +1975,12 @@ void ARM_LLVM_printInstruction(MCInst *MI, SStream *O,
{
printInst(MI, O, info);
}

#else

void ARM_LLVM_printInstruction(MCInst *MI, SStream *O,
void * /* MCRegisterInfo* */ info)
{
}

#endif
30 changes: 29 additions & 1 deletion arch/ARM/ARMMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "ARMInstPrinter.h"
#include "ARMMapping.h"

#ifndef CAPSTONE_TINY

static const name_map insn_alias_mnem_map[] = {
#include "ARMGenCSAliasMnemMap.inc"
{ ARM_INS_ALIAS_ASR, "asr" },
Expand Down Expand Up @@ -89,7 +91,7 @@ const char *ARM_reg_name(csh handle, unsigned int reg)
return ARM_LLVM_getRegisterName(reg, ARM_RegNamesRaw);
}

const insn_map arm_insns[] = {
static const insn_map arm_insns[] = {
#include "ARMGenCSMappingInsn.inc"
};

Expand Down Expand Up @@ -814,6 +816,8 @@ void ARM_reg_access(const cs_insn *insn, cs_regs regs_read,
}
#endif

#endif

void ARM_setup_op(cs_arm_op *op)
{
memset(op, 0, sizeof(cs_arm_op));
Expand All @@ -837,6 +841,8 @@ void ARM_init_cs_detail(MCInst *MI)
}
}

#ifndef CAPSTONE_TINY

static uint64_t t_add_pc(MCInst *MI, uint64_t v)
{
int32_t imm = (int32_t)v;
Expand Down Expand Up @@ -2126,4 +2132,26 @@ void ARM_set_detail_op_float(MCInst *MI, unsigned OpNum, uint64_t Imm)
ARM_inc_op_count(MI);
}

#else

void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
{
}

void ARM_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
{
}

bool ARM_getInstruction(csh handle, const uint8_t *code, size_t code_len,
MCInst *instr, uint16_t *size, uint64_t address,
void *info)
{
ARM_init_cs_detail(instr);
return ARM_LLVM_getInstruction(handle, code, code_len, instr,
size, address,
info) != MCDisassembler_Fail;
}

#endif

#endif
6 changes: 4 additions & 2 deletions arch/ARM/ARMModule.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@

cs_err ARM_global_init(cs_struct *ud)
{
#ifndef CAPSTONE_TINY
MCRegisterInfo *mri;
mri = cs_mem_malloc(sizeof(*mri));

ARM_init_mri(mri);

ud->printer = ARM_printer;
ud->printer_info = mri;
ud->reg_name = ARM_reg_name;
ud->insn_id = ARM_get_insn_id;
ud->insn_name = ARM_insn_name;
ud->group_name = ARM_group_name;
ud->post_printer = NULL;
#endif
ud->printer = ARM_printer;
ud->insn_id = ARM_get_insn_id;
#ifndef CAPSTONE_DIET
ud->reg_access = ARM_reg_access;
#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/PowerPC/PPCMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,10 @@ void PPC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
MI->fillDetailOps = detail_is_set(MI);
MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
PPC_LLVM_printInst(MI, MI->address, "", O);
#ifndef CAPSTONE_DIET
map_set_alias_id(MI, O, insn_alias_mnem_map,
ARR_SIZE(insn_alias_mnem_map));
#endif
}

bool PPC_getInstruction(csh handle, const uint8_t *bytes, size_t bytes_len,
Expand Down
Loading

0 comments on commit cc7d686

Please sign in to comment.