private void lvListing_SelectedIndexChanged(object sender, EventArgs e) { txtStatus.Text = ""; if (lvListing.SelectedIndices.Count == 0) { return; } int i = lvListing.SelectedIndices[0]; activeRowIndex = i; // Display brief description of instruction. ListingRow row = viewModel.Rows[viewportBeginIndex + i]; if (row is CodeListingRow) { Operation op = ((CodeListingRow)row).Instruction.Operation; string desc = op.GetDescription(); if (desc != null) { txtStatus.Text = string.Format("{0} - {1}", op.ToString().ToUpperInvariant(), desc); } } Pointer address = row.Location; ByteProperties b = document.Image[address]; if (b == null) // TBD: we should also do something for an unanalyzed byte. { return; } // Update the current location. document.Navigator.SetLocation(row.Location, this, LocationChangeType.Minor); // this.ActiveSegment = address.Segment; }
private BasicBlock AnalyzeBasicBlock(XRef start, ICollection <XRef> xrefs) { Pointer pos = start.Target; // Check if we are running into the middle of code or data. This // can only happen when we process the first instruction in the // block. if (image[pos].Type != ByteType.Unknown && !image[pos].IsLeadByte) { AddError(pos, ErrorCategory.Error, "XRef target is in the middle of code/data (referred from {0})", start.Source); return(null); } // Check if this location is already analyzed as code. if (image[pos].Type == ByteType.Code) { ByteProperties b = image[pos]; // Now we are already covered by a basic block. If the // basic block *starts* from this address, do nothing. // Otherwise, split the basic block into two. if (b.BasicBlock.StartAddress == pos.LinearAddress) { return(null); } else { 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); } BasicBlock newBlock = b.BasicBlock.Split(pos.LinearAddress); return(null); // newBlock; } } // Analyze each instruction in sequence until we encounter // analyzed code, flow instruction, or an error condition. while (true) { // Decode an instruction at this location. Pointer insnPos = pos; Instruction insn; try { insn = image.DecodeInstruction(pos); } catch (Exception ex) { AddError(pos, ErrorCategory.Error, "Bad instruction: {0}", ex.Message); break; } // Create a code piece for this instruction. if (!image.CheckByteType(pos, pos + insn.EncodedLength, ByteType.Unknown)) { AddError(pos, "Ran into the middle of code when processing block {0} referred from {1}", start.Target, start.Source); break; } // Advance the byte pointer. Note: the IP may wrap around 0xFFFF // if pos.off + count > 0xFFFF. This is probably not intended. try { Piece piece = image.CreatePiece(pos, pos + insn.EncodedLength, ByteType.Code); pos += insn.EncodedLength; } catch (AddressWrappedException) { AddError(pos, ErrorCategory.Error, "CS:IP wrapped when processing block {1} referred from {2}", start.Target, start.Source); break; } // Check if this instruction terminates the block. if (insn.Operation == Operation.RET || insn.Operation == Operation.RETF || insn.Operation == Operation.HLT) { break; } // Analyze BCJ (branch, jump, call) instructions. Such an // instruction will create a cross reference. XRef xref = AnalyzeFlowInstruction(insnPos, insn); if (xref != null) { xrefs.Add(xref); // If the instruction is a conditional jump, add xref to // the 'no-jump' branch. // TODO: adding a no-jump xref causes confusion when we // browse xrefs in the disassembly listing window. Is it // truely necessary to add these xrefs? if (xref.Type == XRefType.ConditionalJump) { xrefs.Add(new XRef( type: XRefType.ConditionalJump, source: insnPos, target: pos )); } // Finish basic block unless this is a CALL instruction. if (xref.Type == XRefType.ConditionalJump || xref.Type == XRefType.NearJump || xref.Type == XRefType.FarJump || xref.Type == XRefType.NearIndexedJump) { 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[pos].Type == ByteType.Code) { System.Diagnostics.Debug.Assert(image[pos].IsLeadByte); break; } } // Create a basic block unless we failed on the first instruction. if (pos.LinearAddress > start.Target.LinearAddress) { return(image.CreateBasicBlock(start.Target.LinearAddress, pos.LinearAddress)); } else { return(null); } }
private static bool IsLeadByteOfData(ByteProperties b) { return(b.Type == ByteType.Data && b.IsLeadByte); }
public ListingViewModel(BinaryImage image) { this.image = image; // Make a dictionary that maps a location to the error at that location. // TODO: there may be multiple errors at a single location. Dictionary <LinearPointer, Error> errorMap = new Dictionary <LinearPointer, Error>(); foreach (Error error in image.Errors) { errorMap[error.Location.LinearAddress] = error; } // Display analyzed code and data. Pointer address = image.BaseAddress; for (var i = image.StartAddress; i < image.EndAddress;) { ByteProperties b = image[i]; if (IsLeadByteOfCode(b)) { if (b.BasicBlock != null && b.BasicBlock.StartAddress == i) { rows.Add(new LabelListingRow(0, b.BasicBlock)); } Instruction insn = image.DecodeInstruction(b.Address); rows.Add(new CodeListingRow(0, b.Address, insn, image.GetBytes(i, insn.EncodedLength))); address = b.Address + insn.EncodedLength; i += insn.EncodedLength; } else if (IsLeadByteOfData(b)) { var j = i + 1; while (j < image.EndAddress && image[j].Type == ByteType.Data && !image[j].IsLeadByte) { j++; } rows.Add(new DataListingRow(0, b.Address, image.GetBytes(i, j - i))); address = b.Address + (j - i); i = j; } else { if (errorMap.ContainsKey(i)) { // rows.Add(new ErrorListingRow(errorMap[i])); } var j = i + 1; while (j < image.EndAddress && !IsLeadByteOfCode(image[j]) && !IsLeadByteOfData(image[j])) { j++; } rows.Add(new BlankListingRow(0, address, image.GetBytes(i, j - i))); try { address += (j - i); } catch (AddressWrappedException) { address = Pointer.Invalid; } i = j; } } // Create a sorted array containing the address of each row. rowAddresses = new LinearPointer[rows.Count]; for (int i = 0; i < rows.Count; i++) { rowAddresses[i] = rows[i].Location.LinearAddress; } // Create a ProcedureItem view object for each non-empty // procedure. // TODO: display an error for empty procedures. foreach (Procedure proc in image.Procedures) { if (proc.IsEmpty) { continue; } ProcedureItem item = new ProcedureItem(proc); //var range = proc.Bounds; //item.FirstRowIndex = FindRowIndex(range.Begin); //item.LastRowIndex = FindRowIndex(range.End - 1); // TBD: need to check broken instruction conditions // as well as leading/trailing unanalyzed bytes. procItems.Add(item); } // Create segment items. foreach (Segment segment in image.Segments) { segmentItems.Add(new SegmentItem(segment)); } }
private static bool IsLeadByteOfCode(ByteProperties b) { return(b.Type == ByteType.Code && b.IsLeadByte); }