Ejemplo n.º 1
0
        /*
         * Main goals:
         * 1. No copies, ever.  States are deposited directly to, and read directly from, one giant ring buffer.
         *      As a consequence, there is no multi-threading because there is nothing to thread.
         * 2. Support for arbitrary and changeable state sizes.  Frequency is calculated dynamically.
         * 3. No delta compression.  Keep it simple.  If there are cores that benefit heavily from delta compression, we should
         *      maintain a separate rewinder alongside this one that is customized for those cores.
         */
        public ZwinderBuffer(IRewindSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentException("ZwinderBuffer's settings cannot be null.");
            }

            long targetSize = settings.BufferSize * 1024 * 1024;

            if (settings.TargetFrameLength < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(settings.TargetFrameLength));
            }

            Size              = 1L << (int)Math.Floor(Math.Log(targetSize, 2));
            _sizeMask         = Size - 1;
            _backingStoreType = settings.BackingStore;
            switch (settings.BackingStore)
            {
            case IRewindSettings.BackingStoreType.Memory:
            {
                var buffer = new MemoryBlock((ulong)Size);
                buffer.Protect(buffer.Start, buffer.Size, MemoryBlock.Protection.RW);
                _disposables.Add(buffer);
                _backingStore = new MemoryViewStream(true, true, (long)buffer.Start, (long)buffer.Size);
                _disposables.Add(_backingStore);
                break;
            }

            case IRewindSettings.BackingStoreType.TempFile:
            {
                var filename   = TempFileManager.GetTempFilename("ZwinderBuffer");
                var filestream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
                filestream.SetLength(Size);
                _backingStore = filestream;
                _disposables.Add(filestream);
                break;
            }

            default:
                throw new ArgumentException("Unsupported store type for ZwinderBuffer.");
            }
            if (settings.UseFixedRewindInterval)
            {
                _fixedRewindInterval  = true;
                _targetRewindInterval = settings.TargetRewindInterval;
            }
            else
            {
                _fixedRewindInterval = false;
                _targetFrameLength   = settings.TargetFrameLength;
            }
            _allowOutOfOrderStates = settings.AllowOutOfOrderStates;
            _states         = new StateInfo[STATEMASK + 1];
            _useCompression = settings.UseCompression;
        }
Ejemplo n.º 2
0
        /*
         * Main goals:
         * 1. No copies, ever.  States are deposited directly to, and read directly from, one giant ring buffer.
         *      As a consequence, there is no multi-threading because there is nothing to thread.
         * 2. Support for arbitrary and changeable state sizes.  Frequency is calculated dynamically.
         * 3. No delta compression.  Keep it simple.  If there are cores that benefit heavily from delta compression, we should
         *      maintain a separate rewinder alongside this one that is customized for those cores.
         */
        public ZwinderBuffer(IRewindSettings settings)
        {
            long targetSize = settings.BufferSize * 1024 * 1024;

            if (settings.TargetFrameLength < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(settings.TargetFrameLength));
            }

            Size      = 1L << (int)Math.Floor(Math.Log(targetSize, 2));
            _sizeMask = Size - 1;
            _buffer   = new MemoryBlock((ulong)Size);
            _buffer.Protect(_buffer.Start, _buffer.Size, MemoryBlock.Protection.RW);
            _targetFrameLength = settings.TargetFrameLength;
            _states            = new StateInfo[STATEMASK + 1];
            _useCompression    = settings.UseCompression;
        }
