/// <summary> /// Marks a contiguous range of bytes as the given type, and marks /// the first byte in this range as a lead byte. The address range /// must be on the same segment. /// </summary> public void UpdateByteType(Address startAddress, Address endAddress, ByteType type) { if (startAddress.Segment != endAddress.Segment) { throw new ArgumentException("startAddress and endAddress must be on the same segment."); } ArraySegment <ByteAttribute> attrs = attributes.GetAttributes( startAddress, endAddress.Offset - startAddress.Offset); for (int i = 0; i < attrs.Count; i++) { if (attrs.Array[attrs.Offset + i].Type != ByteType.Unknown) { // Undo for (int j = i - 1; j >= 0; j--) { attrs.Array[attrs.Offset + j] = ByteAttribute.Empty; } throw new ArgumentException("[start, end) overlaps with analyzed bytes."); } ByteAttribute attr = new ByteAttribute { Type = type, IsLeadByte = (i == 0), }; attrs.Array[attrs.Offset + i] = attr; } OnBytesAnalyzed(startAddress, endAddress); }
protected override void GenerateProcedures() { // Enumerate the defined names, and assign names to the procedures. foreach (ObjectModule module in library.Modules) { foreach (DefinedSymbol symbol in module.DefinedNames) { if (symbol.BaseSegment != null) { Address address = new Address(symbol.BaseSegment.Id, (int)symbol.Offset); if (image.IsAddressValid(address)) { ByteAttribute b = image[address]; if (b.Type == ByteType.Code && b.IsLeadByte) { Procedure proc = Procedures.Find(address); if (proc == null) { proc = CreateProcedure(address); Procedures.Add(proc); } proc.Name = symbol.Name; } } } } } }
public void SetAt(Address address, ByteAttribute attribute) { if (!image.IsAddressValid(address)) { throw new ArgumentOutOfRangeException("address"); } for (int i = attrs.Count; i < image.Segments.Count; i++) { attrs.Add(new ByteAttribute[image.Segments[i].OffsetBounds.End]); } attrs[address.Segment][address.Offset] = attribute; }
public void SetAt(Address address, ByteAttribute attribute) { if (!image.IsAddressValid(address)) throw new ArgumentOutOfRangeException("address"); for (int i = attrs.Count; i < image.Segments.Count; i++) { attrs.Add(new ByteAttribute[image.Segments[i].OffsetBounds.End]); } attrs[address.Segment][address.Offset] = attribute; }
/// <summary> /// Marks a contiguous range of bytes as the given type, and marks /// the first byte in this range as a lead byte. The address range /// must be on the same segment. /// </summary> public void UpdateByteType(Address startAddress, Address endAddress, ByteType type) { if (startAddress.Segment != endAddress.Segment) throw new ArgumentException("startAddress and endAddress must be on the same segment."); ArraySegment<ByteAttribute> attrs = attributes.GetAttributes( startAddress, endAddress.Offset - startAddress.Offset); for (int i = 0; i < attrs.Count; i++) { if (attrs.Array[attrs.Offset + i].Type != ByteType.Unknown) { // Undo for (int j = i - 1; j >= 0; j--) { attrs.Array[attrs.Offset + j] = ByteAttribute.Empty; } throw new ArgumentException("[start, end) overlaps with analyzed bytes."); } ByteAttribute attr = new ByteAttribute { Type = type, IsLeadByte = (i == 0), }; attrs.Array[attrs.Offset + i] = attr; } OnBytesAnalyzed(startAddress, endAddress); }
/// <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); }