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