Beispiel #1
0
        // 
        /// <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;
        }
Beispiel #2
0
 private void DeleteRangeFromCache(DisassemblyBlock block)
 {
     for (int i = 0; i < _disassemlyCache.Count; ++i)
     {
         DisassemblyBlock elem = _disassemlyCache.ElementAt(i).Value;
         if (block.Contains(elem.Address, elem.Count))
         {
             _disassemlyCache.RemoveAt(i);
             break;
         }
     }
 }
Beispiel #3
0
        //
        /// <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);
        }