public override void Process() { var builder = new VectorBuilder(scanner, program, new DirectedGraphImpl <object>()); var vector = builder.Build(Table.TableAddress, AddrFrom, State); if (vector.Count == 0) { Address addrNext = Table.TableAddress + Stride.Size; if (program.Image.IsValidAddress(addrNext)) { // Can't determine the size of the table, but surely it has one entry? program.ImageMap.AddItem(addrNext, new ImageMapItem()); } return; } Table.Addresses.AddRange(vector); for (int i = 0; i < vector.Count; ++i) { var st = State.Clone(); if (Table.IsCallTable) { scanner.ScanProcedure(vector[i], null, st); } else { //$TODO: BlockFromAddress. scanner.EnqueueJumpTarget(AddrFrom, vector[i], proc, st); } } vectorUses[AddrFrom] = new VectorUse(Table.TableAddress, builder.IndexRegister); program.ImageMap.AddItem(Table.TableAddress + builder.TableByteSize, new ImageMapItem()); }
public ProcedureBase ScanProcedure(IProcessorArchitecture arch, Address addr, string?procedureName, ProcessorState state) { TerminateAnyBlockAt(addr); if (TryGetNoDecompiledProcedure(addr, out var ep)) { return(ep); } if (Program.InterceptedCalls.TryGetValue(addr, out ep)) { return(ep); } var trampoline = GetTrampoline(arch, addr); if (trampoline != null) { return(trampoline); } var imp = GetImportedProcedure(arch, addr, addr); if (imp != null) { return(imp); } Procedure proc = Program.EnsureProcedure(arch, addr, procedureName); if (visitedProcs.Contains(proc)) { return(proc); } visitedProcs.Add(proc); trace.Inform("Scanning procedure at {0}", addr); var st = state.Clone(); EstablishInitialState(addr, st, proc); //$REFACTOR: make the stack explicit? var oldQueue = procQueue; procQueue = new PriorityQueue <WorkItem>(); var block = EnqueueJumpTarget(addr, addr, proc, st); if (proc.EntryBlock.Succ.Count == 0) { proc.ControlGraph.AddEdge(proc.EntryBlock, block !); } ProcessQueue(); procQueue = oldQueue; InjectProcedureEntryInstructions(addr, proc); var usb = new UserSignatureBuilder(Program); usb.BuildSignature(addr, proc); cinj.InjectComments(proc); return(proc); }
/// <summary> /// Performs a scan of the blocks that constitute a procedure named <paramref name="procedureName"/> /// </summary> /// <param name="addr">Address of the code from which we will start scanning.</param> /// <param name="procedureName"></param> /// <param name="state"></param> /// <returns></returns> public ProcedureBase ScanProcedure(Address addr, string procedureName, ProcessorState state) { TerminateAnyBlockAt(addr); ExternalProcedure ep; if (TryGetNoDecompiledProcedure(addr, out ep)) { return(ep); } if (program.InterceptedCalls.TryGetValue(addr, out ep)) { return(ep); } var trampoline = GetTrampoline(addr); if (trampoline != null) { return(trampoline); } var imp = GetImportedProcedure(addr, addr); if (imp != null) { return(imp); } Procedure proc = EnsureProcedure(addr, procedureName); if (visitedProcs.Contains(proc)) { return(proc); } visitedProcs.Add(proc); Debug.WriteLineIf(trace.TraceInfo, string.Format("Scanning procedure at {0}", addr)); var st = state.Clone(); EstablishInitialState(addr, st, proc); //$REFACTOR: make the stack explicit? var oldQueue = queue; queue = new PriorityQueue <WorkItem>(); var block = EnqueueJumpTarget(addr, addr, proc, st); proc.ControlGraph.AddEdge(proc.EntryBlock, block); ProcessQueue(); queue = oldQueue; InjectProcedureEntryInstructions(addr, proc); var usb = new UserSignatureBuilder(program); usb.BuildSignature(addr, proc); return(proc); }
/// <summary> /// Performs a scan of the blocks that constitute a procedure named <paramref name="procedureName"/> /// </summary> /// <param name="addr">Address of the code from which we will start scanning.</param> /// <param name="procedureName"></param> /// <param name="state"></param> /// <returns></returns> public ProcedureBase ScanProcedure(Address addr, string procedureName, ProcessorState state) { TerminateAnyBlockAt(addr); ExternalProcedure ep; if (program.InterceptedCalls.TryGetValue(addr, out ep)) { return(ep); } var trampoline = GetTrampoline(addr); if (trampoline != null) { return(trampoline); } var imp = GetImportedProcedure(addr, addr); if (imp != null) { return(imp); } Procedure proc = EnsureProcedure(addr, procedureName); if (visitedProcs.Contains(proc)) { return(proc); } visitedProcs.Add(proc); Debug.WriteLineIf(trace.TraceInfo, string.Format("Scanning procedure at {0}", addr)); //$REFACTOR: make the stack explicit? var oldQueue = queue; queue = new PriorityQueue <WorkItem>(); var st = state.Clone(); st.SetInstructionPointer(addr); st.OnProcedureEntered(); var sp = proc.Frame.EnsureRegister(program.Architecture.StackRegister); st.SetValue(sp, proc.Frame.FramePointer); SetAssumedRegisterValues(addr, st); var block = EnqueueJumpTarget(addr, addr, proc, st); proc.ControlGraph.AddEdge(proc.EntryBlock, block); ProcessQueue(); queue = oldQueue; // Add <stackpointer> := fp explicitly to the starting block. EstablishFrame(addr, proc, sp); return(proc); }
public void EnqueueVectorTable(Address addrFrom, Address addrTable, PrimitiveType elemSize, ushort segBase, bool calltable, Procedure proc, ProcessorState state) { ImageMapVectorTable table; if (vectors.TryGetValue(addrTable, out table)) { return; } table = new ImageMapVectorTable(addrTable, calltable); var wi = new VectorWorkItem(this, program, table, proc); wi.State = state.Clone(); wi.Stride = elemSize; wi.SegBase = segBase; wi.Table = table; wi.AddrFrom = addrFrom; imageMap.AddItem(addrTable, table); vectors[addrTable] = table; queue.Enqueue(PriorityVector, wi); }
Instruction ConditionalBranch(ProcessorState state, Func<Expression, BinaryExpression> condition) { var val1 = state.Stack.Pop(); var test = condition(val1); var left = (Instruction) state.Instruction.Operand; var right = state.Instruction.Next; Instruction common = GetJoinPoint(left, right); var rightState = state.Clone(right, common); var leftState = state.Clone(left, common); states.Push(rightState); states.Push(leftState); // Run this once the conditional branches have been processed state.RunNext = () => state.Merge(test, leftState, rightState); return common; }
/// <summary> /// Branches need to terminate the current basic block and make links /// to the 'true' and 'false' destinations. /// </summary> /// <param name="b"></param> /// <returns></returns> public bool VisitBranch(RtlBranch b) { // We don't know the 'then' block yet, as the following statements may chop up the block // we're presently in. Back-patch in when the block target is obtained. var branch = new Branch(b.Condition, new Block(blockCur.Procedure, "TMP!")); Emit(branch, blockCur); // The following statements may chop up the blockCur, so hang on to the essentials. var proc = blockCur.Procedure; RtlInstructionCluster ricDelayed = null; if ((b.Class & RtlClass.Delay) != 0) { rtlStream.MoveNext(); ricDelayed = rtlStream.Current; ric = ricDelayed; } var fallthruAddress = ric.Address + ric.Length; Block blockThen; if (!program.SegmentMap.IsValidAddress((Address)b.Target)) { blockThen = proc.AddBlock(this.ric.Address.GenerateName("l", "_then")); var jmpSite = state.OnBeforeCall(stackReg, arch.PointerType.Size); GenerateCallToOutsideProcedure(jmpSite, (Address)b.Target); Emit(new ReturnInstruction()); blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock); } else { blockThen = BlockFromAddress(ric.Address, (Address)b.Target, proc, state.Clone()); } var blockElse = FallthroughBlock(ric.Address, proc, fallthruAddress); var branchingBlock = blockCur.IsSynthesized ? blockCur : scanner.FindContainingBlock(ric.Address); if ((b.Class & RtlClass.Delay) != 0 && ricDelayed.Instructions.Length > 0) { // Introduce stubs for the delay slot, but only // if the delay slot isn't empty. if ((b.Class & RtlClass.Annul) != 0) { EnsureEdge(proc, branchingBlock, blockElse); } else { Block blockDsF = null; blockDsF = proc.AddBlock(branchingBlock.Name + "_ds_f"); blockDsF.IsSynthesized = true; blockCur = blockDsF; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsF, blockElse); EnsureEdge(proc, branchingBlock, blockDsF); } Block blockDsT = proc.AddBlock(branchingBlock.Name + "_ds_t"); blockDsT.IsSynthesized = true; blockCur = blockDsT; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsT, blockThen); branch.Target = blockDsT; EnsureEdge(proc, branchingBlock, blockDsT); } else { branch.Target = blockThen; // The back-patch referred to above. EnsureEdge(proc, branchingBlock, blockElse); if (blockElse != blockThen) { EnsureEdge(proc, branchingBlock, blockThen); } else { proc.ControlGraph.AddEdge(branchingBlock, blockThen); } } if (BlockHasBeenScanned(blockElse)) { return(false); } else { blockCur = blockElse; return(true); } }