public void Add(Address address, Instruction instruction) { if (!image.IsAddressValid(address)) { throw new ArgumentOutOfRangeException("address"); } if (instruction == null) { throw new ArgumentNullException("instruction"); } this.instructions.Add(address, instruction); }
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> /// Fills the Target of an IndexedJump xref heuristically by plugging /// in the jump target stored in DataLocation and performing various /// sanity checks. /// </summary> /// <param name="entry">A xref of type IndexedJump whose Target field /// is Invalid.</param> /// <param name="xrefs">Collection to add a new dynamic IndexedJump /// xref to, if any.</param> /// <returns>The updated xref, or null if the jump table ends.</returns> private XRef ProcessJumpTableEntry(XRef entry, ICollection <XRef> xrefs) { #if true return(null); #else System.Diagnostics.Debug.Assert( entry.Type == XRefType.NearIndexedJump && entry.Target == LogicalAddress.Invalid, "Entry must be NearIndexedJump with unknown target"); // Verify that the location that supposedly stores the jump table // entry is not analyzed as anything else. If it is, it indicates // that the jump table ends here. LinearPointer b = entry.DataLocation.LinearAddress; if (image[b].Type != ByteType.Unknown || image[b + 1].Type != ByteType.Unknown) { return(null); } // If the data location looks like in another segment, stop. if (image.LargestSegmentThatStartsBefore(b) > entry.Source.Segment) { return(null); } // TBD: it's always a problem if CS:IP wraps. We need a more // general way to detect and fix it. For this particular case, // we need to check that the jump target is within the space // of this segment. if (entry.DataLocation.Offset >= 0xFFFE) { AddError(entry.DataLocation, ErrorCategory.Error, "Jump table is too big (jumped from {0}).", entry.Source); return(null); } // Find the target address of the jump table entry. ushort jumpOffset = image.GetUInt16(b); Pointer jumpTarget = new Pointer(entry.Source.Segment, jumpOffset); // Check that the target address looks valid. If it doesn't, it // probably indicates that the jump table ends here. if (!image.IsAddressValid(jumpTarget.LinearAddress)) { return(null); } // If the jump target is outside the range of the current segment // but inside the range of a later segment, it likely indicates // that the jump table ends here. // TBD: this heuristic is kind of a hack... we should do better. #if true if (image.LargestSegmentThatStartsBefore(jumpTarget.LinearAddress) > entry.Source.Segment) { return(null); } #endif // BUG: We really do need to check that the destination // is valid. If not, we should stop immediately. if (!(image[jumpTarget].Type == ByteType.Unknown || image[jumpTarget].Type == ByteType.Code && image[jumpTarget].IsLeadByte)) { return(null); } // ... // Mark DataLocation as data and add it to the owning procedure's // byte range. Piece piece = image.CreatePiece( entry.DataLocation, entry.DataLocation + 2, ByteType.Data); Procedure proc = image[entry.Source].Procedure; proc.AddDataBlock(piece.StartAddress, piece.EndAddress); // Add a dynamic xref from the JMP instruction to the next jump // table entry. xrefs.Add(new XRef( type: XRefType.NearIndexedJump, source: entry.Source, target: Pointer.Invalid, dataLocation: entry.DataLocation + 2 )); // Return the updated xref with Target field filled. return(new XRef( type: XRefType.NearIndexedJump, source: entry.Source, target: jumpTarget, dataLocation: entry.DataLocation )); #endif }