Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterFunction: true
BreakBeforeBraces: Custom
UseTab: Always
BasedOnStyle: LLVM
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ cstool/cstool

# android
android-ndk-*

# cmake
cmake-build-debug
19 changes: 7 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ option(CAPSTONE_BUILD_CSTOOL "Build cstool" ON)
option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON)
option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by default" ON)
option(CAPSTONE_DEBUG "Whether to enable extra debug assertions" OFF)
option(CAPSTONE_INSTALL "Generate install target" OFF)
Copy link
Copy Markdown
Contributor

@mrexodia mrexodia Dec 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was done like this on purpose to support FetchContent workflows without doing custom hackery on the cache. Likely a good solution is to set it to CAPSTONE_ROOT_PROJECT (and also set the other sensible defaults):

if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
	set(CAPSTONE_ROOT_PROJECT ON)
endif()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless, the change seems unrelated to the goal of this pr, so it should not be part of it.

option(CAPSTONE_INSTALL "Generate install target" ON)

set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV)
Expand Down Expand Up @@ -89,6 +89,7 @@ set(SOURCES_ENGINE
MCInst.c
MCInstrDesc.c
MCRegisterInfo.c
MCInstPrinter.c
SStream.c
utils.c
)
Expand All @@ -101,6 +102,7 @@ set(HEADERS_ENGINE
MCInst.h
MCInstrDesc.h
MCRegisterInfo.h
MCInstPrinter.h
SStream.h
utils.h
)
Expand Down Expand Up @@ -201,21 +203,14 @@ if (CAPSTONE_MIPS_SUPPORT)
arch/Mips/MipsDisassembler.h
arch/Mips/MipsGenAsmWriter.inc
arch/Mips/MipsGenDisassemblerTables.inc
arch/Mips/MipsGenInstrInfo.inc
arch/Mips/MipsGenRegisterInfo.inc
arch/Mips/MipsGenSubtargetInfo.inc
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsMapping.h
arch/Mips/MipsMappingInsn.inc
)
)
set(HEADERS_MIPS
arch/Mips/MipsDisassembler.h
arch/Mips/MipsGenAsmWriter.inc
arch/Mips/MipsGenDisassemblerTables.inc
arch/Mips/MipsGenInstrInfo.inc
arch/Mips/MipsGenRegisterInfo.inc
arch/Mips/MipsGenSubtargetInfo.inc
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsMapping.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_mips.c)
Expand Down Expand Up @@ -606,7 +601,7 @@ if (CAPSTONE_BUILD_TESTS)
if (CAPSTONE_ARM_SUPPORT)
set(ARM_REGRESS_TEST test_arm_regression.c)
STRING(REGEX REPLACE ".c$" "" ARM_REGRESS_BIN ${ARM_REGRESS_TEST})
add_executable(${ARM_REGRESS_BIN} "suite/arm/${ARM_REGRESS_TEST}")
add_executable(${ARM_REGRESS_BIN} "suite/arm/${ARM_REGRESS_TEST}" sync/logger.h)
target_link_libraries(${ARM_REGRESS_BIN} ${default-target})
add_test(NAME "capstone_${ARM_REGRESS_BIN}" COMMAND ${ARM_REGRESS_BIN})
endif()
Expand Down
115 changes: 115 additions & 0 deletions MCInstPrinter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// Created by Phosphorus15 on 2021/5/14.
//
#include "MCInstPrinter.h"
#include "MCInst.h"
#include "sync/logger.h"

static bool MCInstPrinter_matchAliasCondition(
const MCInst *MI, unsigned *OpIdx, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const AliasPatternCond *Cond, bool *OrPredicateResult) {
// FIXME so here's on problem we ought to detect feature bits here
if (Cond->Kind == AliasPatternCond_K_Feature ||
Cond->Kind == AliasPatternCond_K_NegFeature)
return true; // STI->getFeatureBits().test(C.Value);
// For feature tests where just one feature is required in a list, set the
// predicate result bit to whether the expression will return true, and only
// return the real result at the end of list marker.
if (Cond->Kind == AliasPatternCond_K_OrFeature) {
// *OrPredicateResult |= STI->getFeatureBits().test(C.Value);
return true;
}
if (Cond->Kind == AliasPatternCond_K_OrNegFeature) {
// *OrPredicateResult |= !(STI->getFeatureBits().test(C.Value));
return true;
}
if (Cond->Kind == AliasPatternCond_K_EndOrFeatures) {
bool Res = *OrPredicateResult;
*OrPredicateResult = false;
return Res;
}

const MCOperand *Opnd = MCInst_getOperand(MI, *OpIdx);
*OpIdx = *OpIdx + 1;
switch (Cond->Kind) {
case AliasPatternCond_K_Imm:
// Operand must be a specific immediate.
return MCOperand_isImm(Opnd) && MCOperand_getImm(Opnd) == Cond->Value;
case AliasPatternCond_K_Reg:
// Operand must be a specific register.
return MCOperand_isReg(Opnd) && MCOperand_getReg(Opnd) == Cond->Value;
case AliasPatternCond_K_TiedReg:
// Operand must match the register of another operand.
return MCOperand_isReg(Opnd) &&
MCOperand_getReg(Opnd) ==
MCOperand_getReg(MCInst_getOperand(MI, Cond->Value));
case AliasPatternCond_K_RegClass:
// Operand must be a register in this class. Value is a register class id.
return MCOperand_isReg(Opnd) &&
MCRegisterClass_contains(
MCRegisterInfo_getRegClass(MRI, Cond->Value),
MCOperand_getReg(Opnd));
case AliasPatternCond_K_Custom:
// Operand must match some custom criteria.
// TODO might affect something return M.ValidateMCOperand(Opnd,
// *STI, C.Value);
return false;
case AliasPatternCond_K_Ignore:
// Operand can be anything.
return true;
case AliasPatternCond_K_Feature:
case AliasPatternCond_K_NegFeature:
case AliasPatternCond_K_OrFeature:
case AliasPatternCond_K_OrNegFeature:
case AliasPatternCond_K_EndOrFeatures:
0x0;
// llvm_unreachable("handled earlier");
}
}

