Skip to content

Implement a Pseudo Objective-C language representation #6807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions lang/c/plugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "binaryninjaapi.h"
#include "pseudoc.h"
#include "pseudoobjc.h"

using namespace BinaryNinja;

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);

type = new PseudoObjCFunctionType();
LanguageRepresentationFunctionType::Register(type);
return true;
}
}
192 changes: 88 additions & 104 deletions lang/c/pseudoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -2800,6 +2724,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
{
Expand All @@ -2819,32 +2825,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;
}
}
13 changes: 13 additions & 0 deletions lang/c/pseudoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ class PseudoCFunction: public BinaryNinja::LanguageRepresentationFunction
void EndLines(
const BinaryNinja::HighLevelILInstruction& instr, BinaryNinja::HighLevelILTokenEmitter& tokens) override;

virtual void GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelILInstruction& instr,
BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
BNOperatorPrecedence precedence, bool statement);
virtual void GetExpr_CONST_PTR(const BinaryNinja::HighLevelILInstruction& instr,
BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
BNOperatorPrecedence precedence, bool statement);
virtual void GetExpr_IMPORT(const BinaryNinja::HighLevelILInstruction& instr,
BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
BNOperatorPrecedence precedence, bool statement);

public:
PseudoCFunction(BinaryNinja::LanguageRepresentationFunctionType* type, BinaryNinja::Architecture* arch,
BinaryNinja::Function* owner, BinaryNinja::HighLevelILFunction* highLevelILFunction);
Expand All @@ -66,4 +76,7 @@ class PseudoCFunctionType: public BinaryNinja::LanguageRepresentationFunctionTyp
PseudoCFunctionType();
BinaryNinja::Ref<BinaryNinja::LanguageRepresentationFunction> Create(BinaryNinja::Architecture* arch,
BinaryNinja::Function* owner, BinaryNinja::HighLevelILFunction* highLevelILFunction) override;

protected:
PseudoCFunctionType(const std::string& name);
};
Loading