Skip to content

Commit e7ab0ac

Browse files
committed
Add format string resolution provider API
1 parent 73bd58d commit e7ab0ac

4 files changed

Lines changed: 207 additions & 1 deletion

File tree

.doxygen.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@
9797
\defgroup flowgraph Flowgraph
9898
\ingroup coreapi
9999
*/
100+
/*!
101+
\defgroup formatstringresolutionprovider Format String Resolution Provider
102+
\ingroup coreapi
103+
*/
100104
/*!
101105
\defgroup function Function
102106
\ingroup coreapi

binaryninjaapi.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20941,6 +20941,49 @@ namespace BinaryNinja {
2094120941
virtual bool DeleteData(const std::string& key) override;
2094220942
};
2094320943

20944+
/*! Resolves the argument types described by a format string.
20945+
20946+
\ingroup formatstringresolutionprovider
20947+
*/
20948+
class FormatStringResolutionProvider : public StaticCoreRefCountObject<BNFormatStringResolutionProvider>
20949+
{
20950+
std::string m_nameForRegister;
20951+
20952+
protected:
20953+
FormatStringResolutionProvider(const std::string& name);
20954+
FormatStringResolutionProvider(BNFormatStringResolutionProvider* provider);
20955+
20956+
static bool IsValidCallback(
20957+
void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count);
20958+
static void FreeTypeListCallback(void* ctxt, BNTypeWithConfidence* types, size_t count);
20959+
20960+
public:
20961+
/*! Resolve the argument types described by a format string.
20962+
20963+
\param format Format string to validate and resolve
20964+
\return A list of argument types when valid, including an empty list for a valid format with no
20965+
arguments, or an empty optional when invalid
20966+
*/
20967+
virtual std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(const std::string& format) = 0;
20968+
20969+
std::string GetName() const;
20970+
static std::vector<Ref<FormatStringResolutionProvider>> GetList();
20971+
static Ref<FormatStringResolutionProvider> GetByName(const std::string& name);
20972+
static void Register(FormatStringResolutionProvider* provider);
20973+
};
20974+
20975+
/*!
20976+
\ingroup formatstringresolutionprovider
20977+
*/
20978+
class CoreFormatStringResolutionProvider : public FormatStringResolutionProvider
20979+
{
20980+
public:
20981+
CoreFormatStringResolutionProvider(BNFormatStringResolutionProvider* provider);
20982+
20983+
virtual std::optional<std::vector<Confidence<Ref<Type>>>> IsValid(
20984+
const std::string& format) override;
20985+
};
20986+
2094420987
/*! Components are objects that can contain Functions and other Components.
2094520988

2094620989
\note Components should not be instantiated directly. Instead use BinaryView::CreateComponent()

binaryninjacore.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 179
40+
#define BN_CURRENT_CORE_ABI_VERSION 180
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
@@ -316,6 +316,7 @@ extern "C"
316316
typedef struct BNDebugInfo BNDebugInfo;
317317
typedef struct BNDebugInfoParser BNDebugInfoParser;
318318
typedef struct BNSecretsProvider BNSecretsProvider;
319+
typedef struct BNFormatStringResolutionProvider BNFormatStringResolutionProvider;
319320
typedef struct BNLogger BNLogger;
320321
typedef struct BNSymbolQueue BNSymbolQueue;
321322
typedef struct BNTypeArchive BNTypeArchive;
@@ -3744,6 +3745,13 @@ extern "C"
37443745
bool (*deleteData)(void* ctxt, const char* key);
37453746
} BNSecretsProviderCallbacks;
37463747

3748+
typedef struct BNFormatStringResolutionProviderCallbacks
3749+
{
3750+
void* context;
3751+
bool (*isValid)(void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count);
3752+
void (*freeTypeList)(void* ctxt, BNTypeWithConfidence* types, size_t count);
3753+
} BNFormatStringResolutionProviderCallbacks;
3754+
37473755
typedef struct BNMergedVariable
37483756
{
37493757
BNVariable target;
@@ -8727,6 +8735,20 @@ extern "C"
87278735
BINARYNINJACOREAPI bool BNStoreSecretsProviderData(BNSecretsProvider* provider, const char* key, const char* data);
87288736
BINARYNINJACOREAPI bool BNDeleteSecretsProviderData(BNSecretsProvider* provider, const char* key);
87298737

8738+
// Format string resolution providers
8739+
BINARYNINJACOREAPI BNFormatStringResolutionProvider* BNRegisterFormatStringResolutionProvider(
8740+
const char* name, BNFormatStringResolutionProviderCallbacks* callbacks);
8741+
BINARYNINJACOREAPI BNFormatStringResolutionProvider** BNGetFormatStringResolutionProviderList(size_t* count);
8742+
BINARYNINJACOREAPI void BNFreeFormatStringResolutionProviderList(
8743+
BNFormatStringResolutionProvider** providers);
8744+
BINARYNINJACOREAPI BNFormatStringResolutionProvider* BNGetFormatStringResolutionProviderByName(const char* name);
8745+
BINARYNINJACOREAPI char* BNGetFormatStringResolutionProviderName(
8746+
BNFormatStringResolutionProvider* provider);
8747+
BINARYNINJACOREAPI bool BNFormatStringResolutionProviderIsValid(
8748+
BNFormatStringResolutionProvider* provider, const char* format,
8749+
BNTypeWithConfidence** types, size_t* count);
8750+
BINARYNINJACOREAPI void BNFreeTypeWithConfidenceList(BNTypeWithConfidence* types, size_t count);
8751+
87308752
BINARYNINJACOREAPI BNSymbolQueue* BNCreateSymbolQueue(void);
87318753
BINARYNINJACOREAPI void BNDestroySymbolQueue(BNSymbolQueue* queue);
87328754
BINARYNINJACOREAPI void BNAppendSymbolQueue(BNSymbolQueue* queue,

formatstringresolutionprovider.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Copyright (c) 2015-2026 Vector 35 Inc
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to
5+
// deal in the Software without restriction, including without limitation the
6+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7+
// sell copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19+
// IN THE SOFTWARE.
20+
21+
#include "binaryninjaapi.h"
22+
23+
using namespace BinaryNinja;
24+
using namespace std;
25+
26+
27+
FormatStringResolutionProvider::FormatStringResolutionProvider(const string& name) : m_nameForRegister(name) {}
28+
29+
30+
FormatStringResolutionProvider::FormatStringResolutionProvider(BNFormatStringResolutionProvider* provider)
31+
{
32+
m_object = provider;
33+
}
34+
35+
36+
bool FormatStringResolutionProvider::IsValidCallback(
37+
void* ctxt, const char* format, BNTypeWithConfidence** types, size_t* count)
38+
{
39+
FormatStringResolutionProvider* provider = (FormatStringResolutionProvider*)ctxt;
40+
auto result = provider->IsValid(format);
41+
if (!result.has_value())
42+
{
43+
*types = nullptr;
44+
*count = 0;
45+
return false;
46+
}
47+
48+
*count = result->size();
49+
if (result->empty())
50+
{
51+
*types = nullptr;
52+
return true;
53+
}
54+
55+
*types = new BNTypeWithConfidence[result->size()];
56+
for (size_t i = 0; i < result->size(); i++)
57+
{
58+
(*types)[i].type = BNNewTypeReference((*result)[i].GetValue()->GetObject());
59+
(*types)[i].confidence = (*result)[i].GetConfidence();
60+
}
61+
return true;
62+
}
63+
64+
65+
void FormatStringResolutionProvider::FreeTypeListCallback(
66+
void*, BNTypeWithConfidence* types, size_t count)
67+
{
68+
for (size_t i = 0; i < count; i++)
69+
BNFreeType(types[i].type);
70+
delete[] types;
71+
}
72+
73+
74+
string FormatStringResolutionProvider::GetName() const
75+
{
76+
char* name = BNGetFormatStringResolutionProviderName(m_object);
77+
string result = name;
78+
BNFreeString(name);
79+
return result;
80+
}
81+
82+
83+
vector<Ref<FormatStringResolutionProvider>> FormatStringResolutionProvider::GetList()
84+
{
85+
size_t count;
86+
BNFormatStringResolutionProvider** list = BNGetFormatStringResolutionProviderList(&count);
87+
vector<Ref<FormatStringResolutionProvider>> result;
88+
result.reserve(count);
89+
for (size_t i = 0; i < count; i++)
90+
result.push_back(new CoreFormatStringResolutionProvider(list[i]));
91+
BNFreeFormatStringResolutionProviderList(list);
92+
return result;
93+
}
94+
95+
96+
Ref<FormatStringResolutionProvider> FormatStringResolutionProvider::GetByName(const string& name)
97+
{
98+
BNFormatStringResolutionProvider* result = BNGetFormatStringResolutionProviderByName(name.c_str());
99+
if (!result)
100+
return nullptr;
101+
return new CoreFormatStringResolutionProvider(result);
102+
}
103+
104+
105+
void FormatStringResolutionProvider::Register(FormatStringResolutionProvider* provider)
106+
{
107+
BNFormatStringResolutionProviderCallbacks callbacks;
108+
callbacks.context = provider;
109+
callbacks.isValid = IsValidCallback;
110+
callbacks.freeTypeList = FreeTypeListCallback;
111+
provider->AddRefForRegistration();
112+
provider->m_object = BNRegisterFormatStringResolutionProvider(provider->m_nameForRegister.c_str(), &callbacks);
113+
}
114+
115+
116+
CoreFormatStringResolutionProvider::CoreFormatStringResolutionProvider(BNFormatStringResolutionProvider* provider) :
117+
FormatStringResolutionProvider(provider)
118+
{}
119+
120+
121+
optional<vector<Confidence<Ref<Type>>>> CoreFormatStringResolutionProvider::IsValid(const string& format)
122+
{
123+
BNTypeWithConfidence* types = nullptr;
124+
size_t count = 0;
125+
if (!BNFormatStringResolutionProviderIsValid(m_object, format.c_str(), &types, &count))
126+
return nullopt;
127+
128+
vector<Confidence<Ref<Type>>> result;
129+
result.reserve(count);
130+
for (size_t i = 0; i < count; i++)
131+
{
132+
result.emplace_back(
133+
new Type(BNNewTypeReference(types[i].type)), types[i].confidence);
134+
}
135+
BNFreeTypeWithConfidenceList(types, count);
136+
return result;
137+
}

0 commit comments

Comments
 (0)