Skip to content

Commit 8767400

Browse files
committed
Add line formatter API and a generic line formatter plugin
1 parent 1c81ef6 commit 8767400

18 files changed

+1821
-49
lines changed

basicblock.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,24 @@ DisassemblySettings::DisassemblySettings(BNDisassemblySettings* settings)
3636
}
3737

3838

39+
Ref<DisassemblySettings> DisassemblySettings::GetDefaultSettings()
40+
{
41+
return new DisassemblySettings(BNDefaultDisassemblySettings());
42+
}
43+
44+
45+
Ref<DisassemblySettings> DisassemblySettings::GetDefaultGraphSettings()
46+
{
47+
return new DisassemblySettings(BNDefaultGraphDisassemblySettings());
48+
}
49+
50+
51+
Ref<DisassemblySettings> DisassemblySettings::GetDefaultLinearSettings()
52+
{
53+
return new DisassemblySettings(BNDefaultLinearDisassemblySettings());
54+
}
55+
56+
3957
DisassemblySettings* DisassemblySettings::Duplicate()
4058
{
4159
return new DisassemblySettings(BNDuplicateDisassemblySettings(m_object));
@@ -144,6 +162,73 @@ DisassemblyTextLine::DisassemblyTextLine()
144162
}
145163

146164

165+
size_t DisassemblyTextLine::GetTotalWidth() const
166+
{
167+
size_t result = 0;
168+
for (auto& i : tokens)
169+
result += i.width;
170+
return result;
171+
}
172+
173+
174+
static void FindAddressAndIndentationTokens(
175+
const vector<InstructionTextToken>& tokens, const std::function<void(const InstructionTextToken&)>& callback)
176+
{
177+
size_t startToken = 0;
178+
for (size_t i = 0; i < tokens.size(); i++)
179+
{
180+
if (tokens[i].type == AddressSeparatorToken)
181+
{
182+
startToken = i + 1;
183+
break;
184+
}
185+
}
186+
187+
for (size_t i = 0; i < startToken; i++)
188+
callback(tokens[i]);
189+
for (size_t i = startToken; i < tokens.size(); i++)
190+
{
191+
if (tokens[i].type == AddressDisplayToken || tokens[i].type == AddressSeparatorToken
192+
|| tokens[i].type == CollapseStateIndicatorToken)
193+
{
194+
callback(tokens[i]);
195+
continue;
196+
}
197+
198+
bool whitespace = true;
199+
for (auto ch : tokens[i].text)
200+
{
201+
if (!isspace(ch))
202+
{
203+
whitespace = false;
204+
break;
205+
}
206+
}
207+
208+
if (!whitespace)
209+
break;
210+
211+
callback(tokens[i]);
212+
}
213+
}
214+
215+
216+
size_t DisassemblyTextLine::GetAddressAndIndentationWidth() const
217+
{
218+
size_t result = 0;
219+
FindAddressAndIndentationTokens(tokens, [&](const InstructionTextToken& token) { result += token.width; });
220+
return result;
221+
}
222+
223+
224+
vector<InstructionTextToken> DisassemblyTextLine::GetAddressAndIndentationTokens() const
225+
{
226+
vector<InstructionTextToken> result;
227+
FindAddressAndIndentationTokens(tokens, [&](const InstructionTextToken& token) { result.push_back(token); });
228+
return result;
229+
}
230+
231+
147232
BasicBlock::BasicBlock(BNBasicBlock* block)
148233
{
149234
m_object = block;

binaryninjaapi.h

+96-1
Original file line numberDiff line numberDiff line change
@@ -4057,6 +4057,10 @@ namespace BinaryNinja {
40574057
DisassemblyTextLineTypeInfo typeInfo;
40584058

40594059
DisassemblyTextLine();
4060+
4061+
size_t GetTotalWidth() const;
4062+
size_t GetAddressAndIndentationWidth() const;
4063+
std::vector<InstructionTextToken> GetAddressAndIndentationTokens() const;
40604064
};
40614065

40624066
/*!
@@ -10175,6 +10179,10 @@ namespace BinaryNinja {
1017510179
DisassemblySettings(BNDisassemblySettings* settings);
1017610180
DisassemblySettings* Duplicate();
1017710181

10182+
static Ref<DisassemblySettings> GetDefaultSettings();
10183+
static Ref<DisassemblySettings> GetDefaultGraphSettings();
10184+
static Ref<DisassemblySettings> GetDefaultLinearSettings();
10185+
1017810186
bool IsOptionSet(BNDisassemblyOption option) const;
1017910187
void SetOption(BNDisassemblyOption option, bool state = true);
1018010188

@@ -13698,6 +13706,82 @@ namespace BinaryNinja {
1369813706
std::set<SSAVariable> GetSSAVariables();
1369913707
};
1370013708

13709+
struct LineFormatterSettings
13710+
{
13711+
Ref<HighLevelILFunction> highLevelIL;
13712+
size_t desiredLineLength;
13713+
size_t minimumContentLength;
13714+
size_t tabWidth;
13715+
std::string languageName;
13716+
std::string commentStartString;
13717+
std::string commentEndString;
13718+
std::string annotationStartString;
13719+
std::string annotationEndString;
13720+
13721+
/*! Gets the default line formatter settings for High Level IL code.
13722+
13723+
\param settings The settings for reformatting.
13724+
\param func High Level IL function to be reformatted.
13725+
\return Settings for reformatting.
13726+
*/
13727+
static LineFormatterSettings GetDefault(DisassemblySettings* settings, HighLevelILFunction* func);
13728+
13729+
/*! Gets the default line formatter settings for a language representation function.
13730+
13731+
\param settings The settings for reformatting.
13732+
\param func Language representation function to be reformatted.
13733+
\return Settings for reformatting.
13734+
*/
13735+
static LineFormatterSettings GetLanguageRepresentationSettings(
13736+
DisassemblySettings* settings, LanguageRepresentationFunction* func);
13737+
13738+
static LineFormatterSettings FromAPIObject(const BNLineFormatterSettings* settings);
13739+
BNLineFormatterSettings ToAPIObject() const;
13740+
};
13741+
13742+
class LineFormatter : public StaticCoreRefCountObject<BNLineFormatter>
13743+
{
13744+
std::string m_nameForRegister;
13745+
13746+
static BNDisassemblyTextLine* FormatLinesCallback(void* ctxt, BNDisassemblyTextLine* inLines, size_t inCount,
13747+
const BNLineFormatterSettings* settings, size_t* outCount);
13748+
static void FreeLinesCallback(void* ctxt, BNDisassemblyTextLine* lines, size_t count);
13749+
13750+
public:
13751+
LineFormatter(const std::string& name);
13752+
LineFormatter(BNLineFormatter* formatter);
13753+
13754+
/*! Registers the line formatter.
13755+
13756+
\param formatter The line formatter to register.
13757+
*/
13758+
static void Register(LineFormatter* formatter);
13759+
13760+
static std::vector<Ref<LineFormatter>> GetList();
13761+
static Ref<LineFormatter> GetByName(const std::string& name);
13762+
static Ref<LineFormatter> GetDefault();
13763+
13764+
/*! Reformats the given list of lines. Returns a new list of lines containing the reformatted code.
13765+
13766+
\param lines The lines to reformat.
13767+
\param settings The settings for reformatting.
13768+
\return A new list of reformatted lines.
13769+
*/
13770+
virtual std::vector<DisassemblyTextLine> FormatLines(
13771+
const std::vector<DisassemblyTextLine>& lines, const LineFormatterSettings& settings) = 0;
13772+
};
13773+
13774+
class CoreLineFormatter : public LineFormatter
13775+
{
13776+
public:
13777+
CoreLineFormatter(BNLineFormatter* formatter);
13778+
13779+
std::vector<DisassemblyTextLine> FormatLines(
13780+
const std::vector<DisassemblyTextLine>& lines, const LineFormatterSettings& settings) override;
13781+
};
13782+
13783+
class LanguageRepresentationFunctionType;
13784+
1370113785
/*! LanguageRepresentationFunction represents a single function in a registered high level language.
1370213786

1370313787
\ingroup highlevelil
@@ -13707,7 +13791,8 @@ namespace BinaryNinja {
1370713791
BNFreeLanguageRepresentationFunction>
1370813792
{
1370913793
public:
13710-
LanguageRepresentationFunction(Architecture* arch, Function* func, HighLevelILFunction* highLevelIL);
13794+
LanguageRepresentationFunction(LanguageRepresentationFunctionType* type, Architecture* arch, Function* func,
13795+
HighLevelILFunction* highLevelIL);
1371113796
LanguageRepresentationFunction(BNLanguageRepresentationFunction* func);
1371213797

1371313798
/*! Gets the lines of tokens for a given High Level IL instruction.
@@ -13746,6 +13831,7 @@ namespace BinaryNinja {
1374613831
*/
1374713832
BNHighlightColor GetHighlight(BasicBlock* block);
1374813833

