private ICollection <DisasmInstruction> UpdateCache(ulong address, int nInstructions, DisasmInstruction[] instructions) { ICollection <DisasmInstruction> ret = null; if (instructions != null && instructions.Length > 0) { DisassemblyBlock block = new DisassemblyBlock(instructions); lock (_disassemlyCache) { // push to the cache DeleteRangeFromCache(block); // removes any entry with the same key if (_disassemlyCache.Count >= cacheSize) { long max = 0; int toDelete = -1; for (int i = 0; i < _disassemlyCache.Count; ++i) { var e = _disassemlyCache.ElementAt(i); if (e.Value.Touch > max) { max = e.Value.Touch; toDelete = i; } } Debug.Assert(toDelete >= 0, "Failed to flush from the cache"); _disassemlyCache.RemoveAt(toDelete); } _disassemlyCache.Add(block.Address, block); } var kv = block.TryFetch(address, nInstructions, out ret); } return(ret); }
// /// <summary> /// Fetch disassembly for a range of instructions. May return more instructions than asked for. /// </summary> /// <param name="address">Beginning address of an instruction to use as a starting point for disassembly.</param> /// <param name="nInstructions">Number of instructions to disassemble. Negative values indicate disassembly backwards from "address".</param> /// <returns></returns> public async Task<IEnumerable<DisasmInstruction>> FetchInstructions(ulong address, int nInstructions) { IEnumerable<DisasmInstruction> ret = null; lock (_disassemlyCache) { // check the cache var kv = _disassemlyCache.FirstOrDefault((p) => p.Value.TryFetch(address, nInstructions, out ret)); if (kv.Value != null) return ret; } ulong endAddress; ulong startAddress; if (nInstructions >= 0) { startAddress = address; endAddress = startAddress + (ulong)(_process.MaxInstructionSize * nInstructions); } else { endAddress = address; startAddress = endAddress - (uint)(_process.MaxInstructionSize * -nInstructions); endAddress++; // make sure to fetch an instruction covering the original start address } DisasmInstruction[] instructions = await Disassemble(_process, startAddress, endAddress); if (instructions != null && instructions.Length > 0 && nInstructions < 0) { instructions = await VerifyDisassembly(instructions, startAddress, address); } if (instructions != null && instructions.Length > 0) { DisassemblyBlock block = new DisassemblyBlock(instructions); lock (_disassemlyCache) { // push to the cache DeleteRangeFromCache(block); // removes any entry with the same key if (_disassemlyCache.Count >= cacheSize) { ulong max = 0; int toDelete = -1; for (int i = 0; i < _disassemlyCache.Count; ++i) { var e = _disassemlyCache.ElementAt(i); if (e.Value.Touch > max) { max = e.Value.Touch; toDelete = i; } } Debug.Assert(toDelete >= 0, "Failed to flush from the cache"); _disassemlyCache.RemoveAt(toDelete); } _disassemlyCache.Add(block.Address, block); } var kv = block.TryFetch(address, nInstructions, out ret); } return ret; }
// /// <summary> /// Fetch disassembly for a range of instructions. May return more instructions than asked for. /// </summary> /// <param name="address">Beginning address of an instruction to use as a starting point for disassembly.</param> /// <param name="nInstructions">Number of instructions to disassemble. Negative values indicate disassembly backwards from "address".</param> /// <returns></returns> public async Task <IEnumerable <DisasmInstruction> > FetchInstructions(ulong address, int nInstructions) { IEnumerable <DisasmInstruction> ret = null; lock (_disassemlyCache) { // check the cache var kv = _disassemlyCache.FirstOrDefault((p) => p.Value.TryFetch(address, nInstructions, out ret)); if (kv.Value != null) { return(ret); } } ulong endAddress; ulong startAddress; if (nInstructions >= 0) { startAddress = address; endAddress = startAddress + (ulong)(_process.MaxInstructionSize * nInstructions); } else { endAddress = address; startAddress = endAddress - (uint)(_process.MaxInstructionSize * -nInstructions); endAddress++; // make sure to fetch an instruction covering the original start address } DisasmInstruction[] instructions = await Disassemble(_process, startAddress, endAddress); if (instructions != null && instructions.Length > 0 && nInstructions < 0) { instructions = await VerifyDisassembly(instructions, startAddress, address); } if (instructions != null && instructions.Length > 0) { DisassemblyBlock block = new DisassemblyBlock(instructions); lock (_disassemlyCache) { // push to the cache DeleteRangeFromCache(block); // removes any entry with the same key if (_disassemlyCache.Count >= cacheSize) { long max = 0; int toDelete = -1; for (int i = 0; i < _disassemlyCache.Count; ++i) { var e = _disassemlyCache.ElementAt(i); if (e.Value.Touch > max) { max = e.Value.Touch; toDelete = i; } } Debug.Assert(toDelete >= 0, "Failed to flush from the cache"); _disassemlyCache.RemoveAt(toDelete); } _disassemlyCache.Add(block.Address, block); } var kv = block.TryFetch(address, nInstructions, out ret); } return(ret); }