@@ -3971,6 +3971,159 @@ class X86LinuxSystemCallConvention: public CallingConvention
39713971};
39723972
39733973
3974+ class X86PascalCallingConvention : public X86BaseCallingConvention
3975+ {
3976+ public:
3977+ X86PascalCallingConvention (Architecture* arch) : X86BaseCallingConvention(arch, " pascal" ) {}
3978+
3979+ bool IsNonRegisterArgumentIndirect (Type* type) override
3980+ {
3981+ return type && !type->IsFloat () && type->GetWidth () > 4 ;
3982+ }
3983+
3984+ bool IsStackAdjustedOnReturn () override
3985+ {
3986+ return true ;
3987+ }
3988+
3989+ bool AreStackArgumentsPushedLeftToRight () override
3990+ {
3991+ return true ;
3992+ }
3993+
3994+ Variable GetIndirectReturnValueLocation () override
3995+ {
3996+ // Return value pointer is always at the top of the stack (effectively the last parameter
3997+ // in a left-to-right convention)
3998+ return Variable::StackOffset (4 );
3999+ }
4000+
4001+ std::optional<Variable> GetReturnedIndirectReturnValuePointer () override
4002+ {
4003+ return std::nullopt ;
4004+ }
4005+ };
4006+
4007+
4008+ class X86PascalRegisterCallingConvention : public X86BaseCallingConvention
4009+ {
4010+ public:
4011+ X86PascalRegisterCallingConvention (Architecture* arch) : X86BaseCallingConvention(arch, " register" ) {}
4012+
4013+ vector<uint32_t > GetIntegerArgumentRegisters () override
4014+ {
4015+ return { XED_REG_EAX, XED_REG_EDX, XED_REG_ECX };
4016+ }
4017+
4018+ bool IsNonRegisterArgumentIndirect (Type* type) override
4019+ {
4020+ return type && !type->IsFloat () && type->GetWidth () > 4 ;
4021+ }
4022+
4023+ bool AreStackArgumentsPushedLeftToRight () override
4024+ {
4025+ return true ;
4026+ }
4027+
4028+ std::optional<Variable> GetReturnedIndirectReturnValuePointer () override
4029+ {
4030+ return std::nullopt ;
4031+ }
4032+ };
4033+
4034+
4035+ class X86GoStackCallingConvention : public CallingConvention
4036+ {
4037+ public:
4038+ X86GoStackCallingConvention (Architecture* arch): CallingConvention(arch, " go-stack" )
4039+ {
4040+ }
4041+
4042+ bool IsEligibleForHeuristics () override
4043+ {
4044+ // This convention cannot be detected by heuristics at this time and will cause issues
4045+ // with non-Go code.
4046+ return false ;
4047+ }
4048+
4049+ uint32_t GetIntegerReturnValueRegister () override
4050+ {
4051+ return BN_INVALID_REGISTER;
4052+ }
4053+
4054+ vector<uint32_t > GetCallerSavedRegisters () override
4055+ {
4056+ return vector<uint32_t > { XED_REG_EAX, XED_REG_ECX, XED_REG_EDX, XED_REG_EBX, XED_REG_EBP };
4057+ }
4058+
4059+ RegisterValue GetIncomingFlagValue (uint32_t flag, Function*) override
4060+ {
4061+ RegisterValue result;
4062+ if (flag == IL_FLAG_D)
4063+ {
4064+ result.state = ConstantValue;
4065+ result.value = 0 ;
4066+ }
4067+ return result;
4068+ }
4069+
4070+ ValueLocation GetReturnValueLocation (const ReturnValue&) override
4071+ {
4072+ // It is not possible for this API to determine the return value location on the stack at
4073+ // this point, return an invalid location and fall back to GetCallLayout.
4074+ return ValueLocation ();
4075+ }
4076+
4077+ CallLayout GetCallLayout (const ReturnValue& returnValue, const vector<FunctionParameter>& params,
4078+ const std::optional<set<uint32_t >>& permittedRegs) override
4079+ {
4080+ CallLayout result;
4081+ result.parameters = GetParameterLocations (result.returnValue , params, permittedRegs);
4082+
4083+ if (returnValue.type .GetValue () && returnValue.type ->GetClass () != VoidTypeClass)
4084+ {
4085+ if (returnValue.defaultLocation )
4086+ {
4087+ int64_t stackOffset = 4 ;
4088+ size_t i = 0 ;
4089+ for (auto it = result.parameters .begin (); it != result.parameters .end (); ++i, ++it)
4090+ {
4091+ if (i >= params.size ())
4092+ continue ;
4093+ if (!params[i].type .GetValue ())
4094+ continue ;
4095+
4096+ auto var = it->GetVariableForParameter (i);
4097+ if (!var.has_value ())
4098+ continue ;
4099+ if (var->type != StackVariableSourceType)
4100+ continue ;
4101+ if (var->storage < stackOffset)
4102+ continue ;
4103+
4104+ uint64_t width = params[i].type ->GetWidth ();
4105+ if (width < 4 )
4106+ width = 4 ;
4107+ else if ((width % 4 ) != 0 )
4108+ width += 4 - (width % 4 );
4109+
4110+ stackOffset = var->storage + width;
4111+ }
4112+
4113+ result.returnValue = Variable::StackOffset (stackOffset);
4114+ }
4115+ else
4116+ {
4117+ result.returnValue = returnValue.location .GetValue ();
4118+ }
4119+ }
4120+
4121+ result.registerStackAdjustments = GetRegisterStackAdjustments (result.returnValue , result.parameters );
4122+ return result;
4123+ }
4124+ };
4125+
4126+
39744127class X64BaseCallingConvention : public CallingConvention
39754128{
39764129public:
@@ -4103,7 +4256,7 @@ class X64WindowsCallingConvention: public X64BaseCallingConvention
41034256 || type->GetWidth () == 8 ;
41044257 }
41054258
4106- bool AreNonRegisterArgumentsIndirect ( ) override
4259+ bool IsNonRegisterArgumentIndirect (Type* ) override
41074260 {
41084261 return true ;
41094262 }
@@ -4145,6 +4298,100 @@ class X64LinuxSystemCallConvention: public CallingConvention
41454298};
41464299
41474300
4301+ class X64GoStackCallingConvention : public CallingConvention
4302+ {
4303+ public:
4304+ X64GoStackCallingConvention (Architecture* arch): CallingConvention(arch, " go-stack" )
4305+ {
4306+ }
4307+
4308+ bool IsEligibleForHeuristics () override
4309+ {
4310+ // This convention cannot be detected by heuristics at this time and will cause issues
4311+ // with non-Go code.
4312+ return false ;
4313+ }
4314+
4315+ uint32_t GetIntegerReturnValueRegister () override
4316+ {
4317+ return BN_INVALID_REGISTER;
4318+ }
4319+
4320+ vector<uint32_t > GetCallerSavedRegisters () override
4321+ {
4322+ return vector<uint32_t > { XED_REG_RAX, XED_REG_RCX, XED_REG_RDX, XED_REG_RBX, XED_REG_RBP,
4323+ XED_REG_R8, XED_REG_R9, XED_REG_R10, XED_REG_R11, XED_REG_R12, XED_REG_R13, XED_REG_R14,
4324+ XED_REG_R15 };
4325+ }
4326+
4327+ RegisterValue GetIncomingFlagValue (uint32_t flag, Function*) override
4328+ {
4329+ RegisterValue result;
4330+ if (flag == IL_FLAG_D)
4331+ {
4332+ result.state = ConstantValue;
4333+ result.value = 0 ;
4334+ }
4335+ return result;
4336+ }
4337+
4338+ ValueLocation GetReturnValueLocation (const ReturnValue&) override
4339+ {
4340+ // It is not possible for this API to determine the return value location on the stack at
4341+ // this point, return an invalid location and fall back to GetCallLayout.
4342+ return ValueLocation ();
4343+ }
4344+
4345+ CallLayout GetCallLayout (const ReturnValue& returnValue, const vector<FunctionParameter>& params,
4346+ const std::optional<set<uint32_t >>& permittedRegs) override
4347+ {
4348+ CallLayout result;
4349+ result.parameters = GetParameterLocations (result.returnValue , params, permittedRegs);
4350+
4351+ if (returnValue.type .GetValue () && returnValue.type ->GetClass () != VoidTypeClass)
4352+ {
4353+ if (returnValue.defaultLocation )
4354+ {
4355+ int64_t stackOffset = 8 ;
4356+ size_t i = 0 ;
4357+ for (auto it = result.parameters .begin (); it != result.parameters .end (); ++i, ++it)
4358+ {
4359+ if (i >= params.size ())
4360+ continue ;
4361+ if (!params[i].type .GetValue ())
4362+ continue ;
4363+
4364+ auto var = it->GetVariableForParameter (i);
4365+ if (!var.has_value ())
4366+ continue ;
4367+ if (var->type != StackVariableSourceType)
4368+ continue ;
4369+ if (var->storage < stackOffset)
4370+ continue ;
4371+
4372+ uint64_t width = params[i].type ->GetWidth ();
4373+ if (width < 8 )
4374+ width = 8 ;
4375+ else if ((width % 8 ) != 0 )
4376+ width += 8 - (width % 8 );
4377+
4378+ stackOffset = var->storage + width;
4379+ }
4380+
4381+ result.returnValue = Variable::StackOffset (stackOffset);
4382+ }
4383+ else
4384+ {
4385+ result.returnValue = returnValue.location .GetValue ();
4386+ }
4387+ }
4388+
4389+ result.registerStackAdjustments = GetRegisterStackAdjustments (result.returnValue , result.parameters );
4390+ return result;
4391+ }
4392+ };
4393+
4394+
41484395class x86MachoRelocationHandler : public RelocationHandler
41494396{
41504397public:
@@ -5052,6 +5299,12 @@ extern "C"
50525299 x86->RegisterCallingConvention (conv);
50535300 conv = new X86LinuxSystemCallConvention (x86);
50545301 x86->RegisterCallingConvention (conv);
5302+ conv = new X86PascalCallingConvention (x86);
5303+ x86->RegisterCallingConvention (conv);
5304+ conv = new X86PascalRegisterCallingConvention (x86);
5305+ x86->RegisterCallingConvention (conv);
5306+ conv = new X86GoStackCallingConvention (x86);
5307+ x86->RegisterCallingConvention (conv);
50555308
50565309 x86->RegisterRelocationHandler (" Mach-O" , new x86MachoRelocationHandler ());
50575310 x86->RegisterRelocationHandler (" KCView" , new x86MachoRelocationHandler ());
@@ -5069,6 +5322,8 @@ extern "C"
50695322 x64->RegisterCallingConvention (conv);
50705323 conv = new X64LinuxSystemCallConvention (x64);
50715324 x64->RegisterCallingConvention (conv);
5325+ conv = new X64GoStackCallingConvention (x64);
5326+ x64->RegisterCallingConvention (conv);
50725327
50735328 x64->RegisterRelocationHandler (" Mach-O" , new x64MachoRelocationHandler ());
50745329 x64->RegisterRelocationHandler (" KCView" , new x64MachoRelocationHandler ());
0 commit comments