Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion analyzer/syscall/asm_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (a *asmSyscallAnalyser) Analyze(path string, withTrace bool) ([]*analyzer.I
}
for _, syscall := range syscalls {
// Categorize syscall
if slices.Contains(a.profile.AllowedSycalls, syscall.Number) {
if slices.Contains(a.profile.AllowedSyscalls, syscall.Number) {
continue
}
sources, err := common.TraceAllAsmCaller(
Expand Down
2 changes: 1 addition & 1 deletion analyzer/syscall/go_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (a *goSyscallAnalyser) Analyze(path string, withTrace bool) ([]*analyzer.Is
issues := make([]*analyzer.Issue, 0)
for i := range syscalls {
syscll := syscalls[i]
if slices.Contains(a.profile.AllowedSycalls, syscll.num) {
if slices.Contains(a.profile.AllowedSyscalls, syscll.num) {
continue
}
stackTrace := a.edgeToCallStack(syscll.edgeStack, fset, withTrace)
Expand Down
30 changes: 21 additions & 9 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import (

var (
VMProfileFlag = &cli.StringFlag{
Name: "vm-profile",
Usage: "Path to the VM profile config file",
Required: true,
Name: "vm-profile",
Usage: "vm profile against which compatibity should be checked. Options: cannon-singlethreaded-32, cannon-multithreaded-32, cannon-multithreaded-64",
}
VMProfileConfigFlag = &cli.StringFlag{
Name: "vm-profile-config",
Usage: "Path to the VM profile config file",
}
AnalysisTypeFlag = &cli.StringFlag{
Name: "analysis-type",
Expand Down Expand Up @@ -67,6 +70,7 @@ func CreateAnalyzeCommand(action cli.ActionFunc) *cli.Command {
Action: action,
Flags: []cli.Flag{
VMProfileFlag,
VMProfileConfigFlag,
AnalysisTypeFlag,
DisassemblyOutputFlag,
FormatFlag,
Expand All @@ -80,8 +84,16 @@ func CreateAnalyzeCommand(action cli.ActionFunc) *cli.Command {
var AnalyzeCommand = CreateAnalyzeCommand(AnalyzeCompatibility)

func AnalyzeCompatibility(ctx *cli.Context) error {
vmProfile := ctx.Path(VMProfileFlag.Name)
prof, err := profile.LoadProfile(vmProfile)
var vmProfile *profile.VMProfile
var err error
prof := ctx.Path(VMProfileFlag.Name)
if prof != "" {
vmProfile, err = profile.LoadProfile(prof)
} else {
profPath := ctx.Path(VMProfileConfigFlag.Name)
vmProfile, err = profile.LoadProfileFromConfig(profPath)
}

if err != nil {
return fmt.Errorf("error loading profile: %w", err)
}
Expand All @@ -94,25 +106,25 @@ func AnalyzeCompatibility(ctx *cli.Context) error {
withTrace := ctx.Bool(TraceFlag.Name)
baselineReport := ctx.Path(BaselineReport.Name)

disassemblyPath, err = disassemble(prof, source, disassemblyPath)
disassemblyPath, err = disassemble(vmProfile, source, disassemblyPath)
if err != nil {
return fmt.Errorf("error disassembling the file: %w", err)
}

issues, err := analyze(prof, disassemblyPath, analysisType, withTrace)
issues, err := analyze(vmProfile, disassemblyPath, analysisType, withTrace)
if err != nil {
return fmt.Errorf("analysis failed: %w", err)
}

if baselineReport != "" {
err = compareReport(issues, format, reportOutputPath, prof, baselineReport)
err = compareReport(issues, format, reportOutputPath, vmProfile, baselineReport)
if err != nil {
return fmt.Errorf("error comparing reports: %w", err)
}
return nil
}

if err := writeReport(issues, format, reportOutputPath, prof); err != nil {
if err := writeReport(issues, format, reportOutputPath, vmProfile); err != nil {
return fmt.Errorf("unable to write report: %w", err)
}
return nil
Expand Down
17 changes: 13 additions & 4 deletions cmd/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func CreateTraceCommand(action cli.ActionFunc) *cli.Command {
Action: action,
Flags: []cli.Flag{
VMProfileFlag,
VMProfileConfigFlag,
FunctionNameFlag,
SourceTypeFlag,
},
Expand All @@ -44,8 +45,16 @@ func CreateTraceCommand(action cli.ActionFunc) *cli.Command {
var TraceCommand = CreateTraceCommand(TraceCaller)

func TraceCaller(ctx *cli.Context) error {
vmProfile := ctx.Path(VMProfileFlag.Name)
prof, err := profile.LoadProfile(vmProfile)
var vmProfile *profile.VMProfile
var err error
prof := ctx.Path(VMProfileFlag.Name)
if prof != "" {
vmProfile, err = profile.LoadProfile(prof)
} else {
profPath := ctx.Path(VMProfileConfigFlag.Name)
vmProfile, err = profile.LoadProfileFromConfig(profPath)
}

if err != nil {
return fmt.Errorf("error loading profile: %w", err)
}
Expand All @@ -56,9 +65,9 @@ func TraceCaller(ctx *cli.Context) error {

var analyzer analyzer.Analyzer
if sourceType == "go" {
analyzer = syscall.NewGOSyscallAnalyser(prof)
analyzer = syscall.NewGOSyscallAnalyser(vmProfile)
} else {
analyzer = syscall.NewAssemblySyscallAnalyser(prof)
analyzer = syscall.NewAssemblySyscallAnalyser(vmProfile)
}

callStack, err := analyzer.TraceStack(path, function)
Expand Down
237 changes: 237 additions & 0 deletions profile/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package profile

var vmProfileConfigs map[string]*VMProfile = map[string]*VMProfile{
"cannon-singlethreaded-32": {
VMName: "Cannon Singlethreaded 32bit",
GOOS: "linux",
GOARCH: "mips",
IgnoredFunctions: []string{
"syscall.setrlimit",
"runtime.morestack",
"runtime.abort",
"runtime.exitThread",
"runtime.sigaltstack",
"runtime.rtsigprocmask",
"runtime.munmap",
"runtime.exit",
"runtime.gcenable",
"runtime.init.5",
"runtime.main.func1",
"runtime.deductSweepCredit",
"runtime.(*gcControllerState).commit",
"github.com/prometheus/client_golang/prometheus.init",
"github.com/prometheus/client_golang/prometheus.init.0",
"github.com/prometheus/procfs.init",
"github.com/prometheus/common/model.init",
"github.com/prometheus/client_model/go.init",
"github.com/prometheus/client_model/go.init.0",
"github.com/prometheus/client_model/go.init.1",
"flag.init",
"runtime.check",
"runtime.sysFaultOS",
"runtime.netpollinit",
},
AllowedOpcodes: []OpcodeInstruction{
{Opcode: "0x2"},
{Opcode: "0x3"},
{Opcode: "0x4"},
{Opcode: "0x5"},
{Opcode: "0x6"},
{Opcode: "0x7"},
{Opcode: "0x1"},
{Opcode: "0x1a"},
{Opcode: "0x1b"},
{Opcode: "0x0", Funct: []string{
"0x0", "0x2", "0x3", "0x4", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xf",
"0x10", "0x11", "0x12", "0x13", "0x18", "0x19", "0x1a", "0x1b", "0x20", "0x21", "0x22",
"0x23", "0x24", "0x25", "0x26", "0x27", "0x2a", "0x2b", "0xa", "0xb", "0xc",
}},
{Opcode: "0x8"},
{Opcode: "0x9"},
{Opcode: "0xa"},
{Opcode: "0xb"},
{Opcode: "0xc"},
{Opcode: "0xd"},
{Opcode: "0xe"},
{Opcode: "0x1c", Funct: []string{"0x2", "0x20", "0x21"}},
{Opcode: "0xf"},
{Opcode: "0x20"},
{Opcode: "0x21"},
{Opcode: "0x22"},
{Opcode: "0x23"},
{Opcode: "0x24"},
{Opcode: "0x25"},
{Opcode: "0x26"},
{Opcode: "0x28"},
{Opcode: "0x29"},
{Opcode: "0x2a"},
{Opcode: "0x2b"},
{Opcode: "0x2e"},
{Opcode: "0x30"},
{Opcode: "0x38"},
},
AllowedSyscalls: []int{4090, 4045, 4120, 4246, 4003, 4004, 4055},
NOOPSyscalls: []int{
4000, 4001, 4002, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012,
4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026,
4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041,
4042, 4043, 4044, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4056, 4057, 4058,
4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073,
4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088,
4089, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104,
4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119,
4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135,
4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150,
4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165,
4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180,
4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194,
4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208,
4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222,
4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236,
4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4247, 4248, 4249, 4250, 4251,
4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265,
4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4280,
4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294,
4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308,
4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322,
4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336,
4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4346, 4346, 4305, 4310,
},
},
"cannon-multithreaded-32": {
VMName: "Cannon Multithreaded 32bit",
GOOS: "linux",
GOARCH: "mips",
IgnoredFunctions: []string{
"syscall.setrlimit",
"runtime.morestack",
"runtime.abort",
"runtime.exitThread",
"runtime.sigaltstack",
"runtime.rtsigprocmask",
"runtime.munmap",
"runtime.exit",
"runtime.sysFaultOS",
"runtime.netpollinit",
},
AllowedOpcodes: []OpcodeInstruction{
{"0x2", []string{}},
{"0x3", []string{}},
{"0x4", []string{}},
{"0x5", []string{}},
{"0x6", []string{}},
{"0x7", []string{}},
{"0x1", []string{}},
{"0x1a", []string{}},
{"0x1b", []string{}},
{"0x0", []string{
"0x0", "0x2", "0x3", "0x4", "0x6", "0x7", "0x8", "0x9",
"0xa", "0xb", "0xc", "0xf", "0x10", "0x11", "0x12", "0x13", "0x18", "0x19",
"0x1a", "0x1b", "0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26",
"0x27", "0x2a", "0x2b", "0xa", "0xb", "0xc",
}},
{"0x8", []string{}},
{"0x9", []string{}},
{"0xa", []string{}},
{"0xb", []string{}},
{"0xc", []string{}},
{"0xd", []string{}},
{"0xe", []string{}},
{"0x1c", []string{"0x2", "0x20", "0x21"}},
{"0xf", []string{}},
{"0x20", []string{}},
{"0x21", []string{}},
{"0x22", []string{}},
{"0x23", []string{}},
{"0x24", []string{}},
{"0x25", []string{}},
{"0x26", []string{}},
{"0x28", []string{}},
{"0x29", []string{}},
{"0x2a", []string{}},
{"0x2b", []string{}},
{"0x2e", []string{}},
{"0x30", []string{}},
{"0x38", []string{}},
},
AllowedSyscalls: []int{
4090, 4045, 4120, 4246, 4003, 4004, 4055, 4222, 4001, 4238, 4162,
4166, 4005, 4263, 4020,
},
NOOPSyscalls: []int{
4091, 4240, 4218, 4195, 4206, 4194, 4338, 4006, 4200, 4106,
4108, 4288, 4085, 4298, 4054, 4326, 4328, 4249, 4313, 4353, 4122, 4024, 4047,
4217, 4266, 4104, 4257, 4258, 4261, 4076, 4019, 4215, 4213, 4140,
},
},
"cannon-multithreaded-64": {
VMName: "Cannon Multithreaded 64bit",
GOOS: "linux",
GOARCH: "mips64",
IgnoredFunctions: []string{
"syscall.setrlimit",
"runtime.morestack",
"runtime.abort",
"runtime.sysFaultOS",
"runtime.netpollinit",
},
AllowedOpcodes: []OpcodeInstruction{
{Opcode: "0x2", Funct: []string{}},
{Opcode: "0x3", Funct: []string{}},
{Opcode: "0x38", Funct: []string{}},
{Opcode: "0x30", Funct: []string{}},
{Opcode: "0x27", Funct: []string{}},
{Opcode: "0x1a", Funct: []string{}},
{Opcode: "0x1b", Funct: []string{}},
{Opcode: "0x4", Funct: []string{}},
{Opcode: "0x5", Funct: []string{}},
{Opcode: "0x6", Funct: []string{}},
{Opcode: "0x7", Funct: []string{}},
{Opcode: "0x1", Funct: []string{}},
{Opcode: "0x0", Funct: []string{
"0x27", "0x20", "0x21", "0x2A", "0x2B", "0x24", "0x25", "0x26",
"0x2c", "0x2d", "0x0", "0x2", "0x3", "0x4", "0x6", "0x7", "0x8", "0x9",
"0xa", "0xb", "0xc", "0xf", "0x10", "0x11", "0x12", "0x13", "0x14", "0x18",
"0x19", "0x16", "0x17", "0x1C", "0x1D", "0x1E", "0x1F", "0x2c", "0x2d", "0x2e",
"0x2f", "0x38", "0x3A", "0x3B", "0x3C", "0x3E", "0x3F", "0x1a", "0x1b", "0xc",
}},
{Opcode: "0x8", Funct: []string{}},
{Opcode: "0x9", Funct: []string{}},
{Opcode: "0xa", Funct: []string{}},
{Opcode: "0xb", Funct: []string{}},
{Opcode: "0xc", Funct: []string{}},
{Opcode: "0xd", Funct: []string{}},
{Opcode: "0xe", Funct: []string{}},
{Opcode: "0x18", Funct: []string{}},
{Opcode: "0x19", Funct: []string{}},
{Opcode: "0x1c", Funct: []string{"0x2", "0x20", "0x21"}},
{Opcode: "0xf", Funct: []string{}},
{Opcode: "0x20", Funct: []string{}},
{Opcode: "0x21", Funct: []string{}},
{Opcode: "0x22", Funct: []string{}},
{Opcode: "0x23", Funct: []string{}},
{Opcode: "0x24", Funct: []string{}},
{Opcode: "0x25", Funct: []string{}},
{Opcode: "0x26", Funct: []string{}},
{Opcode: "0x28", Funct: []string{}},
{Opcode: "0x29", Funct: []string{}},
{Opcode: "0x2a", Funct: []string{}},
{Opcode: "0x2b", Funct: []string{}},
{Opcode: "0x2e", Funct: []string{}},
{Opcode: "0x2c", Funct: []string{}},
{Opcode: "0x2d", Funct: []string{}},
{Opcode: "0x37", Funct: []string{}},
{Opcode: "0x3f", Funct: []string{}},
{Opcode: "0x34", Funct: []string{}},
{Opcode: "0x3c", Funct: []string{}},
},
AllowedSyscalls: []int{
5009, 5012, 5205, 5000, 5001, 5070, 5055, 5058, 5023, 5178, 5194, 5002, 5034, 5222, 5038,
},
NOOPSyscalls: []int{
5011, 5196, 5027, 5014, 5129, 5013, 5297, 5003, 5016, 5004, 5005, 5247, 5087,
5257, 5015, 5285, 5287, 5208, 5272, 5313, 5061, 5100, 5102, 5026, 5225, 5095, 5008,
5036, 5216, 5217, 5220,
},
},
}
15 changes: 12 additions & 3 deletions profile/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type VMProfile struct {
GOOS string `yaml:"goos"`
GOARCH string `yaml:"goarch"`
AllowedOpcodes []OpcodeInstruction `yaml:"allowed_opcodes"`
AllowedSycalls []int `yaml:"allowed_syscalls"`
AllowedSyscalls []int `yaml:"allowed_syscalls"`
NOOPSyscalls []int `yaml:"noop_syscalls"`
IgnoredFunctions []string `yaml:"ignored_functions"`
}
Expand All @@ -34,8 +34,17 @@ func (p *VMProfile) SetDefaults() {
}
}

// LoadProfile loads a VM profile from a JSON file.
func LoadProfile(filename string) (*VMProfile, error) {
// LoadProfile loads a VM profile for predefined profiles.
func LoadProfile(name string) (*VMProfile, error) {
vmProfile, ok := vmProfileConfigs[name]
if !ok {
return nil, fmt.Errorf("invalid profile")
}
return vmProfile, nil
}

// LoadProfileFromConfig loads a VM profile from a yaml file.
func LoadProfileFromConfig(filename string) (*VMProfile, error) {
path, err := filepath.Abs(filename)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path of profile: %w", err)
Expand Down
Loading
Loading