Skip to content

Commit b16d5bc

Browse files
committed
Add support for multiple global pointer registers
1 parent ac359f8 commit b16d5bc

12 files changed

Lines changed: 348 additions & 11 deletions

binaryninjaapi.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8248,9 +8248,13 @@ namespace BinaryNinja {
82488248
std::vector<Ref<ExternalLocation>> GetExternalLocations();
82498249

82508250
Confidence<RegisterValue> GetGlobalPointerValue() const;
8251+
std::vector<std::pair<uint32_t, Confidence<RegisterValue>>> GetGlobalPointerValues() const;
8252+
std::vector<std::pair<uint32_t, Confidence<RegisterValue>>> GetDefaultGlobalPointerValues() const;
8253+
std::vector<std::pair<uint32_t, Confidence<RegisterValue>>> GetUserGlobalPointerValues() const;
82518254
bool UserGlobalPointerValueSet() const;
82528255
void ClearUserGlobalPointerValue();
82538256
void SetUserGlobalPointerValue(const Confidence<RegisterValue>& value);
8257+
void SetUserGlobalPointerValues(const std::vector<std::pair<uint32_t, Confidence<RegisterValue>>>& values);
82548258

82558259
std::optional<std::pair<std::string, BNStringType>> StringifyUnicodeData(Architecture* arch, const DataBuffer& buffer, bool nullTerminates = true, bool allowShortStrings = false);
82568260
};
@@ -13531,6 +13535,7 @@ namespace BinaryNinja {
1353113535
std::vector<DisassemblyTextLine> GetTypeTokens(DisassemblySettings* settings = nullptr);
1353213536

1353313537
Confidence<RegisterValue> GetGlobalPointerValue() const;
13538+
std::vector<std::pair<uint32_t, Confidence<RegisterValue>>> GetGlobalPointerValues() const;
1353413539
bool UsesIncomingGlobalPointer() const;
1353513540
Confidence<RegisterValue> GetRegisterValueAtExit(uint32_t reg) const;
1353613541

@@ -17822,6 +17827,7 @@ namespace BinaryNinja {
1782217827
static uint32_t GetHighIntegerReturnValueRegisterCallback(void* ctxt);
1782317828
static uint32_t GetFloatReturnValueRegisterCallback(void* ctxt);
1782417829
static uint32_t GetGlobalPointerRegisterCallback(void* ctxt);
17830+
static uint32_t* GetGlobalPointerRegistersCallback(void* ctxt, size_t* count);
1782517831

1782617832
static uint32_t* GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count);
1782717833
static void GetIncomingRegisterValueCallback(
@@ -17867,6 +17873,7 @@ namespace BinaryNinja {
1786717873
virtual uint32_t GetHighIntegerReturnValueRegister();
1786817874
virtual uint32_t GetFloatReturnValueRegister();
1786917875
virtual uint32_t GetGlobalPointerRegister();
17876+
virtual std::vector<uint32_t> GetGlobalPointerRegisters();
1787017877

1787117878
virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters();
1787217879
virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func);
@@ -17901,6 +17908,7 @@ namespace BinaryNinja {
1790117908
virtual uint32_t GetHighIntegerReturnValueRegister() override;
1790217909
virtual uint32_t GetFloatReturnValueRegister() override;
1790317910
virtual uint32_t GetGlobalPointerRegister() override;
17911+
virtual std::vector<uint32_t> GetGlobalPointerRegisters() override;
1790417912

1790517913
virtual std::vector<uint32_t> GetImplicitlyDefinedRegisters() override;
1790617914
virtual RegisterValue GetIncomingRegisterValue(uint32_t reg, Function* func) override;

binaryninjacore.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,12 @@ extern "C"
13141314
uint8_t confidence;
13151315
} BNRegisterValueWithConfidence;
13161316

1317+
typedef struct BNRegisterValueWithConfidenceAndRegister
1318+
{
1319+
uint32_t reg;
1320+
BNRegisterValueWithConfidence value;
1321+
} BNRegisterValueWithConfidenceAndRegister;
1322+
13171323
typedef struct BNValueRange
13181324
{
13191325
uint64_t start, end, step;
@@ -2875,6 +2881,7 @@ extern "C"
28752881
uint32_t (*getHighIntegerReturnValueRegister)(void* ctxt);
28762882
uint32_t (*getFloatReturnValueRegister)(void* ctxt);
28772883
uint32_t (*getGlobalPointerRegister)(void* ctxt);
2884+
uint32_t* (*getGlobalPointerRegisters)(void* ctxt, size_t* count);
28782885

28792886
uint32_t* (*getImplicitlyDefinedRegisters)(void* ctxt, size_t* count);
28802887
void (*getIncomingRegisterValue)(void* ctxt, uint32_t reg, BNFunction* func, BNRegisterValue* result);
@@ -4778,9 +4785,14 @@ extern "C"
47784785
BINARYNINJACOREAPI void BNFreeNameSpace(BNNameSpace* name);
47794786

47804787
BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetGlobalPointerValue(BNBinaryView* view);
4788+
BINARYNINJACOREAPI BNRegisterValueWithConfidenceAndRegister* BNGetGlobalPointerValues(BNBinaryView* view, size_t* count);
4789+
BINARYNINJACOREAPI BNRegisterValueWithConfidenceAndRegister* BNGetDefaultGlobalPointerValues(BNBinaryView* view, size_t* count);
4790+
BINARYNINJACOREAPI BNRegisterValueWithConfidenceAndRegister* BNGetUserGlobalPointerValues(BNBinaryView* view, size_t* count);
4791+
BINARYNINJACOREAPI void BNFreeRegisterValueWithConfidenceAndRegisterList(BNRegisterValueWithConfidenceAndRegister* values);
47814792
BINARYNINJACOREAPI bool BNUserGlobalPointerValueSet(BNBinaryView* view);
47824793
BINARYNINJACOREAPI void BNClearUserGlobalPointerValue(BNBinaryView* view);
47834794
BINARYNINJACOREAPI void BNSetUserGlobalPointerValue(BNBinaryView* view, BNRegisterValueWithConfidence value);
4795+
BINARYNINJACOREAPI void BNSetUserGlobalPointerValues(BNBinaryView* view, const BNRegisterValueWithConfidenceAndRegister* values, size_t count);
47844796

47854797
BINARYNINJACOREAPI bool BNStringifyUnicodeData(BNBinaryView* data, BNArchitecture* arch, const BNDataBuffer* buffer, bool nullTerminates, bool allowShortStrings, char** string, BNStringType* type);
47864798

@@ -5320,6 +5332,7 @@ extern "C"
53205332
BNFunction* func, BNDisassemblySettings* settings, size_t* count);
53215333

53225334
BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionGlobalPointerValue(BNFunction* func);
5335+
BINARYNINJACOREAPI BNRegisterValueWithConfidenceAndRegister* BNGetFunctionGlobalPointerValues(BNFunction* func, size_t* count);
53235336
BINARYNINJACOREAPI bool BNFunctionUsesIncomingGlobalPointer(BNFunction* func);
53245337
BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionRegisterValueAtExit(BNFunction* func, uint32_t reg);
53255338

@@ -7623,6 +7636,7 @@ extern "C"
76237636
BINARYNINJACOREAPI uint32_t BNGetHighIntegerReturnValueRegister(BNCallingConvention* cc);
76247637
BINARYNINJACOREAPI uint32_t BNGetFloatReturnValueRegister(BNCallingConvention* cc);
76257638
BINARYNINJACOREAPI uint32_t BNGetGlobalPointerRegister(BNCallingConvention* cc);
7639+
BINARYNINJACOREAPI uint32_t* BNGetGlobalPointerRegisters(BNCallingConvention* cc, size_t* count);
76267640

76277641
BINARYNINJACOREAPI uint32_t* BNGetImplicitlyDefinedRegisters(BNCallingConvention* cc, size_t* count);
76287642
BINARYNINJACOREAPI BNRegisterValue BNGetIncomingRegisterValue(

binaryview.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5800,6 +5800,43 @@ Confidence<RegisterValue> BinaryView::GetGlobalPointerValue() const
58005800
}
58015801

58025802

5803+
static vector<pair<uint32_t, Confidence<RegisterValue>>> ConvertGlobalPointerValues(
5804+
BNRegisterValueWithConfidenceAndRegister* values, size_t count)
5805+
{
5806+
vector<pair<uint32_t, Confidence<RegisterValue>>> result;
5807+
result.reserve(count);
5808+
for (size_t i = 0; i < count; i++)
5809+
result.emplace_back(values[i].reg,
5810+
Confidence<RegisterValue>(RegisterValue::FromAPIObject(values[i].value.value), values[i].value.confidence));
5811+
BNFreeRegisterValueWithConfidenceAndRegisterList(values);
5812+
return result;
5813+
}
5814+
5815+
5816+
vector<pair<uint32_t, Confidence<RegisterValue>>> BinaryView::GetGlobalPointerValues() const
5817+
{
5818+
size_t count;
5819+
BNRegisterValueWithConfidenceAndRegister* values = BNGetGlobalPointerValues(m_object, &count);
5820+
return ConvertGlobalPointerValues(values, count);
5821+
}
5822+
5823+
5824+
vector<pair<uint32_t, Confidence<RegisterValue>>> BinaryView::GetDefaultGlobalPointerValues() const
5825+
{
5826+
size_t count;
5827+
BNRegisterValueWithConfidenceAndRegister* values = BNGetDefaultGlobalPointerValues(m_object, &count);
5828+
return ConvertGlobalPointerValues(values, count);
5829+
}
5830+
5831+
5832+
vector<pair<uint32_t, Confidence<RegisterValue>>> BinaryView::GetUserGlobalPointerValues() const
5833+
{
5834+
size_t count;
5835+
BNRegisterValueWithConfidenceAndRegister* values = BNGetUserGlobalPointerValues(m_object, &count);
5836+
return ConvertGlobalPointerValues(values, count);
5837+
}
5838+
5839+
58035840
bool BinaryView::UserGlobalPointerValueSet() const
58045841
{
58055842
return BNUserGlobalPointerValueSet(m_object);
@@ -5824,6 +5861,25 @@ void BinaryView::SetUserGlobalPointerValue(const Confidence<RegisterValue>& valu
58245861
}
58255862

58265863

5864+
void BinaryView::SetUserGlobalPointerValues(const vector<pair<uint32_t, Confidence<RegisterValue>>>& values)
5865+
{
5866+
vector<BNRegisterValueWithConfidenceAndRegister> apiValues;
5867+
apiValues.reserve(values.size());
5868+
for (auto& [reg, value] : values)
5869+
{
5870+
BNRegisterValueWithConfidenceAndRegister v;
5871+
v.reg = reg;
5872+
v.value.confidence = value.GetConfidence();
5873+
v.value.value.value = value.GetValue().value;
5874+
v.value.value.state = value.GetValue().state;
5875+
v.value.value.size = value.GetValue().size;
5876+
v.value.value.offset = value.GetValue().offset;
5877+
apiValues.push_back(v);
5878+
}
5879+
BNSetUserGlobalPointerValues(m_object, apiValues.data(), apiValues.size());
5880+
}
5881+
5882+
58275883
optional<pair<string, BNStringType>> BinaryView::StringifyUnicodeData(Architecture* arch, const DataBuffer& buffer, bool nullTerminates, bool allowShortStrings)
58285884
{
58295885
char* str = nullptr;

callingconvention.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
5151
cc.getHighIntegerReturnValueRegister = GetHighIntegerReturnValueRegisterCallback;
5252
cc.getFloatReturnValueRegister = GetFloatReturnValueRegisterCallback;
5353
cc.getGlobalPointerRegister = GetGlobalPointerRegisterCallback;
54+
cc.getGlobalPointerRegisters = GetGlobalPointerRegistersCallback;
5455
cc.getImplicitlyDefinedRegisters = GetImplicitlyDefinedRegistersCallback;
5556
cc.getIncomingRegisterValue = GetIncomingRegisterValueCallback;
5657
cc.getIncomingFlagValue = GetIncomingFlagValueCallback;
@@ -216,6 +217,19 @@ uint32_t CallingConvention::GetGlobalPointerRegisterCallback(void* ctxt)
216217
}
217218

218219

220+
uint32_t* CallingConvention::GetGlobalPointerRegistersCallback(void* ctxt, size_t* count)
221+
{
222+
CallbackRef<CallingConvention> cc(ctxt);
223+
vector<uint32_t> regs = cc->GetGlobalPointerRegisters();
224+
*count = regs.size();
225+
226+
uint32_t* result = new uint32_t[regs.size()];
227+
for (size_t i = 0; i < regs.size(); i++)
228+
result[i] = regs[i];
229+
return result;
230+
}
231+
232+
219233
uint32_t* CallingConvention::GetImplicitlyDefinedRegistersCallback(void* ctxt, size_t* count)
220234
{
221235
CallbackRef<CallingConvention> cc(ctxt);
@@ -372,6 +386,15 @@ uint32_t CallingConvention::GetGlobalPointerRegister()
372386
}
373387

374388

389+
vector<uint32_t> CallingConvention::GetGlobalPointerRegisters()
390+
{
391+
uint32_t reg = GetGlobalPointerRegister();
392+
if (reg == BN_INVALID_REGISTER)
393+
return vector<uint32_t>();
394+
return vector<uint32_t> { reg };
395+
}
396+
397+
375398
vector<uint32_t> CallingConvention::GetImplicitlyDefinedRegisters()
376399
{
377400
return vector<uint32_t>();
@@ -533,6 +556,17 @@ uint32_t CoreCallingConvention::GetGlobalPointerRegister()
533556
}
534557

535558

559+
vector<uint32_t> CoreCallingConvention::GetGlobalPointerRegisters()
560+
{
561+
size_t count;
562+
uint32_t* regs = BNGetGlobalPointerRegisters(m_object, &count);
563+
vector<uint32_t> result;
564+
result.insert(result.end(), regs, &regs[count]);
565+
BNFreeRegisterList(regs);
566+
return result;
567+
}
568+
569+
536570
vector<uint32_t> CoreCallingConvention::GetImplicitlyDefinedRegisters()
537571
{
538572
size_t count;

examples/triage/analysisinfo.cpp

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ AnalysisInfoWidget::~AnalysisInfoWidget()
4444

4545
void AnalysisInfoWidget::timerExpired()
4646
{
47-
auto gpValue = m_data->GetGlobalPointerValue();
48-
if (gpValue == m_lastGPValue)
47+
auto gpValues = m_data->GetGlobalPointerValues();
48+
if (gpValues == m_lastGPValues)
4949
return;
5050

51-
m_lastGPValue = gpValue;
51+
m_lastGPValues = gpValues;
5252
updateDisplay();
5353
}
5454

@@ -61,14 +61,36 @@ void AnalysisInfoWidget::updateDisplay()
6161
auto callingConvention = defaultPlatform->GetDefaultCallingConvention();
6262
if (callingConvention)
6363
{
64-
auto gpRegister = callingConvention->GetGlobalPointerRegister();
65-
if (gpRegister != BN_INVALID_REGISTER)
64+
auto gpValues = m_data->GetGlobalPointerValues();
65+
if (!gpValues.empty())
6666
{
67-
auto gpValue = m_data->GetGlobalPointerValue();
68-
std::string gpString = getStringForRegisterValue(m_data->GetDefaultArchitecture(), gpValue);
69-
std::string gpExtraString = std::string(" @ ") + m_data->GetDefaultArchitecture()->GetRegisterName(gpRegister);
67+
std::vector<std::string> gpStrings;
68+
auto arch = m_data->GetDefaultArchitecture();
69+
for (auto& [reg, value] : gpValues)
70+
{
71+
if (reg == BN_INVALID_REGISTER)
72+
continue;
73+
gpStrings.push_back(arch->GetRegisterName(reg) + "=" + getStringForRegisterValue(arch, value));
74+
}
75+
76+
if (gpStrings.empty())
77+
{
78+
m_gpLabel->setText("N/A");
79+
m_gpExtraLabel->setText("");
80+
return;
81+
}
82+
83+
std::string gpString;
84+
for (size_t i = 0; i < gpStrings.size(); i++)
85+
{
86+
if (i != 0)
87+
gpString += ", ";
88+
gpString += gpStrings[i];
89+
}
90+
91+
std::string gpExtraString;
7092
if (m_data->UserGlobalPointerValueSet())
71-
gpExtraString += " (*)";
93+
gpExtraString = " (*)";
7294

7395
m_gpLabel->setText(QString::fromStdString(gpString));
7496
m_gpExtraLabel->setText(QString::fromStdString(gpExtraString));
@@ -78,4 +100,5 @@ void AnalysisInfoWidget::updateDisplay()
78100
}
79101

80102
m_gpLabel->setText("N/A");
103+
m_gpExtraLabel->setText("");
81104
}

examples/triage/analysisinfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class AnalysisInfoWidget : public QWidget
1616
NavigationAddressLabel* m_gpLabel;
1717
QLabel* m_gpExtraLabel;
1818

19-
BinaryNinja::Confidence<BinaryNinja::RegisterValue> m_lastGPValue;
19+
std::vector<std::pair<uint32_t, BinaryNinja::Confidence<BinaryNinja::RegisterValue>>> m_lastGPValues;
2020

2121
void updateDisplay();
2222

function.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,20 @@ Confidence<RegisterValue> Function::GetGlobalPointerValue() const
23522352
}
23532353

23542354

2355+
vector<pair<uint32_t, Confidence<RegisterValue>>> Function::GetGlobalPointerValues() const
2356+
{
2357+
size_t count;
2358+
BNRegisterValueWithConfidenceAndRegister* values = BNGetFunctionGlobalPointerValues(m_object, &count);
2359+
vector<pair<uint32_t, Confidence<RegisterValue>>> result;
2360+
result.reserve(count);
2361+
for (size_t i = 0; i < count; i++)
2362+
result.emplace_back(values[i].reg,
2363+
Confidence<RegisterValue>(RegisterValue::FromAPIObject(values[i].value.value), values[i].value.confidence));
2364+
BNFreeRegisterValueWithConfidenceAndRegisterList(values);
2365+
return result;
2366+
}
2367+
2368+
23552369
bool Function::UsesIncomingGlobalPointer() const
23562370
{
23572371
return BNFunctionUsesIncomingGlobalPointer(m_object);

python/binaryview.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4200,6 +4200,34 @@ def global_pointer_value(self) -> 'variable.RegisterValue':
42004200
result = core.BNGetGlobalPointerValue(self.handle)
42014201
return variable.RegisterValue.from_BNRegisterValue(result, self.arch)
42024202

4203+
@property
4204+
def global_pointer_values(self) -> List[Tuple['architecture.RegisterName', 'variable.RegisterValue']]:
4205+
"""Discovered values of the global pointer registers, if the binary uses any (read-only)"""
4206+
return self._get_global_pointer_values(core.BNGetGlobalPointerValues)
4207+
4208+
@property
4209+
def default_global_pointer_values(self) -> List[Tuple['architecture.RegisterName', 'variable.RegisterValue']]:
4210+
"""Auto-discovered values of the global pointer registers before user overrides are applied (read-only)"""
4211+
return self._get_global_pointer_values(core.BNGetDefaultGlobalPointerValues)
4212+
4213+
@property
4214+
def user_global_pointer_values(self) -> List[Tuple['architecture.RegisterName', 'variable.RegisterValue']]:
4215+
"""User overrides for global pointer register values (read-only)"""
4216+
return self._get_global_pointer_values(core.BNGetUserGlobalPointerValues)
4217+
4218+
def _get_global_pointer_values(self, getter) -> List[Tuple['architecture.RegisterName', 'variable.RegisterValue']]:
4219+
count = ctypes.c_ulonglong()
4220+
values = getter(self.handle, count)
4221+
if values is None:
4222+
return []
4223+
try:
4224+
return [
4225+
(self.arch.get_reg_name(values[i].reg), variable.RegisterValue.from_BNRegisterValue(values[i].value, self.arch))
4226+
for i in range(count.value)
4227+
]
4228+
finally:
4229+
core.BNFreeRegisterValueWithConfidenceAndRegisterList(values)
4230+
42034231
@property
42044232
def user_global_pointer_value_set(self) -> bool:
42054233
"""Check whether a user global pointer value has been set"""
@@ -4255,6 +4283,23 @@ def set_user_global_pointer_value(self, value: variable.RegisterValue, confidenc
42554283
val.confidence = confidence
42564284
core.BNSetUserGlobalPointerValue(self.handle, val)
42574285

4286+
def set_user_global_pointer_values(self, values):
4287+
"""
4288+
Set user global pointer values for multiple registers.
4289+
4290+
:param list[tuple[str, variable.RegisterValue]] values: register name/value pairs
4291+
:return: None
4292+
:rtype: None
4293+
"""
4294+
api_values = (core.BNRegisterValueWithConfidenceAndRegister * len(values))()
4295+
for i, value in enumerate(values):
4296+
reg, reg_value = value[:2]
4297+
confidence = value[2] if len(value) > 2 else 255
4298+
api_values[i].reg = self.arch.get_reg_index(reg)
4299+
api_values[i].value.value = reg_value._to_core_struct()
4300+
api_values[i].value.confidence = confidence
4301+
core.BNSetUserGlobalPointerValues(self.handle, api_values, len(values))
4302+
42584303
@property
42594304
def parameters_for_analysis(self):
42604305
return core.BNGetParametersForAnalysis(self.handle)

0 commit comments

Comments
 (0)