Ejemplo n.º 3
0
        public ElfRunner(string filename, long heapsize, long sealedheapsize, long invisibleheapsize)
        {
            using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                _elfhash = WaterboxUtils.Hash(fs);
            }

            // todo: hack up this baby to take Streams
            _elf = ELFReader.Load <long>(filename);

            var loadsegs = _elf.Segments.Where(s => s.Type == SegmentType.Load);

            long orig_start = loadsegs.Min(s => s.Address);

            orig_start &= ~(Environment.SystemPageSize - 1);
            long orig_end = loadsegs.Max(s => s.Address + s.Size);

            if (HasRelocations())
            {
                _base       = new MemoryBlock((ulong)(orig_end - orig_start));
                _loadoffset = (long)_base.Start - orig_start;
                Initialize(0);
            }
            else
            {
                Initialize((ulong)orig_start);
                _base       = new MemoryBlock((ulong)orig_start, (ulong)(orig_end - orig_start));
                _loadoffset = 0;
                Enter();
            }

            try
            {
                _disposeList.Add(_base);
                AddMemoryBlock(_base, "elf");
                _base.Activate();
                _base.Protect(_base.Start, _base.Size, MemoryBlock.Protection.RW);

                foreach (var seg in loadsegs)
                {
                    var data = seg.GetContents();
                    Marshal.Copy(data, 0, Z.SS(seg.Address + _loadoffset), data.Length);
                }
                RegisterSymbols();
                ProcessRelocations();

                _base.Protect(_base.Start, _base.Size, MemoryBlock.Protection.R);

                foreach (var sec in _elf.Sections.Where(s => (s.Flags & SectionFlags.Allocatable) != 0))
                {
                    if ((sec.Flags & SectionFlags.Executable) != 0)
                    {
                        _base.Protect((ulong)(sec.LoadAddress + _loadoffset), (ulong)sec.Size, MemoryBlock.Protection.RX);
                    }
                    else if ((sec.Flags & SectionFlags.Writable) != 0)
                    {
                        _base.Protect((ulong)(sec.LoadAddress + _loadoffset), (ulong)sec.Size, MemoryBlock.Protection.RW);
                    }
                }

                ulong end = _base.End;

                if (heapsize > 0)
                {
                    _heap = new Heap(GetHeapStart(end), (ulong)heapsize, "sbrk-heap");
                    _heap.Memory.Activate();
                    end = _heap.Memory.End;
                    _disposeList.Add(_heap);
                    AddMemoryBlock(_heap.Memory, "sbrk - heap");
                }

                if (sealedheapsize > 0)
                {
                    _sealedheap = new Heap(GetHeapStart(end), (ulong)sealedheapsize, "sealed-heap");
                    _sealedheap.Memory.Activate();
                    end = _sealedheap.Memory.End;
                    _disposeList.Add(_sealedheap);
                    AddMemoryBlock(_sealedheap.Memory, "sealed-heap");
                }

                if (invisibleheapsize > 0)
                {
                    _invisibleheap = new Heap(GetHeapStart(end), (ulong)invisibleheapsize, "invisible-heap");
                    _invisibleheap.Memory.Activate();
                    end = _invisibleheap.Memory.End;
                    _disposeList.Add(_invisibleheap);
                    AddMemoryBlock(_invisibleheap.Memory, "invisible-heap");
                }

                ConnectAllClibPatches();
                Console.WriteLine("Loaded {0}@{1:X16}", filename, _base.Start);
                foreach (var sec in _elf.Sections.Where(s => s.LoadAddress != 0))
                {
                    Console.WriteLine("  {0}@{1:X16}, size {2}", sec.Name.PadLeft(20), sec.LoadAddress + _loadoffset, sec.Size.ToString().PadLeft(12));
                }

                PrintTopSavableSymbols();
            }
            catch
            {
                Dispose();
                throw;
            }
            finally
            {
                Exit();
            }
        }
