Skip to content

Commit ac98a87

Browse files
committed
Register list & register class API bindings in C++ and Python.
1 parent 88615aa commit ac98a87

File tree

4 files changed

+541
-5
lines changed

4 files changed

+541
-5
lines changed

binaryninjaapi.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16733,6 +16733,14 @@ namespace BinaryNinja {
1673316733
static void GetParameterVariableForIncomingVariableCallback(
1673416734
void* ctxt, const BNVariable* var, BNFunction* func, BNVariable* result);
1673516735

16736+
static uint32_t* GetRegisterArgumentClassesCallback(void* ctxt, size_t* count);
16737+
static uint32_t* GetRegisterArgumentClassListsCallback(void* ctxt, uint32_t classId, size_t* count);
16738+
static uint32_t* GetRegisterArgumentListsCallback(void* ctxt, size_t* count);
16739+
static uint32_t* GetRegisterArgumentListRegsCallback(void* ctxt, uint32_t regListId, size_t* count);
16740+
static BNRegisterListKind GetRegisterArgumentListKindCallback(void* ctxt, uint32_t regListId);
16741+
static BNVariable* GetVariablesForParametersCallback(void* ctxt, const BNFunctionParameter* paramTypes, size_t paramCount, const uint32_t* permittedRegs, size_t permittedRegCount, size_t* resultCount);
16742+
static void FreeVariableListCallback(void* ctxt, BNVariable* vars, size_t count);
16743+
1673616744
public:
1673716745
Ref<Architecture> GetArchitecture() const;
1673816746
std::string GetName() const;
@@ -16748,6 +16756,14 @@ namespace BinaryNinja {
1674816756
virtual bool IsStackAdjustedOnReturn();
1674916757
virtual bool IsEligibleForHeuristics();
1675016758

16759+
virtual std::vector<uint32_t> GetRegisterArgumentClasses();
16760+
virtual std::vector<uint32_t> GetRegisterArgumentClassLists(uint32_t classId);
16761+
virtual std::vector<uint32_t> GetRegisterArgumentLists();
16762+
virtual std::vector<uint32_t> GetRegisterArgumentListRegs(uint32_t regListId);
16763+
virtual BNRegisterListKind GetRegisterArgumentListKind(uint32_t regListId);
16764+
virtual std::vector<Variable> GetVariablesForParameters(const std::vector<FunctionParameter>& paramTypes,
16765+
const std::set<uint32_t>* permittedRegs = nullptr);
16766+
1675116767
virtual uint32_t GetIntegerReturnValueRegister() = 0;
1675216768
virtual uint32_t GetHighIntegerReturnValueRegister();
1675316769
virtual uint32_t GetFloatReturnValueRegister();
@@ -16791,6 +16807,14 @@ namespace BinaryNinja {
1679116807

1679216808
virtual Variable GetIncomingVariableForParameterVariable(const Variable& var, Function* func) override;
1679316809
virtual Variable GetParameterVariableForIncomingVariable(const Variable& var, Function* func) override;
16810+
16811+
virtual std::vector<uint32_t> GetRegisterArgumentClasses() override;
16812+
virtual std::vector<uint32_t> GetRegisterArgumentClassLists(uint32_t classId) override;
16813+
virtual std::vector<uint32_t> GetRegisterArgumentLists() override;
16814+
virtual std::vector<uint32_t> GetRegisterArgumentListRegs(uint32_t regListId) override;
16815+
virtual BNRegisterListKind GetRegisterArgumentListKind(uint32_t regListId) override;
16816+
virtual std::vector<Variable> GetVariablesForParameters(const std::vector<FunctionParameter>& paramTypes,
16817+
const std::set<uint32_t>* permittedRegs = nullptr) override;
1679416818
};
1679516819

1679616820
/*!

callingconvention.cpp

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
5454
cc.getIncomingFlagValue = GetIncomingFlagValueCallback;
5555
cc.getIncomingVariableForParameterVariable = GetIncomingVariableForParameterVariableCallback;
5656
cc.getParameterVariableForIncomingVariable = GetParameterVariableForIncomingVariableCallback;
57+
cc.getRegisterArgumentClasses = GetRegisterArgumentClassesCallback;
58+
cc.getRegisterArgumentClassLists = GetRegisterArgumentClassListsCallback;
59+
cc.getRegisterArgumentLists = GetRegisterArgumentListsCallback;
60+
cc.getRegisterArgumentListRegs = GetRegisterArgumentListRegsCallback;
61+
cc.getRegisterArgumentListKind = GetRegisterArgumentListKindCallback;
62+
cc.getVariablesForParameters = GetVariablesForParametersCallback;
63+
cc.freeVariableList = FreeVariableListCallback;
5764

5865
AddRefForRegistration();
5966
m_object = BNCreateCallingConvention(arch->GetObject(), name.c_str(), &cc);
@@ -125,6 +132,12 @@ void CallingConvention::FreeRegisterListCallback(void*, uint32_t* regs, size_t)
125132
}
126133

127134

135+
void CallingConvention::FreeVariableListCallback(void*, BNVariable* vars, size_t)
136+
{
137+
delete[] vars;
138+
}
139+
140+
128141
bool CallingConvention::AreArgumentRegistersSharedIndexCallback(void* ctxt)
129142
{
130143
CallbackRef<CallingConvention> cc(ctxt);
@@ -283,6 +296,65 @@ vector<uint32_t> CallingConvention::GetFloatArgumentRegisters()
283296
return vector<uint32_t>();
284297
}
285298

299+
vector<uint32_t> CallingConvention::GetRegisterArgumentClasses()
300+
{
301+
size_t count;
302+
uint32_t* classes = BNGetRegisterArgumentClasses(GetObject(), &count);
303+
vector<uint32_t> result;
304+
for (size_t i = 0; i < count; i++)
305+
result.push_back(classes[i]);
306+
BNFreeRegisterList(classes);
307+
return result;
308+
}
309+
310+
311+
vector<uint32_t> CallingConvention::GetRegisterArgumentClassLists(uint32_t classId)
312+
{
313+
size_t count;
314+
uint32_t* lists = BNGetRegisterArgumentClassLists(GetObject(), classId, &count);
315+
vector<uint32_t> result;
316+
for (size_t i = 0; i < count; i++)
317+
result.push_back(lists[i]);
318+
BNFreeRegisterList(lists);
319+
return result;
320+
}
321+
322+
323+
vector<uint32_t> CallingConvention::GetRegisterArgumentLists()
324+
{
325+
size_t count;
326+
uint32_t* lists = BNGetRegisterArgumentLists(GetObject(), &count);
327+
vector<uint32_t> result;
328+
for (size_t i = 0; i < count; i++)
329+
result.push_back(lists[i]);
330+
BNFreeRegisterList(lists);
331+
return result;
332+
}
333+
334+
335+
vector<uint32_t> CallingConvention::GetRegisterArgumentListRegs(uint32_t regListId)
336+
{
337+
size_t count;
338+
uint32_t* regs = BNGetRegisterArgumentListRegs(GetObject(), regListId, &count);
339+
vector<uint32_t> result;
340+
for (size_t i = 0; i < count; i++)
341+
result.push_back(regs[i]);
342+
BNFreeRegisterList(regs);
343+
return result;
344+
}
345+
346+
347+
BNRegisterListKind CallingConvention::GetRegisterArgumentListKind(uint32_t regListId)
348+
{
349+
return BNGetRegisterArgumentListKind(GetObject(), regListId);
350+
}
351+
352+
353+
vector<Variable> CallingConvention::GetVariablesForParameters(const vector<FunctionParameter>& paramTypes,
354+
const std::set<uint32_t>* permittedRegs)
355+
{
356+
return vector<Variable>();
357+
}
286358

287359
bool CallingConvention::AreArgumentRegistersSharedIndex()
288360
{
@@ -504,3 +576,202 @@ Variable CoreCallingConvention::GetParameterVariableForIncomingVariable(const Va
504576
{
505577
return BNGetParameterVariableForIncomingVariable(m_object, &var, func ? func->GetObject() : nullptr);
506578
}
579+
580+
581+
vector<uint32_t> CoreCallingConvention::GetRegisterArgumentClasses()
582+
{
583+
size_t count;
584+
uint32_t* classes = BNGetRegisterArgumentClasses(m_object, &count);
585+
vector<uint32_t> result;
586+
result.insert(result.end(), classes, &classes[count]);
587+
BNFreeRegisterList(classes);
588+
return result;
589+
}
590+
591+
592+
vector<uint32_t> CoreCallingConvention::GetRegisterArgumentClassLists(uint32_t classId)
593+
{
594+
size_t count;
595+
uint32_t* lists = BNGetRegisterArgumentClassLists(m_object, classId, &count);
596+
vector<uint32_t> result;
597+
result.insert(result.end(), lists, &lists[count]);
598+
BNFreeRegisterList(lists);
599+
return result;
600+
}
601+
602+
603+
vector<uint32_t> CoreCallingConvention::GetRegisterArgumentLists()
604+
{
605+
size_t count;
606+
uint32_t* lists = BNGetRegisterArgumentLists(m_object, &count);
607+
vector<uint32_t> result;
608+
result.insert(result.end(), lists, &lists[count]);
609+
BNFreeRegisterList(lists);
610+
return result;
611+
}
612+
613+
614+
vector<uint32_t> CoreCallingConvention::GetRegisterArgumentListRegs(uint32_t regListId)
615+
{
616+
size_t count;
617+
uint32_t* regs = BNGetRegisterArgumentListRegs(m_object, regListId, &count);
618+
vector<uint32_t> result;
619+
result.insert(result.end(), regs, &regs[count]);
620+
BNFreeRegisterList(regs);
621+
return result;
622+
}
623+
624+
625+
BNRegisterListKind CoreCallingConvention::GetRegisterArgumentListKind(uint32_t regListId)
626+
{
627+
return BNGetRegisterArgumentListKind(m_object, regListId);
628+
}
629+
630+
631+
vector<Variable> CoreCallingConvention::GetVariablesForParameters(const vector<FunctionParameter>& paramTypes,
632+
const std::set<uint32_t>* permittedRegs)
633+
{
634+
BNFunctionParameter* params = new BNFunctionParameter[paramTypes.size()];
635+
for (size_t i = 0; i < paramTypes.size(); i++)
636+
{
637+
params[i].name = (char*)paramTypes[i].name.c_str();
638+
params[i].type = paramTypes[i].type->GetObject();
639+
params[i].typeConfidence = paramTypes[i].type.GetConfidence();
640+
params[i].defaultLocation = paramTypes[i].defaultLocation;
641+
params[i].location.type = paramTypes[i].location.type;
642+
params[i].location.index = paramTypes[i].location.index;
643+
params[i].location.storage = paramTypes[i].location.storage;
644+
}
645+
646+
uint32_t* permittedRegsArray = nullptr;
647+
size_t permittedRegsCount = 0;
648+
if (permittedRegs != nullptr)
649+
{
650+
permittedRegsCount = permittedRegs->size();
651+
permittedRegsArray = new uint32_t[permittedRegsCount];
652+
size_t j = 0;
653+
for (auto reg : *permittedRegs)
654+
permittedRegsArray[j++] = reg;
655+
}
656+
657+
size_t count;
658+
BNVariable* vars = BNGetVariablesForParameters(m_object, params, paramTypes.size(),
659+
permittedRegsArray, permittedRegsCount, &count);
660+
661+
vector<Variable> result;
662+
for (size_t i = 0; i < count; i++)
663+
result.push_back(vars[i]);
664+
665+
delete[] params;
666+
if (permittedRegsArray)
667+
delete[] permittedRegsArray;
668+
BNFreeVariableList(vars);
669+
return result;
670+
}
671+
672+
673+
uint32_t* CallingConvention::GetRegisterArgumentClassesCallback(void* ctxt, size_t* count)
674+
{
675+
CallbackRef<CallingConvention> cc(ctxt);
676+
vector<uint32_t> classes = cc->GetRegisterArgumentClasses();
677+
*count = classes.size();
678+
679+
uint32_t* result = new uint32_t[classes.size()];
680+
for (size_t i = 0; i < classes.size(); i++)
681+
result[i] = classes[i];
682+
return result;
683+
}
684+
685+
686+
uint32_t* CallingConvention::GetRegisterArgumentClassListsCallback(void* ctxt, uint32_t classId, size_t* count)
687+
{
688+
CallbackRef<CallingConvention> cc(ctxt);
689+
vector<uint32_t> lists = cc->GetRegisterArgumentClassLists(classId);
690+
*count = lists.size();
691+
692+
uint32_t* result = new uint32_t[lists.size()];
693+
for (size_t i = 0; i < lists.size(); i++)
694+
result[i] = lists[i];
695+
return result;
696+
}
697+
698+
699+
uint32_t* CallingConvention::GetRegisterArgumentListsCallback(void* ctxt, size_t* count)
700+
{
701+
CallbackRef<CallingConvention> cc(ctxt);
702+
vector<uint32_t> lists = cc->GetRegisterArgumentLists();
703+
*count = lists.size();
704+
705+
uint32_t* result = new uint32_t[lists.size()];
706+
for (size_t i = 0; i < lists.size(); i++)
707+
result[i] = lists[i];
708+
return result;
709+
}
710+
711+
712+
uint32_t* CallingConvention::GetRegisterArgumentListRegsCallback(void* ctxt, uint32_t regListId, size_t* count)
713+
{
714+
CallbackRef<CallingConvention> cc(ctxt);
715+
vector<uint32_t> regs = cc->GetRegisterArgumentListRegs(regListId);
716+
*count = regs.size();
717+
718+
uint32_t* result = new uint32_t[regs.size()];
719+
for (size_t i = 0; i < regs.size(); i++)
720+
result[i] = regs[i];
721+
return result;
722+
}
723+
724+
725+
BNRegisterListKind CallingConvention::GetRegisterArgumentListKindCallback(void* ctxt, uint32_t regListId)
726+
{
727+
CallbackRef<CallingConvention> cc(ctxt);
728+
return cc->GetRegisterArgumentListKind(regListId);
729+
}
730+
731+
732+
BNVariable* CallingConvention::GetVariablesForParametersCallback(void* ctxt, const BNFunctionParameter* paramTypes, size_t paramCount, const uint32_t* permittedRegs, size_t permittedRegCount, size_t* resultCount)
733+
{
734+
CallbackRef<CallingConvention> cc(ctxt);
735+
736+
vector<FunctionParameter> params;
737+
for (size_t i = 0; i < paramCount; i++)
738+
{
739+
FunctionParameter param;
740+
param.name = paramTypes[i].name;
741+
param.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(paramTypes[i].type)), paramTypes[i].typeConfidence);
742+
param.defaultLocation = paramTypes[i].defaultLocation;
743+
param.location = paramTypes[i].location;
744+
params.push_back(param);
745+
}
746+
747+
std::set<uint32_t>* permittedRegsSet = nullptr;
748+
if (permittedRegs && permittedRegCount > 0)
749+
{
750+
permittedRegsSet = new std::set<uint32_t>();
751+
for (size_t i = 0; i < permittedRegCount; i++)
752+
permittedRegsSet->insert(permittedRegs[i]);
753+
}
754+
755+
vector<Variable> variables = cc->GetVariablesForParameters(params, permittedRegsSet);
756+
757+
// If the calling convention doesn't implement this method, it returns an empty vector
758+
// Signal fallback to core implementation by returning NULL with count 0
759+
if (variables.empty())
760+
{
761+
*resultCount = 0;
762+
if (permittedRegsSet)
763+
delete permittedRegsSet;
764+
return nullptr;
765+
}
766+
767+
*resultCount = variables.size();
768+
769+
BNVariable* result = new BNVariable[variables.size()];
770+
for (size_t i = 0; i < variables.size(); i++)
771+
result[i] = variables[i];
772+
773+
if (permittedRegsSet)
774+
delete permittedRegsSet;
775+
776+
return result;
777+
}

0 commit comments

Comments
 (0)