const char *MCInstPrinter_matchAliasPatterns(
const MCInst *MI, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const char *AsmStrings[], unsigned len) {
// Binary search by opcode. Return false if there are no aliases for this
// opcode.
PatternsForOpcode *It =
Binary_Search(OpToPatterns, MCInst_getOpcode(MI), len);
debugln("binary search result %p, with opcode %d", It, MCInst_getOpcode(MI));
if (It == NULL || It->Opcode != MCInst_getOpcode(MI))
return NULL;

// Try all patterns for this opcode.
uint32_t AsmStrOffset = ~0U;

for (unsigned i = It->PatternStart; i < It->PatternStart + It->NumPatterns;
i++) {
const AliasPattern Pattern = Patterns[i];
if (MCInst_getNumOperands(MI) != Pattern.NumOperands)
return NULL;
unsigned OpIdx = 0;
bool OrPredicateResult = false;
bool fallThrough = true;
for (unsigned j = Pattern.AliasCondStart;
j < Pattern.AliasCondStart + Pattern.NumConds; j++) {
fallThrough &= MCInstPrinter_matchAliasCondition(
MI, &OpIdx, OpToPatterns, Patterns, Conds, &Conds[j],
&OrPredicateResult);
if (!fallThrough)
break;
}
if (fallThrough) {
AsmStrOffset = Pattern.AsmStrOffset;
break;
}
}

debugln("end matching with offset %d", AsmStrOffset);
// If no alias matched, don't print an alias.
if (AsmStrOffset == ~0U)
return NULL;
debugln("string with final offset %s",
(const char *)((*AsmStrings) + AsmStrOffset));
return (const char *)((*AsmStrings) + AsmStrOffset);
}
73 changes: 73 additions & 0 deletions MCInstPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// Created by Phosphorus15 on 2021/5/14.
//

#ifndef CAPSTONE_MCINSTPRINTER_H
#define CAPSTONE_MCINSTPRINTER_H

#include "MCInst.h"
#include "capstone/platform.h"
#include "stdlib.h"

// TODO we'll need this later
const MCRegisterInfo *MRI;

typedef enum CondKind {
AliasPatternCond_K_Feature, // Match only if a feature is enabled.
AliasPatternCond_K_NegFeature, // Match only if a feature is disabled.
AliasPatternCond_K_OrFeature, // Match only if one of a set of features is
// enabled.
AliasPatternCond_K_OrNegFeature, // Match only if one of a set of features is
// disabled.
AliasPatternCond_K_EndOrFeatures, // Note end of list of K_Or(Neg)?Features.
AliasPatternCond_K_Ignore, // Match any operand.
AliasPatternCond_K_Reg, // Match a specific register.
AliasPatternCond_K_TiedReg, // Match another already matched register.
AliasPatternCond_K_Imm, // Match a specific immediate.
AliasPatternCond_K_RegClass, // Match registers in a class.
AliasPatternCond_K_Custom, // Call custom matcher by index.
} CondKind;

typedef struct PatternsForOpcode {
uint32_t Opcode;
uint16_t PatternStart;
uint16_t NumPatterns;
} PatternsForOpcode;

typedef struct AliasPattern {
uint32_t AsmStrOffset;
uint32_t AliasCondStart;
uint8_t NumOperands;
uint8_t NumConds;
} AliasPattern;

typedef struct AliasPatternCond {
CondKind Kind;
uint32_t Value;
} AliasPatternCond;

static int cmp_less(const void *l, const void *r) {
return ((signed)((const PatternsForOpcode *)l)->Opcode) -
((signed)((const PatternsForOpcode *)r)->Opcode);
}

// Binary Search Implementation - let's use bsearch for now
static PatternsForOpcode *Binary_Search(const PatternsForOpcode *OpToPatterns,
const unsigned opcode, unsigned len) {
return bsearch((void *)&opcode, (void *)OpToPatterns, len,
sizeof(PatternsForOpcode), cmp_less);
}

// TODO I'm not sure if this is complete, refer to lib/MC/MCInstPrinter.cpp in
// llvm-project
static bool MCInstPrinter_matchAliasCondition(
const MCInst *MI, unsigned *OpIdx, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const AliasPatternCond *Cond, bool *OrPredicateResult);

const char *MCInstPrinter_matchAliasPatterns(
const MCInst *MI, const PatternsForOpcode *OpToPatterns,
const AliasPattern *Patterns, const AliasPatternCond *Conds,
const char *AsmStrings[], unsigned len);

#endif // CAPSTONE_MCINSTPRINTER_H
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ endif


LIBOBJ =
LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o
LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o $(OBJDIR)/MCInstPrinter.o
LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_RISCV) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ)
LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX) $(LIBOBJ_WASM) $(LIBOBJ_BPF)
LIBOBJ += $(OBJDIR)/MCInst.o
Expand Down
Loading