/** ControlFlowAnalysis implements FunctionAnalysis interface **/
func (a *ControlFlowAnalysis) AnalyzeFunction(f *artifacts.Function) error {
	ld, e := LD.New(a.ws)
	check(e)

	cj, e := ld.RegisterJumpTraceHandler(func(
		insn gapstone.Instruction,
		from_bb AS.VA,
		target AS.VA,
		jtype P.JumpType) error {

		return a.ws.MakeCodeCrossReference(AS.VA(insn.Address), target, jtype)
	})
	check(e)
	defer ld.UnregisterJumpTraceHandler(cj)

	cb, e := ld.RegisterBBTraceHandler(func(start AS.VA, end AS.VA) error {
		return a.ws.MakeBasicBlock(start, end)
	})
	check(e)
	defer ld.UnregisterBBTraceHandler(cb)

	c, e := ld.RegisterCallTraceHandler(func(from AS.VA, to AS.VA) error {
		return a.ws.MakeCallCrossReference(from, to)
	})
	check(e)
	defer ld.UnregisterCallTraceHandler(c)

	e = ld.ExploreFunction(a.ws, f.Start)
	check(e)

	return nil
}
/** StackDeltaAnalysis implements FunctionAnalysis interface **/
func (a *StackDeltaAnalysis) AnalyzeFunction(f *artifacts.Function) error {
	ld, e := LD.New(a.ws)
	check(e)

	didSetStackDelta := false
	c, e := ld.RegisterInstructionTraceHandler(func(insn gapstone.Instruction) error {
		if !didSetStackDelta {
			if !disassembly.DoesInstructionHaveGroup(insn, gapstone.X86_GRP_RET) {
				return nil
			}
			if len(insn.X86.Operands) == 0 {
				f.SetStackDelta(0)
				return nil
			}
			if insn.X86.Operands[0].Type != gapstone.X86_OP_IMM {
				return nil
			}
			stackDelta := insn.X86.Operands[0].Imm
			f.SetStackDelta(stackDelta)
			didSetStackDelta = true
		}
		return nil
	})
	check(e)
	defer ld.UnregisterInstructionTraceHandler(c)

	e = ld.ExploreFunction(a.ws, f.Start)
	check(e)

	return nil
}