diff options
| author | Mark Rowe <mrowe@bdash.net.nz> | 2025-05-07 18:22:50 -0700 |
|---|---|---|
| committer | kat <kat@vector35.com> | 2025-05-29 09:42:11 -0400 |
| commit | 4ea37e18bfed8de162dfb816971417a0679b602f (patch) | |
| tree | 899c8f86701c7a8e2359c84d73e9c2ba2759c540 /lang/c/pseudoc.cpp | |
| parent | c55c604031e0d04a44c39832f5887e2d9aa7314e (diff) | |
Implement a Pseudo Objective-C language representation
This is implemented in the Pseudo C plug-in as it shares 99% of the
logic. The Objective-C support is implemented in a subclass of
`PseudoCFunction`. The handling of instruction types that the
Objective-C representation needs to customize is extracted into virtual
functions that the Objective-C subclass overrides.
This currently supports:
* Rewriting `objc_msgSend` / `objc_msgSendSuper2` with constant
selectors to `[receiver message]` notation.
* Rewriting calls to `objc_alloc` / `objc_alloc_init` / `objc_new` to
the equivalent message send notation.
* Rewriting `objc_retain` / `objc_release` and friends to the
equivalent message send notation.
* Displaying Objective-C class references as their class names rather
than `_OBJC_CLASS_$_` symbol names.
* Displaying Objective-C string literals as `@"..."`.
This works best when used in conjunction with
https://github.com/bdash/bn-objc-extras as the reference counting runtime
calls add so much clutter.
Diffstat (limited to 'lang/c/pseudoc.cpp')
| -rw-r--r-- | lang/c/pseudoc.cpp | 192 |
1 files changed, 88 insertions, 104 deletions
diff --git a/lang/c/pseudoc.cpp b/lang/c/pseudoc.cpp index 7046c6d0..fdc044fc 100644 --- a/lang/c/pseudoc.cpp +++ b/lang/c/pseudoc.cpp @@ -976,73 +976,11 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H break; case HLIL_CALL: - [&]() { - const auto destExpr = instr.GetDestExpr<HLIL_CALL>(); - const auto parameterExprs = instr.GetParameterExprs<HLIL_CALL>(); - - GetExprTextInternal(destExpr, tokens, settings, MemberAndFunctionOperatorPrecedence); - tokens.AppendOpenParen(); - - vector<FunctionParameter> namedParams; - Ref<Type> functionType = instr.GetDestExpr<HLIL_CALL>().GetType(); - if (functionType && (functionType->GetClass() == PointerTypeClass) - && (functionType->GetChildType()->GetClass() == FunctionTypeClass)) - namedParams = functionType->GetChildType()->GetParameters(); - - for (size_t index{}; index < parameterExprs.size(); index++) - { - const auto& parameterExpr = parameterExprs[index]; - if (index != 0) tokens.Append(TextToken, ", "); - - // If the type of the parameter is known to be a pointer to a string, then we directly render it as a - // string, regardless of its length - bool renderedAsString = false; - if (index < namedParams.size() && parameterExprs[index].operation == HLIL_CONST_PTR) - { - auto exprType = namedParams[index].type; - if (exprType && (exprType->GetClass() == PointerTypeClass)) - { - if (auto child = exprType->GetChildType(); child) - { - if ((child->IsInteger() && child->IsSigned() && child->GetWidth() == 1) - || child->IsWideChar()) - { - tokens.AppendPointerTextToken(parameterExprs[index], - parameterExprs[index].GetConstant<HLIL_CONST_PTR>(), settings, AddressOfDataSymbols, - precedence, true); - renderedAsString = true; - } - } - } - } - - if (!renderedAsString) - GetExprText(parameterExpr, tokens, settings); - } - tokens.AppendCloseParen(); - if (statement) - tokens.AppendSemicolon(); - }(); + GetExpr_CALL_OR_TAILCALL(instr, tokens, settings, precedence, statement); break; case HLIL_IMPORT: - [&]() { - const auto constant = instr.GetConstant<HLIL_IMPORT>(); - auto symbol = GetHighLevelILFunction()->GetFunction()->GetView()->GetSymbolByAddress(constant); - const auto symbolType = symbol->GetType(); - - if (symbol && (symbolType == ImportedDataSymbol || symbolType == ImportAddressSymbol)) - { - symbol = Symbol::ImportedFunctionFromImportAddressSymbol(symbol, constant); - const auto symbolShortName = symbol->GetShortName(); - tokens.Append(IndirectImportToken, NoTokenContext, symbolShortName, instr.address, constant, instr.size, instr.sourceOperand); - return; - } - - tokens.AppendPointerTextToken(instr, constant, settings, DereferenceNonDataSymbols, precedence); - if (statement) - tokens.AppendSemicolon(); - }(); + GetExpr_IMPORT(instr, tokens, settings, precedence, statement); break; case HLIL_ARRAY_INDEX: @@ -1288,12 +1226,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H break; case HLIL_CONST_PTR: - [&]() { - tokens.AppendPointerTextToken( - instr, instr.GetConstant<HLIL_CONST_PTR>(), settings, AddressOfDataSymbols, precedence); - if (statement) - tokens.AppendSemicolon(); - }(); + GetExpr_CONST_PTR(instr, tokens, settings, precedence, statement); break; case HLIL_VAR: @@ -1766,17 +1699,8 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H tokens.Append(AnnotationToken, "/* tailcall */"); tokens.NewLine(); tokens.Append(KeywordToken, "return "); - GetExprTextInternal(destExpr, tokens, settings, MemberAndFunctionOperatorPrecedence); - tokens.AppendOpenParen(); - for (size_t index{}; index < parameterExprs.size(); index++) - { - const auto& parameterExpr = parameterExprs[index]; - if (index != 0) tokens.Append(TextToken, ", "); - GetExprTextInternal(parameterExpr, tokens, settings); - } - tokens.AppendCloseParen(); - if (statement) - tokens.AppendSemicolon(); + + GetExpr_CALL_OR_TAILCALL(instr, tokens, settings, precedence, statement); }(); break; @@ -2829,6 +2753,88 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H } } +void PseudoCFunction::GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelILInstruction& instr, + BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings, + BNOperatorPrecedence precedence, bool statement) +{ + const auto destExpr = instr.GetDestExpr(); + const auto parameterExprs = instr.GetParameterExprs(); + + vector<FunctionParameter> namedParams; + Ref<Type> functionType = destExpr.GetType(); + if (functionType && (functionType->GetClass() == PointerTypeClass) + && (functionType->GetChildType()->GetClass() == FunctionTypeClass)) + namedParams = functionType->GetChildType()->GetParameters(); + + GetExprTextInternal(destExpr, tokens, settings, MemberAndFunctionOperatorPrecedence); + tokens.AppendOpenParen(); + + for (size_t index {}; index < parameterExprs.size(); index++) + { + const auto& parameterExpr = parameterExprs[index]; + if (index != 0) + tokens.Append(TextToken, ", "); + + // If the type of the parameter is known to be a pointer to a string, then we directly render it as a + // string, regardless of its length + bool renderedAsString = false; + if (index < namedParams.size() && parameterExprs[index].operation == HLIL_CONST_PTR) + { + auto exprType = namedParams[index].type; + if (exprType && (exprType->GetClass() == PointerTypeClass)) + { + if (auto child = exprType->GetChildType(); child) + { + if ((child->IsInteger() && child->IsSigned() && child->GetWidth() == 1) || child->IsWideChar()) + { + tokens.AppendPointerTextToken(parameterExprs[index], + parameterExprs[index].GetConstant<HLIL_CONST_PTR>(), settings, AddressOfDataSymbols, + precedence, true); + renderedAsString = true; + } + } + } + } + + if (!renderedAsString) + GetExprText(parameterExpr, tokens, settings); + } + tokens.AppendCloseParen(); + if (statement) + tokens.AppendSemicolon(); +} + +void PseudoCFunction::GetExpr_CONST_PTR(const BinaryNinja::HighLevelILInstruction& instr, + BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings, + BNOperatorPrecedence precedence, bool statement) +{ + auto constant = instr.GetConstant<HLIL_CONST_PTR>(); + tokens.AppendPointerTextToken( + instr, instr.GetConstant<HLIL_CONST_PTR>(), settings, AddressOfDataSymbols, precedence); + if (statement) + tokens.AppendSemicolon(); +} + +void PseudoCFunction::GetExpr_IMPORT(const BinaryNinja::HighLevelILInstruction& instr, + BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings, + BNOperatorPrecedence precedence, bool statement) +{ + const auto constant = instr.GetConstant<HLIL_IMPORT>(); + auto symbol = GetHighLevelILFunction()->GetFunction()->GetView()->GetSymbolByAddress(constant); + const auto symbolType = symbol->GetType(); + + if (symbol && (symbolType == ImportedDataSymbol || symbolType == ImportAddressSymbol)) + { + symbol = Symbol::ImportedFunctionFromImportAddressSymbol(symbol, constant); + const auto symbolShortName = symbol->GetShortName(); + tokens.Append(IndirectImportToken, NoTokenContext, symbolShortName, instr.address, constant, instr.size, instr.sourceOperand); + return; + } + + tokens.AppendPointerTextToken(instr, constant, settings, DereferenceNonDataSymbols, precedence); + if (statement) + tokens.AppendSemicolon(); +} string PseudoCFunction::GetAnnotationStartString() const { @@ -2848,32 +2854,10 @@ PseudoCFunctionType::PseudoCFunctionType(): LanguageRepresentationFunctionType(" { } +PseudoCFunctionType::PseudoCFunctionType(const string& name) : LanguageRepresentationFunctionType(name) {} Ref<LanguageRepresentationFunction> PseudoCFunctionType::Create(Architecture* arch, Function* owner, HighLevelILFunction* highLevelILFunction) { return new PseudoCFunction(this, arch, owner, highLevelILFunction); } - - -extern "C" -{ - BN_DECLARE_CORE_ABI_VERSION - -#ifndef DEMO_EDITION - BINARYNINJAPLUGIN void CorePluginDependencies() - { - } -#endif - -#ifdef DEMO_EDITION - bool PseudoCPluginInit() -#else - BINARYNINJAPLUGIN bool CorePluginInit() -#endif - { - LanguageRepresentationFunctionType* type = new PseudoCFunctionType(); - LanguageRepresentationFunctionType::Register(type); - return true; - } -} |