Ejemplo n.º 4
0
        public PeWrapper(string moduleName, byte[] fileData, ulong destAddress)
        {
            ModuleName = moduleName;
            _pe        = new PeFile(fileData);
            Size       = _pe.ImageNtHeaders.OptionalHeader.SizeOfImage;
            Start      = destAddress;

            if (Size < _pe.ImageSectionHeaders.Max(s => (ulong)s.VirtualSize + s.VirtualAddress))
            {
                throw new InvalidOperationException("Image not Big Enough");
            }

            _fileHash = WaterboxUtils.Hash(fileData);

            foreach (var s in _pe.ImageSectionHeaders)
            {
                ulong start  = Start + s.VirtualAddress;
                ulong length = s.VirtualSize;

                MemoryBlock.Protection prot;
                var r = (s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_MEM_READ) != 0;
                var w = (s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_MEM_WRITE) != 0;
                var x = (s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_MEM_EXECUTE) != 0;
                if (w && x)
                {
                    throw new InvalidOperationException("Write and Execute not allowed");
                }

                prot = x ? MemoryBlock.Protection.RX : w ? MemoryBlock.Protection.RW : MemoryBlock.Protection.R;

                var section = new Section
                {
                    // chop off possible null padding from name
                    Name = Encoding.ASCII.GetString(s.Name, 0,
                                                    (s.Name.Select((v, i) => new { v, i }).FirstOrDefault(a => a.v == 0) ?? new { v = (byte)0, i = s.Name.Length }).i),
                    Start     = start,
                    Size      = length,
                    SavedSize = WaterboxUtils.AlignUp(length),
                    R         = r,
                    W         = w,
                    X         = x,
                    Prot      = prot,
                    DiskStart = s.PointerToRawData,
                    DiskSize  = s.SizeOfRawData
                };

                _sections.Add(section);
                _sectionsByName.Add(section.Name, section);
            }
            _sectionsByName.TryGetValue(".idata", out _imports);
            _sectionsByName.TryGetValue(".sealed", out _sealed);
            _sectionsByName.TryGetValue(".invis", out _invisible);

            // OK, NOW MOUNT

            LoadOffset = (long)Start - (long)_pe.ImageNtHeaders.OptionalHeader.ImageBase;
            Memory     = new MemoryBlock(Start, Size);
            Memory.Activate();
            Memory.Protect(Start, Size, MemoryBlock.Protection.RW);

            // copy headers
            Marshal.Copy(fileData, 0, Z.US(Start), (int)_pe.ImageNtHeaders.OptionalHeader.SizeOfHeaders);

            // copy sections
            foreach (var s in _sections)
            {
                ulong datalength = Math.Min(s.Size, s.DiskSize);
                Marshal.Copy(fileData, (int)s.DiskStart, Z.US(s.Start), (int)datalength);
                WaterboxUtils.ZeroMemory(Z.US(s.Start + datalength), (long)(s.SavedSize - datalength));
            }

            // apply relocations
            var n32 = 0;
            var n64 = 0;

            foreach (var rel in _pe.ImageRelocationDirectory)
            {
                foreach (var to in rel.TypeOffsets)
                {
                    ulong address = Start + rel.VirtualAddress + to.Offset;

                    switch (to.Type)
                    {
                    // there are many other types of relocation specified,
                    // but the only that are used is 0 (does nothing), 3 (32 bit standard), 10 (64 bit standard)

                    case 3:                             // IMAGE_REL_BASED_HIGHLOW
                    {
                        byte[] tmp = new byte[4];
                        Marshal.Copy(Z.US(address), tmp, 0, 4);
                        uint val = BitConverter.ToUInt32(tmp, 0);
                        tmp = BitConverter.GetBytes((uint)(val + LoadOffset));
                        Marshal.Copy(tmp, 0, Z.US(address), 4);
                        n32++;
                        break;
                    }

                    case 10:                             // IMAGE_REL_BASED_DIR64
                    {
                        byte[] tmp = new byte[8];
                        Marshal.Copy(Z.US(address), tmp, 0, 8);
                        long val = BitConverter.ToInt64(tmp, 0);
                        tmp = BitConverter.GetBytes(val + LoadOffset);
                        Marshal.Copy(tmp, 0, Z.US(address), 8);
                        n64++;
                        break;
                    }
                    }
                }
            }
            if (IntPtr.Size == 8 && n32 > 0)
            {
                // check mcmodel, etc
                throw new InvalidOperationException("32 bit relocations found in 64 bit dll!  This will fail.");
            }
            Console.WriteLine($"Processed {n32} 32 bit and {n64} 64 bit relocations");

            ProtectMemory();

            // publish exports
            EntryPoint = Z.US(Start + _pe.ImageNtHeaders.OptionalHeader.AddressOfEntryPoint);
            foreach (var export in _pe.ExportedFunctions)
            {
                if (export.Name != null)
                {
                    ExportsByName.Add(export.Name, Z.US(Start + export.Address));
                }
                ExportsByOrdinal.Add(export.Ordinal, Z.US(Start + export.Address));
            }

            // collect information about imports
            // NB: Hints are not the same as Ordinals
            foreach (var import in _pe.ImportedFunctions)
            {
                Dictionary <string, IntPtr> module;
                if (!ImportsByModule.TryGetValue(import.DLL, out module))
                {
                    module = new Dictionary <string, IntPtr>();
                    ImportsByModule.Add(import.DLL, module);
                }
                var dest = Start + import.Thunk;
                if (_imports == null || dest >= _imports.Start + _imports.Size || dest < _imports.Start)
                {
                    throw new InvalidOperationException("Import record outside of .idata!");
                }

                module.Add(import.Name, Z.US(dest));
            }

            Section midipix;

            if (_sectionsByName.TryGetValue(".midipix", out midipix))
            {
                var dataOffset = midipix.DiskStart;
                CtorList = Z.SS(BitConverter.ToInt64(fileData, (int)(dataOffset + 0x30)) + LoadOffset);
                DtorList = Z.SS(BitConverter.ToInt64(fileData, (int)(dataOffset + 0x38)) + LoadOffset);
            }

            Console.WriteLine($"Mounted `{ModuleName}` @{Start:x16}");
            foreach (var s in _sections.OrderBy(s => s.Start))
            {
                Console.WriteLine("  @{0:x16} {1}{2}{3} `{4}` {5} bytes",
                                  s.Start,
                                  s.R ? "R" : " ",
                                  s.W ? "W" : " ",
                                  s.X ? "X" : " ",
                                  s.Name,
                                  s.Size);
            }
            Console.WriteLine("GDB Symbol Load:");
            var symload = $"add-sym {ModuleName} {_sectionsByName[".text"].Start}";

            if (_sectionsByName.ContainsKey(".data"))
            {
                symload += $" -s .data {_sectionsByName[".data"].Start}";
            }
            if (_sectionsByName.ContainsKey(".bss"))
            {
                symload += $" -s .bss {_sectionsByName[".bss"].Start}";
            }
            Console.WriteLine(symload);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// load the PE into memory
        /// </summary>
        /// <param name="org">start address</param>
        private void Mount()
        {
            LoadOffset = (long)Start - (long)_pe.ImageNtHeaders.OptionalHeader.ImageBase;
            Memory     = new MemoryBlock(Start, Size);
            Memory.Activate();
            Memory.Protect(Start, Size, MemoryBlock.Protection.RW);

            // copy headers
            Marshal.Copy(_fileData, 0, Z.US(Start), (int)_pe.ImageNtHeaders.OptionalHeader.SizeOfHeaders);

            // copy sections
            foreach (var s in _sections)
            {
                ulong datalength = Math.Min(s.Size, s.DiskSize);
                Marshal.Copy(_fileData, (int)s.DiskStart, Z.US(s.Start), (int)datalength);
                WaterboxUtils.ZeroMemory(Z.US(s.Start + datalength), (long)(s.SavedSize - datalength));
            }

            // apply relocations
            var n32 = 0;
            var n64 = 0;

            foreach (var rel in _pe.ImageRelocationDirectory)
            {
                foreach (var to in rel.TypeOffsets)
                {
                    ulong address = Start + rel.VirtualAddress + to.Offset;

                    switch (to.Type)
                    {
                    // there are many other types of relocation specified,
                    // but the only that are used is 0 (does nothing), 3 (32 bit standard), 10 (64 bit standard)

                    case 3:                             // IMAGE_REL_BASED_HIGHLOW
                    {
                        byte[] tmp = new byte[4];
                        Marshal.Copy(Z.US(address), tmp, 0, 4);
                        uint val = BitConverter.ToUInt32(tmp, 0);
                        tmp = BitConverter.GetBytes((uint)(val + LoadOffset));
                        Marshal.Copy(tmp, 0, Z.US(address), 4);
                        n32++;
                        break;
                    }

                    case 10:                             // IMAGE_REL_BASED_DIR64
                    {
                        byte[] tmp = new byte[8];
                        Marshal.Copy(Z.US(address), tmp, 0, 8);
                        long val = BitConverter.ToInt64(tmp, 0);
                        tmp = BitConverter.GetBytes(val + LoadOffset);
                        Marshal.Copy(tmp, 0, Z.US(address), 8);
                        n64++;
                        break;
                    }
                    }
                }
            }
            if (IntPtr.Size == 8 && n32 > 0)
            {
                // check mcmodel, etc
                throw new InvalidOperationException("32 bit relocations found in 64 bit dll!  This will fail.");
            }
            Console.WriteLine($"Processed {n32} 32 bit and {n64} 64 bit relocations");

            ProtectMemory();

            // publish exports
            EntryPoint = Z.US(Start + _pe.ImageNtHeaders.OptionalHeader.AddressOfEntryPoint);
            foreach (var export in _pe.ExportedFunctions)
            {
                if (export.Name != null)
                {
                    ExportsByName.Add(export.Name, Z.US(Start + export.Address));
                }
                ExportsByOrdinal.Add(export.Ordinal, Z.US(Start + export.Address));
            }

            // collect information about imports
            // NB: Hints are not the same as Ordinals
            foreach (var import in _pe.ImportedFunctions)
            {
                Dictionary <string, IntPtr> module;
                if (!ImportsByModule.TryGetValue(import.DLL, out module))
                {
                    module = new Dictionary <string, IntPtr>();
                    ImportsByModule.Add(import.DLL, module);
                }
                var dest = Start + import.Thunk;
                if (_imports == null || dest >= _imports.Start + _imports.Size || dest < _imports.Start)
                {
                    throw new InvalidOperationException("Import record outside of .idata!");
                }

                module.Add(import.Name, Z.US(dest));
            }

            Section midipix;

            if (_sectionsByName.TryGetValue(".midipix", out midipix))
            {
                var dataOffset = midipix.DiskStart;
                CtorList = Z.SS(BitConverter.ToInt64(_fileData, (int)(dataOffset + 0x30)) + LoadOffset);
                DtorList = Z.SS(BitConverter.ToInt64(_fileData, (int)(dataOffset + 0x38)) + LoadOffset);
            }

            Console.WriteLine($"Mounted `{ModuleName}` @{Start:x16}");
            foreach (var s in _sections.OrderBy(s => s.Start))
            {
                Console.WriteLine("  @{0:x16} {1}{2}{3} `{4}` {5} bytes",
                                  s.Start,
                                  s.R ? "R" : " ",
                                  s.W ? "W" : " ",
                                  s.X ? "X" : " ",
                                  s.Name,
                                  s.Size);
            }
            Console.WriteLine("GDB Symbol Load:");
            var symload = $"add-sym {ModuleName} {_sectionsByName[".text"].Start}";

            if (_sectionsByName.ContainsKey(".data"))
            {
                symload += $" -s .data {_sectionsByName[".data"].Start}";
            }
            if (_sectionsByName.ContainsKey(".bss"))
            {
                symload += $" -s .bss {_sectionsByName[".bss"].Start}";
            }
            Console.WriteLine(symload);
        }