diff --git a/CMakeLists.txt b/CMakeLists.txt index 94b28d9b..85ab9e95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ add_definitions(-DSHARED_OBJECT_EXT="${CMAKE_SHARED_LIBRARY_SUFFIX}" -DMINIZ_NO_ # set(CPM_USE_LOCAL_PACKAGES ON) include(cmake/CPM.cmake) # https://github.com/TheLartians/CPM.cmake CPMAddPackage("gh:gabime/spdlog@1.9.2") +CPMAddPackage("gh:nlohmann/json@3.10.5") if(ENABLE_TESTS) add_subdirectory(tests) @@ -66,8 +67,7 @@ set(SOURCES ${LIBS_SOURCES} ${RDCORE_SOURCES} ${RDAPI_SOURCES}) add_subdirectory(rdcore/libs/taojson EXCLUDE_FROM_ALL) add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) -target_link_libraries(${PROJECT_NAME} PRIVATE taocpp::json spdlog) -target_include_directories(${PROJECT_NAME} PRIVATE spdlog) +target_link_libraries(${PROJECT_NAME} PRIVATE taocpp::json spdlog nlohmann_json::nlohmann_json) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/rdapi/rdil.cpp b/rdapi/rdil.cpp index 90b3df26..497ef73e 100644 --- a/rdapi/rdil.cpp +++ b/rdapi/rdil.cpp @@ -12,15 +12,19 @@ RDGraph* RDILGraph_Create(RDContext* ctx, rd_address address) RDILExpression* RDILExpression_Create(RDContext* ctx, rd_address address) { return CPTR(RDILExpression, ILFunction::generateOne(CPTR(Context, ctx), address)); } rd_type RDILExpression_Type(const RDILExpression* e) { return e ? CPTR(const ILExpression, e)->type : RDIL_Unknown; } -bool RDILExpression_Match(const RDILExpression* e, const char* m) { return e ? RDIL::match(CPTR(const ILExpression, e), m) : false; } -const RDILExpression* RDILExpression_Extract(const RDILExpression* e, const char* q) { return (e && q) ? CPTR(const RDILExpression, RDIL::extract(CPTR(const ILExpression, e), q)) : nullptr; } +bool RDILExpression_Match(const RDILExpression* e, const char* m) { return e && m ? RDIL::match(CPTR(const ILExpression, e), m) : false; } +size_t RDILExpression_ExtractNew(const RDILExpression* e, const RDILValue** values) { return e && values ? RDIL::extract(CPTR(const ILExpression, e), values) : 0; } bool RDILExpression_GetValue(const RDILExpression* e, RDILValue* value) { const ILExpression* expr = CPTR(const ILExpression, e); if(!expr || !RDIL::hasValue(expr)) return false; - if(value) value->value = expr->value; + if(value) + { + value->type = expr->type; + value->value = expr->value; + } return true; } @@ -49,6 +53,9 @@ const RDILExpression* RDILFunction_GetExpression(const RDILFunction* rdilfunctio const RDILExpression* RDILFunction_GetFirstExpression(const RDILFunction* rdilfunction) { return CPTR(const RDILExpression, CPTR(const ILFunction, rdilfunction)->first()); } const RDILExpression* RDILFunction_GetLastExpression(const RDILFunction* rdilfunction) { return CPTR(const RDILExpression, CPTR(const ILFunction, rdilfunction)->last()); } size_t RDILFunction_Size(const RDILFunction* rdilfunction) { return CPTR(const ILFunction, rdilfunction)->size(); } +size_t RDILFunction_Extract(const RDILFunction* rdilfunction, const RDILValue** values) { return rdilfunction ? RDIL::extract(CPTR(const ILFunction, rdilfunction), values) : 0; } +bool RDILFunction_Match(const RDILFunction* rdilfunction, const char* m) { return rdilfunction && m ? RDIL::match(CPTR(const ILFunction, rdilfunction), m) : false; } +bool RDILFunction_Extract(const RDILFunction* rdilfunction, const char* m) { (void)rdilfunction; (void)m; return false; } //return rdilfunction && m ? RDIL::match(CPTR(const ILFunction, rdilfunction), m) : false; } bool RDILFunction_GetAddress(const RDILFunction* rdilfunction, const RDILExpression* e, rd_address* address) { return CPTR(const ILFunction, rdilfunction)->getAddress(CPTR(const ILExpression, e), address); } void RDILFunction_Insert(RDILFunction* rdilfunction, size_t idx, RDILExpression* expression) { CPTR(ILFunction, rdilfunction)->insert(idx, CPTR(ILExpression, expression)); } void RDILFunction_Append(RDILFunction* rdilfunction, RDILExpression* expression) { CPTR(ILFunction, rdilfunction)->append(CPTR(ILExpression, expression)); } diff --git a/rdapi/rdil.h b/rdapi/rdil.h index 145fbd46..cf2d3fc5 100644 --- a/rdapi/rdil.h +++ b/rdapi/rdil.h @@ -93,9 +93,13 @@ enum RDILTypes u64 u_value; \ s64 s_value; \ const char* reg; \ - const char* var; \ + const char* var; -typedef union RDILValue { PRIVATE_RDIL_VALUE_FIELDS } RDILValue; +typedef struct RDILValue +{ + rd_type type; + union { PRIVATE_RDIL_VALUE_FIELDS }; +} RDILValue; RD_HANDLE(RDILFunction); RD_HANDLE(RDILExpression); @@ -108,12 +112,14 @@ RD_API_EXPORT bool RDILExpression_Match(const RDILExpression* e, const char* m); RD_API_EXPORT bool RDILExpression_GetValue(const RDILExpression* e, RDILValue* value); RD_API_EXPORT const char* RDILExpression_GetText(const RDILExpression* e); RD_API_EXPORT const char* RDILExpression_GetFormat(const RDILExpression* e); -RD_API_EXPORT const RDILExpression* RDILExpression_Extract(const RDILExpression* e, const char* q); +RD_API_EXPORT size_t RDILExpression_ExtractNew(const RDILExpression* e, const RDILValue** values); RD_API_EXPORT RDILFunction* RDILFunction_Create(RDContext* context, rd_address address); RD_API_EXPORT const RDILExpression* RDILFunction_GetExpression(const RDILFunction* rdilfunction, size_t idx); RD_API_EXPORT const RDILExpression* RDILFunction_GetFirstExpression(const RDILFunction* rdilfunction); RD_API_EXPORT const RDILExpression* RDILFunction_GetLastExpression(const RDILFunction* rdilfunction); +RD_API_EXPORT size_t RDILFunction_Extract(const RDILFunction* rdilfunction, const RDILValue** values); +RD_API_EXPORT bool RDILFunction_Match(const RDILFunction* rdilfunction, const char* m); RD_API_EXPORT bool RDILFunction_GetAddress(const RDILFunction* rdilfunction, const RDILExpression* e, rd_address* address); RD_API_EXPORT void RDILFunction_Insert(RDILFunction* rdilfunction, size_t idx, RDILExpression* expression); RD_API_EXPORT void RDILFunction_Append(RDILFunction* rdilfunction, RDILExpression* expression); diff --git a/rdcore/builtin/analyzer/functionanalyzer.cpp b/rdcore/builtin/analyzer/functionanalyzer.cpp index 18472ac6..faad78ee 100644 --- a/rdcore/builtin/analyzer/functionanalyzer.cpp +++ b/rdcore/builtin/analyzer/functionanalyzer.cpp @@ -40,7 +40,7 @@ bool FunctionAnalyzer::findNullSubs(Context* ctx, const ILExpression* expr, rd_a { if((expr->type == RDIL_Ret) || ((expr->type == RDIL_Nop) && (ctx->document()->getFunctionInstrCount(address)) == 1)) { - ctx->document()->setLabel(address, AddressFlags_None, "nullsub_" + Utils::hex(address)); + ctx->document()->updateLabel(address, "nullsub_" + Utils::hex(address)); return true; } @@ -49,18 +49,15 @@ bool FunctionAnalyzer::findNullSubs(Context* ctx, const ILExpression* expr, rd_a std::string FunctionAnalyzer::findThunk(Context* ctx, const ILExpression* expr, rd_address address, int level) { - std::string label; + const RDILValue* values = nullptr; + if(!RDIL::match(expr, "goto [cnst]") && RDIL::match(expr, "goto cnst")) return std::string(); + rd_address raddress = 0; + std::string label; - if(RDIL::match(expr, "goto [cnst]")) - { - raddress = RDIL::extract(expr, "u:mem/u:cnst")->address; - auto dlabel = ctx->document()->getLabel(raddress); - if(dlabel) label = *dlabel; - } - else if(RDIL::match(expr, "goto cnst")) + if(size_t n = RDIL::extract(expr, &values); n == 1) { - raddress = RDIL::extract(expr, "u:cnst")->address; + raddress = values->address; auto dlabel = ctx->document()->getLabel(raddress); if(dlabel) label = *dlabel; } diff --git a/rdcore/rdil/expression.cpp b/rdcore/rdil/expression.cpp index 3438eba7..c23fc23c 100644 --- a/rdcore/rdil/expression.cpp +++ b/rdcore/rdil/expression.cpp @@ -28,3 +28,97 @@ ILExpression* ILExpression::clone(const ILExpression* e) return ne; } + +ILExpressionTree::ILExpressionTree(): Object() { } +ILExpressionTree::ILExpressionTree(Context* ctx): Object(ctx) { } +ILExpression* ILExpressionTree::exprUNKNOWN() const { return this->expr(RDIL_Unknown); } +ILExpression* ILExpressionTree::exprNOP() const { return this->expr(RDIL_Nop); } +ILExpression* ILExpressionTree::exprPOP(ILExpression* e) const { return this->exprU(RDIL_Pop, 0, e); } +ILExpression* ILExpressionTree::exprPUSH(ILExpression* e) const { return this->exprU(RDIL_Push, 0, e); } +ILExpression* ILExpressionTree::exprVAR(size_t size, const char* name) const { return this->exprVALUE_P(RDIL_Var, size, reinterpret_cast(name)); } +ILExpression* ILExpressionTree::exprREG(size_t size, const char* reg) const { return this->exprVALUE_P(RDIL_Reg, size, reinterpret_cast(reg)); } +ILExpression* ILExpressionTree::exprCNST(size_t size, u64 value) const { return this->exprVALUE(RDIL_Cnst, size, value); } +ILExpression* ILExpressionTree::exprJUMP(ILExpression* e) const { return this->exprU(RDIL_Goto, 0, e); } +ILExpression* ILExpressionTree::exprCALL(ILExpression* e) const { return this->exprU(RDIL_Call, 0, e); } +ILExpression* ILExpressionTree::exprRET(ILExpression* e) const { return this->exprU(RDIL_Ret, 0, e); } +ILExpression* ILExpressionTree::exprMEM(ILExpression* e) const { return this->exprU(RDIL_Mem, 0, e); } +ILExpression* ILExpressionTree::exprNOT(ILExpression* e) const { return this->exprU(RDIL_Not, 0, e); } +ILExpression* ILExpressionTree::exprADD(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Add, 0, l, r); } +ILExpression* ILExpressionTree::exprSUB(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Sub, 0, l, r); } +ILExpression* ILExpressionTree::exprMUL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Mul, 0, l, r); } +ILExpression* ILExpressionTree::exprDIV(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Div, 0, l, r); } +ILExpression* ILExpressionTree::exprMOD(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Mod, 0, l, r); } +ILExpression* ILExpressionTree::exprAND(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Div, 0, l, r); } +ILExpression* ILExpressionTree::exprOR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Or, 0, l, r); } +ILExpression* ILExpressionTree::exprXOR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Xor, 0, l, r); } +ILExpression* ILExpressionTree::exprLSL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lsl, 0, l, r); } +ILExpression* ILExpressionTree::exprLSR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lsr, 0, l, r); } +ILExpression* ILExpressionTree::exprASL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Asl, 0, l, r); } +ILExpression* ILExpressionTree::exprASR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Asr, 0, l, r); } +ILExpression* ILExpressionTree::exprROL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Rol, 0, l, r); } +ILExpression* ILExpressionTree::exprROR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ror, 0, l, r); } +ILExpression* ILExpressionTree::exprCOPY(ILExpression* dst, ILExpression* src) const { return this->exprDS(RDIL_Copy, 0, dst, src); } +ILExpression* ILExpressionTree::exprEQ(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Eq, 0, l, r); } +ILExpression* ILExpressionTree::exprNE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ne, 0, l, r); } +ILExpression* ILExpressionTree::exprLT(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lt, 0, l, r); } +ILExpression* ILExpressionTree::exprLE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Le, 0, l, r); } +ILExpression* ILExpressionTree::exprGT(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Gt, 0, l, r); } +ILExpression* ILExpressionTree::exprGE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ge, 0, l, r); } +ILExpression* ILExpressionTree::check(ILExpression* e) const { return e ? e : this->exprUNKNOWN(); } + +ILExpression* ILExpressionTree::exprIF(ILExpression* cond, ILExpression* t, ILExpression* f) const +{ + auto* expr = this->expr(RDIL_If, 0); + expr->cond = cond; + expr->t = this->check(t); + expr->f = this->check(f); + return expr; +} + +ILExpression* ILExpressionTree::exprVALUE_P(rd_type rdil, size_t size, uintptr_t value) const +{ + auto* expr = this->expr(rdil, size); + expr->value = value; + return expr; +} + +ILExpression* ILExpressionTree::exprVALUE(rd_type rdil, size_t size, u64 value) const +{ + auto* expr = this->expr(rdil, size); + expr->u_value = value; + return expr; +} + +ILExpression* ILExpressionTree::exprLR(rd_type rdil, size_t size, ILExpression* l, ILExpression* r) const +{ + auto* expr = this->expr(rdil, size); + expr->left = this->check(l); + expr->right = this->check(r); + return expr; +} + +ILExpression* ILExpressionTree::exprDS(rd_type rdil, size_t size, ILExpression* dst, ILExpression* src) const +{ + auto* expr = this->expr(rdil, size); + expr->dst = this->check(dst); + expr->src = this->check(src); + return expr; +} + +ILExpression* ILExpressionTree::exprU(rd_type rdil, size_t size, ILExpression* e) const +{ + auto* expr = this->expr(rdil, size); + expr->u = this->check(e); + return expr; +} + +ILExpression* ILExpressionTree::expr(rd_type rdil, size_t size) const +{ + auto& expr = m_pool.emplace_front(new ILExpression()); + expr->type = rdil; + expr->size = size; + expr->value = 0; + return expr.get(); +} + +ILExpression* ILExpressionTree::expr(rd_type rdil) const { return this->expr(rdil, 0); } diff --git a/rdcore/rdil/expression.h b/rdcore/rdil/expression.h index 36930f64..28e09de7 100644 --- a/rdcore/rdil/expression.h +++ b/rdcore/rdil/expression.h @@ -1,8 +1,9 @@ #pragma once #include -#include #include +#include +#include #include "../object.h" class ILExpression; @@ -27,3 +28,59 @@ class ILExpression : public Object friend class ILFunction; }; + +class ILExpressionTree: public Object +{ + public: + ILExpressionTree(); + ILExpressionTree(Context* ctx); + ILExpression* exprUNKNOWN() const; + ILExpression* exprNOP() const; + ILExpression* exprPOP(ILExpression* e) const; + ILExpression* exprPUSH(ILExpression* e) const; + ILExpression* exprREG(size_t size, const char* reg) const; + ILExpression* exprCNST(size_t size, u64 value) const; + ILExpression* exprVAR(size_t size, const char* name) const; + ILExpression* exprJUMP(ILExpression* e) const; + ILExpression* exprCALL(ILExpression* e) const; + ILExpression* exprRET(ILExpression* e) const; + ILExpression* exprMEM(ILExpression* e) const; + ILExpression* exprNOT(ILExpression* e) const; + ILExpression* exprADD(ILExpression* l, ILExpression* r) const; + ILExpression* exprSUB(ILExpression* l, ILExpression* r) const; + ILExpression* exprMUL(ILExpression* l, ILExpression* r) const; + ILExpression* exprDIV(ILExpression* l, ILExpression* r) const; + ILExpression* exprMOD(ILExpression* l, ILExpression* r) const; + ILExpression* exprAND(ILExpression* l, ILExpression* r) const; + ILExpression* exprOR(ILExpression* l, ILExpression* r) const; + ILExpression* exprXOR(ILExpression* l, ILExpression* r) const; + ILExpression* exprLSL(ILExpression* l, ILExpression* r) const; + ILExpression* exprLSR(ILExpression* l, ILExpression* r) const; + ILExpression* exprASL(ILExpression* l, ILExpression* r) const; + ILExpression* exprASR(ILExpression* l, ILExpression* r) const; + ILExpression* exprROL(ILExpression* l, ILExpression* r) const; + ILExpression* exprROR(ILExpression* l, ILExpression* r) const; + ILExpression* exprCOPY(ILExpression* dst, ILExpression* src) const; + ILExpression* exprIF(ILExpression* cond, ILExpression* t, ILExpression* f) const; + ILExpression* exprEQ(ILExpression* l, ILExpression* r) const; + ILExpression* exprNE(ILExpression* l, ILExpression* r) const; + ILExpression* exprLT(ILExpression* l, ILExpression* r) const; + ILExpression* exprLE(ILExpression* l, ILExpression* r) const; + ILExpression* exprGT(ILExpression* l, ILExpression* r) const; + ILExpression* exprGE(ILExpression* l, ILExpression* r) const; + + protected: + ILExpression* check(ILExpression* e) const; + + private: + ILExpression* exprVALUE_P(rd_type rdil, size_t size, uintptr_t value) const; + ILExpression* exprVALUE(rd_type rdil, size_t size, u64 value) const; + ILExpression* exprLR(rd_type rdil, size_t size, ILExpression* l, ILExpression* r) const; + ILExpression* exprDS(rd_type rdil, size_t size, ILExpression* dst, ILExpression* src) const; + ILExpression* exprU(rd_type rdil, size_t size, ILExpression* e) const; + ILExpression* expr(rd_type rdil, size_t size) const; + ILExpression* expr(rd_type rdil) const; + + private: + mutable std::list m_pool; +}; diff --git a/rdcore/rdil/ilfunction.cpp b/rdcore/rdil/ilfunction.cpp index be84d708..9c838fea 100644 --- a/rdcore/rdil/ilfunction.cpp +++ b/rdcore/rdil/ilfunction.cpp @@ -7,7 +7,7 @@ #define IL_EXPR_SIZE(size) (size ? size : (this->context()->bits() / CHAR_BIT)) -ILFunction::ILFunction(Context* ctx): Object(ctx) { } +ILFunction::ILFunction(Context* ctx): ILExpressionTree(ctx) { } void ILFunction::insert(size_t idx, ILExpression* e) { @@ -83,97 +83,6 @@ bool ILFunction::getAddress(const ILExpression* e, rd_address* address) const const ILExpression* ILFunction::first() const { return !m_expressions.empty() ? m_expressions.front() : nullptr; } const ILExpression* ILFunction::last() const { return !m_expressions.empty() ? m_expressions.back() : nullptr; } -ILExpression* ILFunction::exprUNKNOWN() const { return this->expr(RDIL_Unknown); } -ILExpression* ILFunction::exprNOP() const { return this->expr(RDIL_Nop); } -ILExpression* ILFunction::exprPOP(ILExpression* e) const { return this->exprU(RDIL_Pop, 0, e); } -ILExpression* ILFunction::exprPUSH(ILExpression* e) const { return this->exprU(RDIL_Push, 0, e); } -ILExpression* ILFunction::exprVAR(size_t size, const char* name) const { return this->exprVALUE_P(RDIL_Var, IL_EXPR_SIZE(size), reinterpret_cast(name)); } -ILExpression* ILFunction::exprREG(size_t size, const char* reg) const { return this->exprVALUE_P(RDIL_Reg, IL_EXPR_SIZE(size), reinterpret_cast(reg)); } -ILExpression* ILFunction::exprCNST(size_t size, u64 value) const { return this->exprVALUE(RDIL_Cnst, size, value); } -ILExpression* ILFunction::exprJUMP(ILExpression* e) const { return this->exprU(RDIL_Goto, 0, e); } -ILExpression* ILFunction::exprCALL(ILExpression* e) const { return this->exprU(RDIL_Call, 0, e); } -ILExpression* ILFunction::exprRET(ILExpression* e) const { return this->exprU(RDIL_Ret, 0, e); } -ILExpression* ILFunction::exprMEM(ILExpression* e) const { return this->exprU(RDIL_Mem, 0, e); } -ILExpression* ILFunction::exprNOT(ILExpression* e) const { return this->exprU(RDIL_Not, 0, e); } -ILExpression* ILFunction::exprADD(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Add, 0, l, r); } -ILExpression* ILFunction::exprSUB(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Sub, 0, l, r); } -ILExpression* ILFunction::exprMUL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Mul, 0, l, r); } -ILExpression* ILFunction::exprDIV(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Div, 0, l, r); } -ILExpression* ILFunction::exprMOD(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Mod, 0, l, r); } -ILExpression* ILFunction::exprAND(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Div, 0, l, r); } -ILExpression* ILFunction::exprOR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Or, 0, l, r); } -ILExpression* ILFunction::exprXOR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Xor, 0, l, r); } -ILExpression* ILFunction::exprLSL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lsl, 0, l, r); } -ILExpression* ILFunction::exprLSR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lsr, 0, l, r); } -ILExpression* ILFunction::exprASL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Asl, 0, l, r); } -ILExpression* ILFunction::exprASR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Asr, 0, l, r); } -ILExpression* ILFunction::exprROL(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Rol, 0, l, r); } -ILExpression* ILFunction::exprROR(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ror, 0, l, r); } -ILExpression* ILFunction::exprCOPY(ILExpression* dst, ILExpression* src) const { return this->exprDS(RDIL_Copy, 0, dst, src); } -ILExpression* ILFunction::exprEQ(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Eq, 0, l, r); } -ILExpression* ILFunction::exprNE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ne, 0, l, r); } -ILExpression* ILFunction::exprLT(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Lt, 0, l, r); } -ILExpression* ILFunction::exprLE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Le, 0, l, r); } -ILExpression* ILFunction::exprGT(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Gt, 0, l, r); } -ILExpression* ILFunction::exprGE(ILExpression* l, ILExpression* r) const { return this->exprLR(RDIL_Ge, 0, l, r); } -ILExpression* ILFunction::check(ILExpression* e) const { return e ? e : this->exprUNKNOWN(); } - -ILExpression* ILFunction::exprIF(ILExpression* cond, ILExpression* t, ILExpression* f) const -{ - auto* expr = this->expr(RDIL_If, 0); - expr->cond = cond; - expr->t = this->check(t); - expr->f = this->check(f); - return expr; -} - -ILExpression* ILFunction::exprVALUE_P(rd_type rdil, size_t size, uintptr_t value) const -{ - auto* expr = this->expr(rdil, size); - expr->value = value; - return expr; -} - -ILExpression* ILFunction::exprVALUE(rd_type rdil, size_t size, u64 value) const -{ - auto* expr = this->expr(rdil, size); - expr->u_value = value; - return expr; -} - -ILExpression* ILFunction::exprLR(rd_type rdil, size_t size, ILExpression* l, ILExpression* r) const -{ - auto* expr = this->expr(rdil, size); - expr->left = this->check(l); - expr->right = this->check(r); - return expr; -} - -ILExpression* ILFunction::exprDS(rd_type rdil, size_t size, ILExpression* dst, ILExpression* src) const -{ - auto* expr = this->expr(rdil, size); - expr->dst = this->check(dst); - expr->src = this->check(src); - return expr; -} - -ILExpression* ILFunction::exprU(rd_type rdil, size_t size, ILExpression* e) const -{ - auto* expr = this->expr(rdil, size); - expr->u = this->check(e); - return expr; -} - -ILExpression* ILFunction::expr(rd_type rdil, size_t size) const -{ - auto& expr = m_pool.emplace_front(new ILExpression()); - expr->type = rdil; - expr->size = size; - expr->value = 0; - return expr.get(); -} - -ILExpression* ILFunction::expr(rd_type rdil) const { return this->expr(rdil, 0); } void ILFunction::generateBasicBlock(rd_address address, ILFunction* il, std::set& path) { diff --git a/rdcore/rdil/ilfunction.h b/rdcore/rdil/ilfunction.h index 24132425..69228b14 100644 --- a/rdcore/rdil/ilfunction.h +++ b/rdcore/rdil/ilfunction.h @@ -10,7 +10,7 @@ class Disassembler; -class ILFunction: public Object +class ILFunction: public ILExpressionTree { public: typedef std::deque ExpressionList; @@ -31,52 +31,6 @@ class ILFunction: public Object static bool generate(rd_address address, ILFunction* il); static ILExpression* generateOne(Context* ctx, rd_address address); - public: - ILExpression* exprUNKNOWN() const; - ILExpression* exprNOP() const; - ILExpression* exprPOP(ILExpression* e) const; - ILExpression* exprPUSH(ILExpression* e) const; - ILExpression* exprREG(size_t size, const char* reg) const; - ILExpression* exprCNST(size_t size, u64 value) const; - ILExpression* exprVAR(size_t size, const char* name) const; - ILExpression* exprJUMP(ILExpression* e) const; - ILExpression* exprCALL(ILExpression* e) const; - ILExpression* exprRET(ILExpression* e) const; - ILExpression* exprMEM(ILExpression* e) const; - ILExpression* exprNOT(ILExpression* e) const; - ILExpression* exprADD(ILExpression* l, ILExpression* r) const; - ILExpression* exprSUB(ILExpression* l, ILExpression* r) const; - ILExpression* exprMUL(ILExpression* l, ILExpression* r) const; - ILExpression* exprDIV(ILExpression* l, ILExpression* r) const; - ILExpression* exprMOD(ILExpression* l, ILExpression* r) const; - ILExpression* exprAND(ILExpression* l, ILExpression* r) const; - ILExpression* exprOR(ILExpression* l, ILExpression* r) const; - ILExpression* exprXOR(ILExpression* l, ILExpression* r) const; - ILExpression* exprLSL(ILExpression* l, ILExpression* r) const; - ILExpression* exprLSR(ILExpression* l, ILExpression* r) const; - ILExpression* exprASL(ILExpression* l, ILExpression* r) const; - ILExpression* exprASR(ILExpression* l, ILExpression* r) const; - ILExpression* exprROL(ILExpression* l, ILExpression* r) const; - ILExpression* exprROR(ILExpression* l, ILExpression* r) const; - ILExpression* exprCOPY(ILExpression* dst, ILExpression* src) const; - ILExpression* exprIF(ILExpression* cond, ILExpression* t, ILExpression* f) const; - ILExpression* exprEQ(ILExpression* l, ILExpression* r) const; - ILExpression* exprNE(ILExpression* l, ILExpression* r) const; - ILExpression* exprLT(ILExpression* l, ILExpression* r) const; - ILExpression* exprLE(ILExpression* l, ILExpression* r) const; - ILExpression* exprGT(ILExpression* l, ILExpression* r) const; - ILExpression* exprGE(ILExpression* l, ILExpression* r) const; - - private: - ILExpression* check(ILExpression* e) const; - ILExpression* exprVALUE_P(rd_type rdil, size_t size, uintptr_t value) const; - ILExpression* exprVALUE(rd_type rdil, size_t size, u64 value) const; - ILExpression* exprLR(rd_type rdil, size_t size, ILExpression* l, ILExpression* r) const; - ILExpression* exprDS(rd_type rdil, size_t size, ILExpression* dst, ILExpression* src) const; - ILExpression* exprU(rd_type rdil, size_t size, ILExpression* e) const; - ILExpression* expr(rd_type rdil, size_t size) const; - ILExpression* expr(rd_type rdil) const; - private: static bool generatePath(rd_address address, ILFunction* il, std::set& path); static void generateBasicBlock(rd_address address, ILFunction* il, std::set& path); @@ -88,8 +42,7 @@ class ILFunction: public Object ExpressionList::const_iterator end() const; private: + std::unordered_map m_addresses; rd_address m_currentaddress{RD_NVAL}; ExpressionList m_expressions; - std::unordered_map m_addresses; - mutable std::list m_pool; }; diff --git a/rdcore/rdil/rdil.cpp b/rdcore/rdil/rdil.cpp index 5aa37921..a6ee1c5a 100644 --- a/rdcore/rdil/rdil.cpp +++ b/rdcore/rdil/rdil.cpp @@ -5,6 +5,8 @@ #include "../support/lexer.h" #include "../config.h" #include +#include +#include #define RDIL_N(x) {x, #x} @@ -64,7 +66,7 @@ std::string RDIL::getFormat(const ILExpression* e) void RDIL::render(const ILExpression* e, Renderer* renderer, rd_address address) { - RDIL::walk(e, [renderer, address](const ILExpression* expr, const std::string& s, WalkType wt) { + RDIL::toString(e, [renderer, address](const ILExpression* expr, const std::string& s, WalkType wt) { if(wt == WalkType::Mnemonic) { switch(expr->type) { case RDIL_Goto: renderer->renderMnemonic(s, Theme_Jump); break; @@ -98,11 +100,46 @@ void RDIL::render(const ILExpression* e, Renderer* renderer, rd_address address) }); } -const ILExpression* RDIL::extract(const ILExpression* e, const char* q) +size_t RDIL::extract(const ILExpression* e, const RDILValue** values) { - RDILQuery query; - if(!RDIL::parseQuery(q, query)) return nullptr; - return RDIL::extract(e, { }, query); + if(!e) return false; + + static std::vector v; + v = { }; + + RDIL::extract(e, v); + if(values) *values = v.data(); + return v.size(); +} + +size_t RDIL::extract(const ILFunction* f, const RDILValue** values) +{ + if(!f) return false; + + static std::vector v; + v = { }; + + for(const ILExpression* e : *f) + RDIL::extract(e, v); + + if(values) *values = v.data(); + return v.size(); +} + +bool RDIL::match(const ILFunction* f, const char* m) +{ + if(!f || !m) return false; + + auto parts = Utils::split(m, ';'); + if(parts.size() != f->size()) return false; + + for(size_t i = 0; i < parts.size(); i++) + { + if(!RDIL::match(f->expression(i), parts.at(i).c_str())) + return false; + } + + return true; } std::string RDIL::textOp(const ILExpression* e) @@ -149,63 +186,14 @@ bool RDIL::hasValue(const ILExpression* e) return false; } -const ILExpression* RDIL::extract(const ILExpression* e, const RDILQueryItem& qi, RDIL::RDILQuery& query, int depth) +void RDIL::extract(const ILExpression* e, std::vector& values) { - if(!e || query.empty()) return e; - if(depth && (qi.opcode != "*") && (e->type != RDIL::getOpType(qi.opcode))) return nullptr; - - RDILQueryItem nqi = query.front(); - query.pop(); - - if(nqi.nodeid == "u") return RDIL::extract(e->u, nqi, query, ++depth); - if(nqi.nodeid == "cond") return RDIL::extract(e->cond, nqi, query, ++depth); - if(nqi.nodeid == "dst") return RDIL::extract(e->dst, nqi, query, ++depth); - if(nqi.nodeid == "left") return RDIL::extract(e->left, nqi, query, ++depth); - if(nqi.nodeid == "t") return RDIL::extract(e->t, nqi, query, ++depth); - if(nqi.nodeid == "src") return RDIL::extract(e->src, nqi, query, ++depth); - if(nqi.nodeid == "right") return RDIL::extract(e->right, nqi, query, ++depth); - if(nqi.nodeid == "f") return RDIL::extract(e->f, nqi, query, ++depth); - rd_cfg->log("Unknown node id: " + nqi.nodeid); - return nullptr; -} - -bool RDIL::parseQuery(const std::string& q, RDIL::RDILQuery& query) -{ - Lexer l(q.c_str()); - RDToken token; - RDILQueryItem item; - - while(!l.hasError() && l.lex(&token)) - { - if(IS_TYPE(&token, TokenType_Slash)) continue; - if(!l.check(&token, TokenType_Identifier)) break; - item.nodeid = Lexer::tokenValue(&token); - - if(!l.lexCheck(&token, TokenType_Colon)) break; - if(!l.lex(&token)) break; - - switch(token.type) - { - case TokenType_Asterisk: - case TokenType_Identifier: break; - - default: l.error(&token); continue; - } - - item.opcode = Lexer::tokenValue(&token); - query.push(item); - } - - if(l.hasError()) - { - rd_cfg->log(l.lastError()); - return false; - } - - return !query.empty(); + RDIL::walk(e, [&values](const ILExpression* expr) { + if(RDIL::hasValue(expr)) values.emplace_back(RDILValue{expr->type, {expr->value}}); + }); } -void RDIL::walk(const ILExpression* e, const RDIL::WalkCallback& cb) +void RDIL::toString(const ILExpression* e, const RDIL::ToStringCallback& cb) { switch(e->type) { @@ -229,16 +217,16 @@ void RDIL::walk(const ILExpression* e, const RDIL::WalkCallback& cb) case RDIL_Ge: RDIL::wrapWalk(e->left, cb); cb(e, RDIL::textOp(e), WalkType::Normal); - RDIL::walk(e->right, cb); + RDIL::toString(e->right, cb); break; case RDIL_Rol: case RDIL_Ror: cb(e, (e->type == RDIL_Rol) ? "rol" : "ror", WalkType::Mnemonic); cb(e, "(", WalkType::Normal); - RDIL::walk(e->left, cb); + RDIL::toString(e->left, cb); cb(e, ", ", WalkType::Normal); - RDIL::walk(e->right, cb); + RDIL::toString(e->right, cb); cb(e, ")", WalkType::Normal); break; @@ -251,19 +239,19 @@ void RDIL::walk(const ILExpression* e, const RDIL::WalkCallback& cb) cb(e, "if", WalkType::Mnemonic); cb(e, " ", WalkType::Normal); cb(e, "(", WalkType::Normal); - RDIL::walk(e->cond, cb); + RDIL::toString(e->cond, cb); cb(e, ") ", WalkType::Normal); - RDIL::walk(e->t, cb); + RDIL::toString(e->t, cb); cb(e, " ", WalkType::Whitespace); cb(e, "else", WalkType::Mnemonic); cb(e, " ", WalkType::Whitespace); - RDIL::walk(e->f, cb); + RDIL::toString(e->f, cb); break; case RDIL_Ret: cb(e, "ret", WalkType::Mnemonic); cb(e, "(", WalkType::Normal); - RDIL::walk(e->cond, cb); + RDIL::toString(e->cond, cb); cb(e, ")", WalkType::Normal); break; @@ -274,37 +262,37 @@ void RDIL::walk(const ILExpression* e, const RDIL::WalkCallback& cb) break; case RDIL_Copy: - RDIL::walk(e->dst, cb); + RDIL::toString(e->dst, cb); cb(e, "=", WalkType::Normal); - RDIL::walk(e->src, cb); + RDIL::toString(e->src, cb); break; case RDIL_Call: - RDIL::walk(e->u, cb); + RDIL::toString(e->u, cb); cb(e, "()", WalkType::Normal); break; case RDIL_Goto: cb(e, "goto", WalkType::Mnemonic); cb(e, " ", WalkType::Whitespace); - RDIL::walk(e->u, cb); + RDIL::toString(e->u, cb); break; case RDIL_Mem: cb(e, "[", WalkType::Normal); - RDIL::walk(e->u, cb); + RDIL::toString(e->u, cb); cb(e, "]", WalkType::Normal); break; case RDIL_Push: cb(e, "push", WalkType::Mnemonic); cb(e, "(", WalkType::Normal); - RDIL::walk(e->u, cb); + RDIL::toString(e->u, cb); cb(e, ")", WalkType::Normal); break; case RDIL_Pop: - RDIL::walk(e->u, cb); + RDIL::toString(e->u, cb); cb(e, "=", WalkType::Normal); cb(e, "pop()", WalkType::Mnemonic); break; @@ -315,6 +303,88 @@ void RDIL::walk(const ILExpression* e, const RDIL::WalkCallback& cb) } } +void RDIL::walk(const ILExpression* e, const WalkCallback& cb) +{ + if(!e) return; + + switch(e->type) + { + case RDIL_Add: + case RDIL_Sub: + case RDIL_Mul: + case RDIL_Div: + case RDIL_Mod: + case RDIL_And: + case RDIL_Or: + case RDIL_Xor: + case RDIL_Lsl: + case RDIL_Lsr: + case RDIL_Asl: + case RDIL_Asr: + case RDIL_Eq: + case RDIL_Ne: + case RDIL_Lt: + case RDIL_Le: + case RDIL_Gt: + case RDIL_Ge: + RDIL::walk(e->left, cb); + cb(e); + RDIL::walk(e->right, cb); + break; + + case RDIL_Rol: + case RDIL_Ror: + cb(e); + RDIL::walk(e->left, cb); + RDIL::walk(e->right, cb); + break; + + case RDIL_If: + cb(e); + RDIL::walk(e->cond, cb); + RDIL::walk(e->t, cb); + RDIL::walk(e->f, cb); + break; + + case RDIL_Ret: + cb(e); + RDIL::walk(e->cond, cb); + break; + + case RDIL_Cnst: + case RDIL_Var: + case RDIL_Reg: + case RDIL_Unknown: + case RDIL_Nop: + cb(e); + break; + + case RDIL_Copy: + RDIL::walk(e->dst, cb); + cb(e); + RDIL::walk(e->src, cb); + break; + + case RDIL_Call: + case RDIL_Pop: + RDIL::walk(e->u, cb); + cb(e); + break; + + case RDIL_Goto: + case RDIL_Push: + case RDIL_Mem: + case RDIL_Not: + cb(e); + RDIL::walk(e->u, cb); + break; + + default: + REDasmError("Unknown RDIL Type: #" + std::to_string(e->type)); + break; + } +} + bool RDIL::match(const ILExpression* e, const char* m) { if(!e || !m) return false; @@ -400,16 +470,16 @@ bool RDIL::format(const ILExpression* e, std::string& res) return true; } -void RDIL::wrapWalk(const ILExpression* e, const RDIL::WalkCallback& cb) +void RDIL::wrapWalk(const ILExpression* e, const RDIL::ToStringCallback& cb) { if(RDIL::hasValue(e) || IS_TYPE(e, RDIL_Mem)) { - RDIL::walk(e, cb); + RDIL::toString(e, cb); return; } cb(e, "(", WalkType::Normal); - RDIL::walk(e, cb); + RDIL::toString(e, cb); cb(e, ")", WalkType::Normal); } @@ -428,7 +498,7 @@ void RDIL::wrapFormat(const ILExpression* e, std::string& res) void RDIL::getText(const ILExpression* e, std::string& res) { - RDIL::walk(e, [&res](const ILExpression* expr, const std::string& s, WalkType) { + RDIL::toString(e, [&res](const ILExpression* expr, const std::string& s, WalkType) { switch(expr->type) { case RDIL_Cnst: res += Utils::hex(expr->u_value); break; case RDIL_Var: res += expr->var; break; diff --git a/rdcore/rdil/rdil.h b/rdcore/rdil/rdil.h index e0f2ad0b..cfd46c34 100644 --- a/rdcore/rdil/rdil.h +++ b/rdcore/rdil/rdil.h @@ -2,9 +2,10 @@ #include #include +#include #include -#include #include "expression.h" +#include "ilfunction.h" class Renderer; @@ -12,9 +13,10 @@ class RDIL { private: enum class WalkType { Normal = 0, Mnemonic, Whitespace, }; - typedef std::function WalkCallback; + typedef std::function WalkCallback; + typedef std::function ToStringCallback; + typedef std::function FormatCallback; struct RDILQueryItem { std::string nodeid, opcode; }; - typedef std::queue RDILQuery; public: RDIL() = delete; @@ -23,16 +25,18 @@ class RDIL static std::string getText(const ILExpression* e); static std::string getFormat(const ILExpression* e); static void render(const ILExpression* e, Renderer* renderer, rd_address address); - static const ILExpression* extract(const ILExpression* e, const char* q); + static size_t extract(const ILExpression* e, const RDILValue** values); + static size_t extract(const ILFunction* f, const RDILValue** values); + static bool match(const ILFunction* f, const char* m); static bool match(const ILExpression* e, const char* m); static bool hasValue(const ILExpression* e); private: - static const ILExpression* extract(const ILExpression* e, const RDILQueryItem& qi, RDILQuery& query, int depth = 0); + static void extract(const ILExpression* e, std::vector& values); + static void toString(const ILExpression* e, const ToStringCallback& cb); static void walk(const ILExpression* e, const WalkCallback& cb); static bool format(const ILExpression* e, std::string& res); - static bool parseQuery(const std::string& q, RDILQuery& query); - static void wrapWalk(const ILExpression* e, const WalkCallback& cb); + static void wrapWalk(const ILExpression* e, const ToStringCallback& cb); static void wrapFormat(const ILExpression* e, std::string& res); static void getText(const ILExpression* e, std::string& res); static std::string textOp(const ILExpression* e);