public IMutableBasicBlock CreateNewBlock(BasicBlockType type, int lineNumber, Guid?id = null) { var block = new BasicBlock(id ?? Guid.NewGuid(), type, lineNumber); _vertexLookup.Add(block.ID, block); return(block); }
private static void FillData(BasicBlockType export, BasicBlock bb) { export.ID.Value = bb.ID; List <string> predecessors = new List <string>(); List <string> successors = new List <string>(); bb.getPredecessors.ForEach(x => predecessors.Add(x.ID)); bb.getSuccessors.ForEach(x => successors.Add(x.ID)); if (predecessors.Count > 0) { export.Predecessors.Value = string.Join(" ", predecessors.ToArray()); } if (successors.Count > 0) { export.Successors.Value = string.Join(" ", successors.ToArray()); } // TODO: continue if (bb.PolyRequired) { export.PolyRequired.Value = bb.PolyRequired; } foreach (Instruction inst_original in bb.Instructions) { InstructionType inst = export.Instruction.Append(); FillData(inst, inst_original); } }
public BasicBlock(Address begin, Address end, BasicBlockType type, BinaryImage image) { if (begin.Segment != end.Segment) { throw new ArgumentException("Basic block must be on the same segment."); } this.location = begin; this.length = end.Offset - begin.Offset; this.type = type; this.features = CodeFeaturesHelper.GetFeatures(GetInstructions(image)); }
private static void FillData(FunctionType export, Function function) { export.CalledFrom.EnumerationValue = (CalledFromType.EnumValues)function.calledFrom; export.GlobalID.Value = function.globalID; export.ID.Value = function.ID; List <string> input_vars_id = new List <string>(); List <string> output_vars_id = new List <string>(); function.LocalVariables.FindAll(x => x.kind == Variable.Kind.Input).ForEach(x => input_vars_id.Add(x.ID)); function.LocalVariables.FindAll(x => x.kind == Variable.Kind.Output).ForEach(x => output_vars_id.Add(x.ID)); if (input_vars_id.Count > 0) { export.RefInputVars.Value = string.Join(" ", input_vars_id.ToArray()); } if (output_vars_id.Count > 0) { export.RefOutputVars.Value = string.Join(" ", output_vars_id.ToArray()); } // Exporting local variables if (function.LocalVariables.Count > 0) { export.Local.Append(); } foreach (Variable var_orig in function.LocalVariables) { VariableType var = export.Local.First.Variable.Append(); FillData(var, var_orig); } // Exporting basic blocks foreach (BasicBlock bb_orig in function.BasicBlocks) { BasicBlockType bb = export.BasicBlock.Append(); FillData(bb, bb_orig); } }
internal BasicBlock(int index, BasicBlockType type, Instruction instruction) : this(index, instruction) { Type = type; OriginalIndex = ++_next_index; }
/// <summary> /// Gets the image associated with the segment specified by its id. /// </summary> /// <param name="segmentId">Id of the segment to resolve.</param> /// <returns>The image associated with the given segment, or null if /// the segment id is invalid.</returns> //protected abstract ImageChunk ResolveSegment(int segmentId); #region Flow Analysis Methods /// <summary> /// Analyzes a contiguous sequence of instructions that form a basic /// block. A basic block terminates as soon as any of the following /// conditions is true: /// - An analysis error occurs /// - An block terminating instructions: RET, RETF, IRET, HLT. /// - A b/c/j instruction: Jcc, JMP, JMPF, LOOPcc. /// </summary> /// <param name="start">Address to begin analysis.</param> /// <param name="xrefs">Collection to add xrefs to.</param> /// <returns> /// A new BasicBlock if one was created during the analysis. /// If no new BasicBlocks are created, or if an existing block was /// split into two, returns null. /// </returns> // TODO: should be roll-back the entire basic block if we // encounters an error on our way? maybe not. protected virtual BasicBlock AnalyzeBasicBlock(XRef start, ICollection <XRef> xrefs) { Address ip = start.Target; // instruction pointer if (!image.IsAddressValid(ip)) { AddError(ip, ErrorCode.OutOfImage, "XRef target is outside of the image (referred from {0})", start.Source); return(null); } // Check if the entry address is already analyzed. ByteAttribute b = image[ip]; if (b.Type != ByteType.Unknown) { // Fail if we ran into data or padding while expecting code. if (b.Type != ByteType.Code) { AddError(ip, ErrorCode.RanIntoData, "XRef target is in the middle of data (referred from {0})", start.Source); return(null); } // Now the byte was previously analyzed as code. We must have // already created a basic block that contains this byte. BasicBlock block = BasicBlocks.Find(ip); System.Diagnostics.Debug.Assert(block != null); // If the existing block starts at this address, we're done. if (block.Location == ip) { return(null); } // TBD: recover the following in some way... #if false if (image[b.BasicBlock.StartAddress].Address.Segment != pos.Segment) { AddError(pos, ErrorCategory.Error, "Ran into the middle of a block [{0},{1}) from another segment " + "when processing block {2} referred from {3}", b.BasicBlock.StartAddress, b.BasicBlock.EndAddress, start.Target, start.Source); return(null); } #endif // Now split the existing basic block into two. This requires // that the cut-off point is at instruction boundary. if (!b.IsLeadByte) { AddError(ip, ErrorCode.RanIntoCode, "XRef target is in the middle of an instruction (referred from {0})", start.Source); return(null); } BasicBlock[] subBlocks = BasicBlocks.SplitBasicBlock(block, ip, image); // Create a xref from the previous block to this block. XRef xref = CreateFallThroughXRef(GetLastInstructionInBasicBlock(subBlocks[0]), ip); xrefs.Add(xref); return(null); } // TODO: Move the above into a separate procedure. // Analyze each instruction in sequence until we encounter // analyzed code, flow instruction, or an error condition. BasicBlockType blockType = BasicBlockType.Unknown; while (true) { // Decode an instruction at this location. Address instructionStart = ip; Instruction insn = CreateInstruction(ip, start); if (insn == null) { AddError(ip, ErrorCode.BrokenBasicBlock, "Basic block ended prematurally because of invalid instruction."); blockType = BasicBlockType.Broken; break; } Address instructionEnd = ip + insn.EncodedLength; // Advance the instruction pointer. ip = instructionEnd; // Determine whether this instruction affects control flow. XRefType flowType = GetFlowInstructionType(insn.Operation); if (flowType != XRefType.None) { // Creates an active cross reference if necessary. if (NeedsActiveXRef(flowType)) { XRef xref = CreateFlowXRef(flowType, instructionStart, insn); if (xref != null) { xrefs.Add(xref); } } // Creates a fall-through cross reference if necessary. if (CanFallThrough(flowType)) { XRef xref = CreateFallThroughXRef(instructionStart, instructionEnd); xrefs.Add(xref); } // Terminate the block. blockType = GetBasicBlockType(flowType); break; } // If the new location is already analyzed as code, create a // control-flow edge from the previous block to the existing // block, and we are done. if (!image.IsAddressValid(ip)) { blockType = BasicBlockType.Broken; break; } if (image[ip].Type == ByteType.Code) { System.Diagnostics.Debug.Assert(image[ip].IsLeadByte); XRef xref = CreateFallThroughXRef(instructionStart, instructionEnd); xrefs.Add(xref); blockType = BasicBlockType.FallThrough; break; } } // Create a basic block unless we failed on the first instruction. if (ip.Offset > start.Target.Offset) { BasicBlock block = new BasicBlock(start.Target, ip, blockType, image); BasicBlocks.Add(block); } return(null); }
//Constructors public BasicBlock(BasicBlockType bb, Function func) { _ID = new IDManager(bb.ID.Value); parent = func; PolyRequired = bb.PolyRequired.Exists() ? bb.PolyRequired.Value : false; if (bb.Predecessors.Exists()) { foreach (string pid in bb.Predecessors.Value.Split(' ')) { RefPredecessors.Add(pid); } } if (bb.Successors.Exists()) { foreach (string sid in bb.Successors.Value.Split(' ')) { RefSuccessors.Add(sid); } } // Adding instructions to basic block foreach (InstructionType instr in bb.Instruction) { Instructions.Add(new Instruction(instr, this)); } // Trying to link real successors to this basic block switch (RefSuccessors.Count) { case 1: if (parent.BasicBlocks.ConvertAll(y => y.ID).Contains(RefSuccessors[0])) { Successors.Add(parent.BasicBlocks.Find(y => y.ID == RefSuccessors[0])); RefSuccessors.Clear(); } break; case 2: if (parent.BasicBlocks.ConvertAll(y => y.ID).Contains(RefSuccessors[0])) { Successors.Insert(0, parent.BasicBlocks.Find(y => y.ID == RefSuccessors[0])); } else if (parent.BasicBlocks.ConvertAll(y => y.ID).Contains(RefSuccessors[1])) { Successors.Add(parent.BasicBlocks.Find(y => y.ID == RefSuccessors[1])); } if (Successors.Count == 2) { RefSuccessors.Clear(); } break; default: break; } // Trying to link real predecessors to this basic block if (RefPredecessors.Count() > 0) { RefPredecessors.ForEach(x => { parent.BasicBlocks.ForEach(y => { if (y.ID == x) { Predecessors.Add(y); } }); }); } Predecessors.ForEach(x => RefPredecessors.Remove(x.ID)); // Trying to link this (new) basic block as predecessor/successor to other basic blocks of the function foreach (BasicBlock block in parent.BasicBlocks) { if (block.RefPredecessors.Contains(ID)) { block.Predecessors.Add(this); block.RefPredecessors.Remove(ID); } if (block.RefSuccessors.Contains(ID)) { switch (block.RefSuccessors.Count) { case 1: block.Successors.Add(this); block.RefSuccessors.Clear(); break; case 2: if (block.RefSuccessors[0] == ID) { block.Successors.Insert(0, this); } else { block.Successors.Add(this); } if (block.Successors.Count == 2) { block.RefSuccessors.Clear(); } break; default: break; } } } }
public BasicBlock(Guid id, BasicBlockType type, int lineNumber) { ID = id; Type = type; LineNumber = lineNumber; }