13834+
Ref<LanguageRepresentationFunctionType> GetLanguage() const;
1374913835
Ref<Architecture> GetArchitecture() const;
1375013836
Ref<Function> GetFunction() const;
1375113837
Ref<HighLevelILFunction> GetHighLevelILFunction() const;
@@ -13894,6 +13980,13 @@ namespace BinaryNinja {
1389413980
*/
1389513981
virtual Ref<TypeParser> GetTypeParser() { return nullptr; }
1389613982

13983+
/*! Returns the line formatter for formatting code in this language. If NULL is returned, the default
13984+
formatter will be used.
13985+
13986+
\return The optional formatter for formatting code in this language.
13987+
*/
13988+
virtual Ref<LineFormatter> GetLineFormatter() { return nullptr; }
13989+
1389713990
/*! Returns a list of lines representing a function prototype in this language. If no lines are returned, the
1389813991
default C-style prototype will be used.
1389913992

@@ -13920,6 +14013,7 @@ namespace BinaryNinja {
1392014013
static bool IsValidCallback(void* ctxt, BNBinaryView* view);
1392114014
static BNTypePrinter* GetTypePrinterCallback(void* ctxt);
1392214015
static BNTypeParser* GetTypeParserCallback(void* ctxt);
14016+
static BNLineFormatter* GetLineFormatterCallback(void* ctxt);
1392314017
static BNDisassemblyTextLine* GetFunctionTypeTokensCallback(
1392414018
void* ctxt, BNFunction* func, BNDisassemblySettings* settings, size_t* count);
1392514019
static void FreeLinesCallback(void* ctxt, BNDisassemblyTextLine* lines, size_t count);
@@ -13934,6 +14028,7 @@ namespace BinaryNinja {
1393414028
bool IsValid(BinaryView* view) override;
1393514029
Ref<TypePrinter> GetTypePrinter() override;
1393614030
Ref<TypeParser> GetTypeParser() override;
14031+
Ref<LineFormatter> GetLineFormatter() override;
1393714032
std::vector<DisassemblyTextLine> GetFunctionTypeTokens(
1393814033
Function* func, DisassemblySettings* settings = nullptr) override;
1393914034
};

binaryninjacore.h

+54-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
// will require rebuilding. The minimum version is increased when there are
4545
// incompatible changes that break binary compatibility, such as changes to
4646
// existing types or functions.
47-
#define BN_MINIMUM_CORE_ABI_VERSION 86
47+
#define BN_MINIMUM_CORE_ABI_VERSION 89
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -302,6 +302,7 @@ extern "C"
302302
typedef struct BNDemangler BNDemangler;
303303
typedef struct BNFirmwareNinja BNFirmwareNinja;
304304
typedef struct BNFirmwareNinjaReferenceNode BNFirmwareNinjaReferenceNode;
305+
typedef struct BNLineFormatter BNLineFormatter;
305306

306307
//! Console log levels
307308
typedef enum BNLogLevel
@@ -727,6 +728,7 @@ extern "C"
727728
HighLevelILLinearDisassembly = 65,
728729
WaitForIL = 66,
729730
IndentHLILBody = 67,
731+
DisableLineFormatting = 68,
730732

731733
// Debugging options
732734
ShowFlagUsage = 128,
@@ -3439,6 +3441,7 @@ extern "C"
34393441
bool (*isValid)(void* ctxt, BNBinaryView* view);
34403442
BNTypePrinter* (*getTypePrinter)(void* ctxt);
34413443
BNTypeParser* (*getTypeParser)(void* ctxt);
3444+
BNLineFormatter* (*getLineFormatter)(void* ctxt);
34423445
BNDisassemblyTextLine* (*getFunctionTypeTokens)(
34433446
void* ctxt, BNFunction* func, BNDisassemblySettings* settings, size_t* count);
34443447
void (*freeLines)(void* ctxt, BNDisassemblyTextLine* lines, size_t count);
@@ -3538,6 +3541,28 @@ extern "C"
35383541
size_t unique;
35393542
} BNFirmwareNinjaDeviceAccesses;
35403543

3544+
typedef struct BNLineFormatterSettings
3545+
{
3546+
BNHighLevelILFunction* highLevelIL;
3547+
size_t desiredLineLength;
3548+
size_t minimumContentLength;
3549+
size_t tabWidth;
3550+
char* languageName;
3551+
char* commentStartString;
3552+
char* commentEndString;
3553+
char* annotationStartString;
3554+
char* annotationEndString;
3555+
} BNLineFormatterSettings;
3556+
3557+
typedef struct BNCustomLineFormatter
3558+
{
3559+
void* context;
3560+
BNDisassemblyTextLine* (*formatLines)(void* ctxt, BNDisassemblyTextLine* inLines, size_t inCount,
3561+
const BNLineFormatterSettings* settings, size_t* outCount);
3562+
void (*freeLines)(void* ctxt, BNDisassemblyTextLine* lines, size_t count);
3563+
} BNCustomLineFormatter;
3564+
3565+
35413566
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
35423567
BINARYNINJACOREAPI char* BNAllocStringWithLength(const char* contents, size_t len);
35433568
BINARYNINJACOREAPI void BNFreeString(char* str);
@@ -5454,6 +5479,9 @@ extern "C"
54545479

54555480
// Disassembly settings
54565481
BINARYNINJACOREAPI BNDisassemblySettings* BNCreateDisassemblySettings(void);
5482+
BINARYNINJACOREAPI BNDisassemblySettings* BNDefaultDisassemblySettings(void);
5483+
BINARYNINJACOREAPI BNDisassemblySettings* BNDefaultGraphDisassemblySettings(void);
5484+
BINARYNINJACOREAPI BNDisassemblySettings* BNDefaultLinearDisassemblySettings(void);
54575485
BINARYNINJACOREAPI BNDisassemblySettings* BNNewDisassemblySettingsReference(BNDisassemblySettings* settings);
54585486
BINARYNINJACOREAPI BNDisassemblySettings* BNDuplicateDisassemblySettings(BNDisassemblySettings* settings);
54595487
BINARYNINJACOREAPI void BNFreeDisassemblySettings(BNDisassemblySettings* settings);
@@ -6144,15 +6172,19 @@ extern "C"
61446172
BNLanguageRepresentationFunctionType* type, BNBinaryView* view);
61456173
BINARYNINJACOREAPI BNTypePrinter* BNGetLanguageRepresentationFunctionTypePrinter(BNLanguageRepresentationFunctionType* type);
61466174
BINARYNINJACOREAPI BNTypeParser* BNGetLanguageRepresentationFunctionTypeParser(BNLanguageRepresentationFunctionType* type);
6175+
BINARYNINJACOREAPI BNLineFormatter* BNGetLanguageRepresentationFunctionTypeLineFormatter(
6176+
BNLanguageRepresentationFunctionType* type);
61476177
BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetLanguageRepresentationFunctionTypeFunctionTypeTokens(
61486178
BNLanguageRepresentationFunctionType* type, BNFunction* func, BNDisassemblySettings* settings, size_t* count);
61496179

61506180
BINARYNINJACOREAPI BNLanguageRepresentationFunction* BNCreateCustomLanguageRepresentationFunction(
6151-
BNArchitecture* arch, BNFunction* func, BNHighLevelILFunction* highLevelIL,
6152-
BNCustomLanguageRepresentationFunction* callbacks);
6181+
BNLanguageRepresentationFunctionType* type, BNArchitecture* arch, BNFunction* func,
6182+
BNHighLevelILFunction* highLevelIL, BNCustomLanguageRepresentationFunction* callbacks);
61536183
BINARYNINJACOREAPI BNLanguageRepresentationFunction* BNNewLanguageRepresentationFunctionReference(
61546184
BNLanguageRepresentationFunction* func);
61556185
BINARYNINJACOREAPI void BNFreeLanguageRepresentationFunction(BNLanguageRepresentationFunction* func);
6186+
BINARYNINJACOREAPI BNLanguageRepresentationFunctionType* BNGetLanguageRepresentationType(
6187+
BNLanguageRepresentationFunction* func);
61566188
BINARYNINJACOREAPI BNArchitecture* BNGetLanguageRepresentationArchitecture(BNLanguageRepresentationFunction* func);
61576189
BINARYNINJACOREAPI BNFunction* BNGetLanguageRepresentationOwnerFunction(BNLanguageRepresentationFunction* func);
61586190
BINARYNINJACOREAPI BNHighLevelILFunction* BNGetLanguageRepresentationILFunction(BNLanguageRepresentationFunction* func);
@@ -8057,6 +8089,25 @@ extern "C"
80578089
BINARYNINJACOREAPI void BNFreeFirmwareNinjaReferenceNode(BNFirmwareNinjaReferenceNode* node);
80588090
BINARYNINJACOREAPI BNFirmwareNinjaReferenceNode* BNNewFirmwareNinjaReferenceNodeReference(BNFirmwareNinjaReferenceNode* node);
80598091
BINARYNINJACOREAPI void BNFreeFirmwareNinjaReferenceNodes(BNFirmwareNinjaReferenceNode** nodes, size_t count);
8092+
8093+
// Line formatters
8094+
BINARYNINJACOREAPI BNLineFormatter* BNRegisterLineFormatter(const char* name, BNCustomLineFormatter* callbacks);
8095+
BINARYNINJACOREAPI BNLineFormatter** BNGetLineFormatterList(size_t* count);
8096+
BINARYNINJACOREAPI void BNFreeLineFormatterList(BNLineFormatter** formatters);
8097+
BINARYNINJACOREAPI BNLineFormatter* BNGetLineFormatterByName(const char* name);
8098+
BINARYNINJACOREAPI BNLineFormatter* BNGetDefaultLineFormatter();
8099+
8100+
BINARYNINJACOREAPI char* BNGetLineFormatterName(BNLineFormatter* formatter);
8101+
8102+
BINARYNINJACOREAPI BNDisassemblyTextLine* BNFormatLines(BNLineFormatter* formatter, BNDisassemblyTextLine* inLines,
8103+
size_t inCount, const BNLineFormatterSettings* settings, size_t* outCount);
8104+
8105+
BINARYNINJACOREAPI BNLineFormatterSettings* BNGetDefaultLineFormatterSettings(
8106+
BNDisassemblySettings* settings, BNHighLevelILFunction* func);
8107+
BINARYNINJACOREAPI BNLineFormatterSettings* BNGetLanguageRepresentationLineFormatterSettings(
8108+
BNDisassemblySettings* settings, BNLanguageRepresentationFunction* func);
8109+
BINARYNINJACOREAPI void BNFreeLineFormatterSettings(BNLineFormatterSettings* settings);
8110+
80608111
#ifdef __cplusplus
80618112
}
80628113
#endif

0 commit comments

Comments
 (0)