@@ -24,6 +24,61 @@ using namespace std;
2424using namespace BinaryNinja ;
2525
2626
27+ CallLayout CallLayout::FromAPIObject (BNCallLayout* layout)
28+ {
29+ CallLayout result;
30+ result.parameters .reserve (layout->parameterCount );
31+ for (size_t i = 0 ; i < layout->parameterCount ; i++)
32+ result.parameters .push_back (ValueLocation::FromAPIObject (&layout->parameters [i]));
33+ if (layout->returnValueValid )
34+ result.returnValue = ValueLocation::FromAPIObject (&layout->returnValue );
35+ result.stackAdjustment = layout->stackAdjustment ;
36+ for (size_t i = 0 ; i < layout->registerStackAdjustmentCount ; i++)
37+ {
38+ result.registerStackAdjustments [layout->registerStackAdjustmentRegisters [i]] =
39+ layout->registerStackAdjustmentAmounts [i];
40+ }
41+ return result;
42+ }
43+
44+
45+ BNCallLayout CallLayout::ToAPIObject () const
46+ {
47+ BNCallLayout result;
48+ result.parameters = new BNValueLocation[parameters.size ()];
49+ result.parameterCount = parameters.size ();
50+ for (size_t i = 0 ; i < parameters.size (); i++)
51+ result.parameters [i] = parameters[i].ToAPIObject ();
52+ result.returnValue = returnValue.value_or (ValueLocation ()).ToAPIObject ();
53+ result.returnValueValid = returnValue.has_value ();
54+ result.stackAdjustment = stackAdjustment;
55+
56+ result.registerStackAdjustmentCount = registerStackAdjustments.size ();
57+ result.registerStackAdjustmentRegisters = new uint32_t [registerStackAdjustments.size ()];
58+ result.registerStackAdjustmentAmounts = new int32_t [registerStackAdjustments.size ()];
59+ size_t i = 0 ;
60+ for (auto [reg, adjust] : registerStackAdjustments)
61+ {
62+ result.registerStackAdjustmentRegisters [i] = reg;
63+ result.registerStackAdjustmentAmounts [i] = adjust;
64+ i++;
65+ }
66+
67+ return result;
68+ }
69+
70+
71+ void CallLayout::FreeAPIObject (BNCallLayout* layout)
72+ {
73+ for (size_t i = 0 ; i < layout->parameterCount ; i++)
74+ ValueLocation::FreeAPIObject (&layout->parameters [i]);
75+ delete[] layout->parameters ;
76+ ValueLocation::FreeAPIObject (&layout->returnValue );
77+ delete[] layout->registerStackAdjustmentRegisters ;
78+ delete[] layout->registerStackAdjustmentAmounts ;
79+ }
80+
81+
2782CallingConvention::CallingConvention (BNCallingConvention* cc)
2883{
2984 m_object = cc;
@@ -54,6 +109,12 @@ CallingConvention::CallingConvention(Architecture* arch, const string& name)
54109 cc.getIncomingFlagValue = GetIncomingFlagValueCallback;
55110 cc.getIncomingVariableForParameterVariable = GetIncomingVariableForParameterVariableCallback;
56111 cc.getParameterVariableForIncomingVariable = GetParameterVariableForIncomingVariableCallback;
112+ cc.getCallLayout = GetCallLayoutCallback;
113+ cc.freeCallLayout = FreeCallLayoutCallback;
114+ cc.getReturnValueLocation = GetReturnValueLocationCallback;
115+ cc.freeValueLocation = FreeValueLocationCallback;
116+ cc.getParameterLocations = GetParameterLocationsCallback;
117+ cc.freeParameterLocations = FreeParameterLocationsCallback;
57118
58119 AddRefForRegistration ();
59120 m_object = BNCreateCallingConvention (arch->GetObject (), name.c_str (), &cc);
@@ -245,6 +306,90 @@ void CallingConvention::GetParameterVariableForIncomingVariableCallback(
245306}
246307
247308
309+ BNCallLayout CallingConvention::GetCallLayoutCallback (void * ctxt, BNReturnValue* returnValue,
310+ BNFunctionParameter* params, size_t paramCount, bool hasPermittedRegs, uint32_t * permittedRegs,
311+ size_t permittedRegCount)
312+ {
313+ CallbackRef<CallingConvention> cc (ctxt);
314+ auto ret = ReturnValue::FromAPIObject (returnValue);
315+ vector<FunctionParameter> paramObjs;
316+ paramObjs.reserve (paramCount);
317+ for (size_t i = 0 ; i < paramCount; i++)
318+ paramObjs.push_back (FunctionParameter::FromAPIObject (¶ms[i]));
319+ optional<set<uint32_t >> regOpt;
320+ if (hasPermittedRegs)
321+ {
322+ set<uint32_t > regs;
323+ for (size_t i = 0 ; i < permittedRegCount; i++)
324+ regs.insert (permittedRegs[i]);
325+ regOpt = regs;
326+ }
327+
328+ auto layout = cc->GetCallLayout (ret, paramObjs, regOpt);
329+ return layout.ToAPIObject ();
330+ }
331+
332+
333+ void CallingConvention::FreeCallLayoutCallback (void *, BNCallLayout* layout)
334+ {
335+ CallLayout::FreeAPIObject (layout);
336+ }
337+
338+
339+ BNValueLocation CallingConvention::GetReturnValueLocationCallback (void * ctxt, BNReturnValue* returnValue)
340+ {
341+ CallbackRef<CallingConvention> cc (ctxt);
342+ ReturnValue ret = ReturnValue::FromAPIObject (returnValue);
343+ ValueLocation location = cc->GetReturnValueLocation (ret);
344+ return location.ToAPIObject ();
345+ }
346+
347+
348+ void CallingConvention::FreeValueLocationCallback (void *, BNValueLocation* location)
349+ {
350+ ValueLocation::FreeAPIObject (location);
351+ }
352+
353+
354+ BNValueLocation* CallingConvention::GetParameterLocationsCallback (void * ctxt, BNValueLocation* returnValue,
355+ BNFunctionParameter* params, size_t paramCount, bool hasPermittedRegs, uint32_t * permittedRegs,
356+ size_t permittedRegCount, size_t * outLocationCount)
357+ {
358+ CallbackRef<CallingConvention> cc (ctxt);
359+ std::optional<ValueLocation> ret;
360+ if (returnValue)
361+ ret = ValueLocation::FromAPIObject (returnValue);
362+ vector<FunctionParameter> paramObjs;
363+ paramObjs.reserve (paramCount);
364+ for (size_t i = 0 ; i < paramCount; i++)
365+ paramObjs.push_back (FunctionParameter::FromAPIObject (¶ms[i]));
366+ optional<set<uint32_t >> regOpt;
367+ if (hasPermittedRegs)
368+ {
369+ set<uint32_t > regs;
370+ for (size_t i = 0 ; i < permittedRegCount; i++)
371+ regs.insert (permittedRegs[i]);
372+ regOpt = regs;
373+ }
374+
375+ vector<ValueLocation> locations = cc->GetParameterLocations (ret, paramObjs, regOpt);
376+
377+ *outLocationCount = locations.size ();
378+ BNValueLocation* result = new BNValueLocation[locations.size ()];
379+ for (size_t i = 0 ; i < locations.size (); i++)
380+ result[i] = locations[i].ToAPIObject ();
381+ return result;
382+ }
383+
384+
385+ void CallingConvention::FreeParameterLocationsCallback (void *, BNValueLocation* locations, size_t count)
386+ {
387+ for (size_t i = 0 ; i < count; i++)
388+ ValueLocation::FreeAPIObject (&locations[i]);
389+ delete[] locations;
390+ }
391+
392+
248393Ref<Architecture> CallingConvention::GetArchitecture () const
249394{
250395 return new CoreArchitecture (BNGetCallingConventionArchitecture (m_object));
@@ -370,6 +515,118 @@ Variable CallingConvention::GetParameterVariableForIncomingVariable(const Variab
370515}
371516
372517
518+ CallLayout CallingConvention::GetCallLayout (const ReturnValue& returnValue, const vector<FunctionParameter>& params,
519+ const optional<set<uint32_t >>& permittedRegs)
520+ {
521+ return GetDefaultCallLayout (returnValue, params, permittedRegs);
522+ }
523+
524+
525+ ValueLocation CallingConvention::GetReturnValueLocation (const ReturnValue& returnValue)
526+ {
527+ return GetDefaultReturnValueLocation (returnValue);
528+ }
529+
530+
531+ vector<ValueLocation> CallingConvention::GetParameterLocations (const optional<ValueLocation>& returnValue,
532+ const vector<FunctionParameter>& params, const optional<set<uint32_t >>& permittedRegs)
533+ {
534+ return GetDefaultParameterLocations (returnValue, params, permittedRegs);
535+ }
536+
537+
538+ CallLayout CallingConvention::GetDefaultCallLayout (const ReturnValue& returnValue,
539+ const vector<FunctionParameter>& params, const optional<set<uint32_t >>& permittedRegs)
540+ {
541+ BNReturnValue ret = returnValue.ToAPIObject ();
542+ BNFunctionParameter* paramArray = new BNFunctionParameter[params.size ()];
543+ for (size_t i = 0 ; i < params.size (); i++)
544+ paramArray[i] = params[i].ToAPIObject ();
545+
546+ BNCallLayout layout;
547+ if (permittedRegs.has_value ())
548+ {
549+ uint32_t * regs = new uint32_t [permittedRegs->size ()];
550+ size_t i = 0 ;
551+ for (auto reg : *permittedRegs)
552+ regs[i++] = reg;
553+ layout = BNGetDefaultCallLayout (m_object, &ret, paramArray, params.size (), regs, permittedRegs->size ());
554+ delete[] regs;
555+ }
556+ else
557+ {
558+ layout = BNGetDefaultCallLayoutDefaultPermittedArgs (m_object, &ret, paramArray, params.size ());
559+ }
560+
561+ ReturnValue::FreeAPIObject (&ret);
562+ for (size_t i = 0 ; i < params.size (); i++)
563+ FunctionParameter::FreeAPIObject (¶mArray[i]);
564+ delete[] paramArray;
565+
566+ CallLayout result = CallLayout::FromAPIObject (&layout);
567+ BNFreeCallLayout (&layout);
568+ return result;
569+ }
570+
571+
572+ ValueLocation CallingConvention::GetDefaultReturnValueLocation (const ReturnValue& returnValue)
573+ {
574+ BNReturnValue ret = returnValue.ToAPIObject ();
575+ BNValueLocation location = BNGetDefaultReturnValueLocation (m_object, &ret);
576+ ReturnValue::FreeAPIObject (&ret);
577+
578+ ValueLocation result = ValueLocation::FromAPIObject (&location);
579+ BNFreeValueLocation (&location);
580+ return result;
581+ }
582+
583+
584+ vector<ValueLocation> CallingConvention::GetDefaultParameterLocations (const optional<ValueLocation>& returnValue,
585+ const vector<FunctionParameter>& params, const optional<set<uint32_t >>& permittedRegs)
586+ {
587+ BNValueLocation* retOpt = nullptr ;
588+ BNValueLocation ret;
589+ if (returnValue.has_value ())
590+ {
591+ ret = returnValue->ToAPIObject ();
592+ retOpt = &ret;
593+ }
594+ BNFunctionParameter* paramArray = new BNFunctionParameter[params.size ()];
595+ for (size_t i = 0 ; i < params.size (); i++)
596+ paramArray[i] = params[i].ToAPIObject ();
597+
598+ size_t locationCount = 0 ;
599+ BNValueLocation* locations;
600+ if (permittedRegs.has_value ())
601+ {
602+ uint32_t * regs = new uint32_t [permittedRegs->size ()];
603+ size_t i = 0 ;
604+ for (auto reg : *permittedRegs)
605+ regs[i++] = reg;
606+ locations = BNGetDefaultParameterLocations (
607+ m_object, retOpt, paramArray, params.size (), regs, permittedRegs->size (), &locationCount);
608+ }
609+ else
610+ {
611+ locations = BNGetDefaultParameterLocationsDefaultPermittedArgs (
612+ m_object, retOpt, paramArray, params.size (), &locationCount);
613+ }
614+
615+ if (retOpt)
616+ ValueLocation::FreeAPIObject (retOpt);
617+ for (size_t i = 0 ; i < params.size (); i++)
618+ FunctionParameter::FreeAPIObject (¶mArray[i]);
619+ delete[] paramArray;
620+
621+ vector<ValueLocation> result;
622+ result.reserve (locationCount);
623+ for (size_t i = 0 ; i < locationCount; i++)
624+ result.push_back (ValueLocation::FromAPIObject (&locations[i]));
625+ BNFreeValueLocationList (locations, locationCount);
626+ return result;
627+ }
628+
629+
373630CoreCallingConvention::CoreCallingConvention (BNCallingConvention* cc) : CallingConvention(cc) {}
374631
375632
@@ -504,3 +761,95 @@ Variable CoreCallingConvention::GetParameterVariableForIncomingVariable(const Va
504761{
505762 return BNGetParameterVariableForIncomingVariable (m_object, &var, func ? func->GetObject () : nullptr );
506763}
764+
765+
766+ CallLayout CoreCallingConvention::GetCallLayout (const ReturnValue& returnValue, const vector<FunctionParameter>& params,
767+ const optional<set<uint32_t >>& permittedRegs)
768+ {
769+ BNReturnValue ret = returnValue.ToAPIObject ();
770+ BNFunctionParameter* paramArray = new BNFunctionParameter[params.size ()];
771+ for (size_t i = 0 ; i < params.size (); i++)
772+ paramArray[i] = params[i].ToAPIObject ();
773+
774+ BNCallLayout layout;
775+ if (permittedRegs.has_value ())
776+ {
777+ uint32_t * regs = new uint32_t [permittedRegs->size ()];
778+ size_t i = 0 ;
779+ for (auto reg : *permittedRegs)
780+ regs[i++] = reg;
781+ layout = BNGetCallLayout (m_object, &ret, paramArray, params.size (), regs, permittedRegs->size ());
782+ delete[] regs;
783+ }
784+ else
785+ {
786+ layout = BNGetCallLayoutDefaultPermittedArgs (m_object, &ret, paramArray, params.size ());
787+ }
788+
789+ ReturnValue::FreeAPIObject (&ret);
790+ for (size_t i = 0 ; i < params.size (); i++)
791+ FunctionParameter::FreeAPIObject (¶mArray[i]);
792+ delete[] paramArray;
793+
794+ CallLayout result = CallLayout::FromAPIObject (&layout);
795+ BNFreeCallLayout (&layout);
796+ return result;
797+ }
798+
799+
800+ ValueLocation CoreCallingConvention::GetReturnValueLocation (const ReturnValue& returnValue)
801+ {
802+ BNReturnValue ret = returnValue.ToAPIObject ();
803+ BNValueLocation location = BNGetReturnValueLocation (m_object, &ret);
804+ ReturnValue::FreeAPIObject (&ret);
805+
806+ ValueLocation result = ValueLocation::FromAPIObject (&location);
807+ BNFreeValueLocation (&location);
808+ return result;
809+ }
810+
811+
812+ vector<ValueLocation> CoreCallingConvention::GetParameterLocations (const optional<ValueLocation>& returnValue,
813+ const vector<FunctionParameter>& params, const optional<set<uint32_t >>& permittedRegs)
814+ {
815+ BNValueLocation* retOpt = nullptr ;
816+ BNValueLocation ret;
817+ if (returnValue.has_value ())
818+ {
819+ ret = returnValue->ToAPIObject ();
820+ retOpt = &ret;
821+ }
822+ BNFunctionParameter* paramArray = new BNFunctionParameter[params.size ()];
823+ for (size_t i = 0 ; i < params.size (); i++)
824+ paramArray[i] = params[i].ToAPIObject ();
825+
826+ size_t locationCount = 0 ;
827+ BNValueLocation* locations;
828+ if (permittedRegs.has_value ())
829+ {
830+ uint32_t * regs = new uint32_t [permittedRegs->size ()];
831+ size_t i = 0 ;
832+ for (auto reg : *permittedRegs)
833+ regs[i++] = reg;
834+ locations = BNGetParameterLocations (
835+ m_object, retOpt, paramArray, params.size (), regs, permittedRegs->size (), &locationCount);
836+ }
837+ else
838+ {
839+ locations =
840+ BNGetParameterLocationsDefaultPermittedArgs (m_object, retOpt, paramArray, params.size (), &locationCount);
841+ }
842+
843+ if (retOpt)
844+ ValueLocation::FreeAPIObject (retOpt);
845+ for (size_t i = 0 ; i < params.size (); i++)
846+ FunctionParameter::FreeAPIObject (¶mArray[i]);
847+ delete[] paramArray;
848+
849+ vector<ValueLocation> result;
850+ result.reserve (locationCount);
851+ for (size_t i = 0 ; i < locationCount; i++)
852+ result.push_back (ValueLocation::FromAPIObject (&locations[i]));
853+ BNFreeValueLocationList (locations, locationCount);
854+ return result;
855+ }
0 commit comments