Example #1
0
        private void RegisterSymbols()
        {
            _symlist = ((ISymbolTable)_elf.GetSection(".symtab")).Entries
                       .Cast <SymbolEntry <long> >()
                       .ToList();

            // when there are duplicate names, don't register either in the dictionary
            _symdict = _symlist
                       .GroupBy(e => e.Name)
                       .Where(g => g.Count() == 1)
                       .ToDictionary(g => g.Key, g => g.First());
        }
Example #2
0
        /// <summary>
        /// This pulls info from the hypervisor areas regarding memory extents
        /// </summary>
        /// <param name="vtero"></param>
        /// <returns></returns>
        public override bool IsSupportedFormat(Vtero vtero)
        {
            long InfoCnt;
            long nr_vcpu, nr_pages = 0, page_size = 0, pfn_LAST, pfn_VAL;

            // use abstract implementation & scan for internal
            LogicalPhysMemDesc = ExtractMemDesc(vtero);

            if (Elf == null)
            {
                return(false);
            }

            using (var dstream = File.OpenRead(vtero.MemFile))
            {
                using (var ebin = new BinaryReader(dstream))
                {
                    ELFInfo = Elf.GetSection(".note.Xen"); // get note stuff and fill in da info
                    if (ELFInfo != null)
                    {
                        ebin.BaseStream.Position = ELFInfo.Offset;
                        InfoCnt = ebin.ReadInt64();
                        for (long l = 0; l < InfoCnt; l++)
                        {
                            var InfoType = ebin.ReadInt32();
                            ebin.BaseStream.Position += 12;

                            switch (InfoType)
                            {
                            // header type
                            case 0x2000001:
                                nr_vcpu   = ebin.ReadInt64();
                                nr_pages  = ebin.ReadInt64();
                                page_size = ebin.ReadInt64();
                                break;

                            // none type
                            case 0x2:
                                break;

                            default:
                                break;
                            }
                        }

                        ELFPfn = Elf.GetSection(".xen_pfn");
                        ebin.BaseStream.Position = ELFPfn.Offset;

                        // base page, length

                        long CurrBasePage = 0;
                        long CurrRunLen   = 0;
                        // parse the array
                        pfn_LAST = ebin.ReadInt64();
                        for (long pfnx = 0; pfnx < nr_pages; pfnx++)
                        {
                            CurrRunLen++;

                            pfn_VAL = ebin.ReadInt64();
                            if (pfn_LAST + 1 == pfn_VAL)
                            {
                                pfn_LAST = pfn_VAL;
                                continue;
                            }
                            // add run
                            DetectedRuns.Add(CurrBasePage, CurrRunLen);

                            // reset counter
                            // that is adjusted in the value
                            pfn_LAST   = CurrBasePage = pfn_VAL;
                            CurrRunLen = 0;

                            if (CurrBasePage >= nr_pages)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            ELFPages = Elf.GetSection(".xen_pages");
            if (ELFPages != null)
            {
                StartOfMem = ELFPages.Offset;
            }

            PhysMemDesc = new MemoryDescriptor(nr_pages * page_size);
            PhysMemDesc.NumberOfRuns   = DetectedRuns.Count;
            PhysMemDesc.NumberOfPages  = nr_pages;
            PhysMemDesc.StartOfMemmory = StartOfMem;
            PhysMemDesc.Run            = new List <MemoryRun>();

            foreach (var kvp in DetectedRuns)
            {
                PhysMemDesc.Run.Add(new MemoryRun()
                {
                    BasePage = kvp.Key, PageCount = kvp.Value
                });
            }

            return(SupportedStatus);
        }
Example #3
0
        public ElfLoader(string moduleName, byte[] fileData, ulong assumedStart, bool skipCoreConsistencyCheck, bool skipMemoryConsistencyCheck)
        {
            ModuleName = moduleName;
            _skipCoreConsistencyCheck   = skipCoreConsistencyCheck;
            _skipMemoryConsistencyCheck = skipMemoryConsistencyCheck;

            _elfHash = WaterboxUtils.Hash(fileData);
            _elf     = ELFReader.Load <ulong>(new MemoryStream(fileData, false), true);

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

            start = WaterboxUtils.AlignDown(start);
            var end = loadsegs.Max(s => s.Address + s.Size);

            end = WaterboxUtils.AlignUp(end);
            var size = end - start;

            if (start != assumedStart)
            {
                throw new InvalidOperationException($"{nameof(assumedStart)} did not match actual origin in elf file");
            }

            if (_elf.Sections.Any(s => s.Name.StartsWith(".rel")))
            {
                throw new InvalidOperationException("Elf has relocations!");
            }

            _allSymbols = ((ISymbolTable)_elf.GetSection(".symtab"))
                          .Entries
                          .Cast <SymbolEntry <ulong> >()
                          .ToList();

            _sectionsByName = _elf.Sections
                              .ToDictionary(s => s.Name);

            _sectionsByName.TryGetValue(".wbxsyscall", out _imports);
            if (_imports == null)
            {
                // Likely cause:  This is a valid elf file, but it was not compiled by our toolchain at all
                throw new InvalidOperationException("Missing .wbxsyscall section!");
            }
            _sectionsByName.TryGetValue(".sealed", out _sealed);
            _sectionsByName.TryGetValue(".invis", out _invisible);

            _visibleSymbols = _allSymbols
                              .Where(s => s.Binding == SymbolBinding.Global && s.Visibility == SymbolVisibility.Default)
                              .ToDictionary(s => s.Name);

            _importSymbols = _allSymbols
                             // TODO: No matter what attributes I provide, I seem to end up with Local and/or Hidden symbols in
                             // .wbxsyscall a lot of the time on heavily optimized release builds.
                             // Fortunately, there's nothing else in .wbxsyscall so we can just not filter at all.
                             .Where(s => s.PointedSection == _imports)
                             .ToList();

            Memory = MemoryBlock.Create(start, size);
            Memory.Activate();
            Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.RW);

            foreach (var seg in loadsegs)
            {
                var data = seg.GetFileContents();
                Marshal.Copy(data, 0, Z.US(seg.Address), Math.Min((int)seg.Size, (int)seg.FileSize));
            }

            {
                // Compute RW boundaries

                var allocated = _elf.Sections
                                .Where(s => (s.Flags & SectionFlags.Allocatable) != 0);
                var writable = allocated
                               .Where(s => (s.Flags & SectionFlags.Writable) != 0);
                var postSealWritable = writable
                                       .Where(s => !IsSpecialReadonlySection(s));
                var saveable = postSealWritable
                               .Where(s => s != _invisible);
                var executable = allocated
                                 .Where(s => (s.Flags & SectionFlags.Executable) != 0);

                _writeStart         = WaterboxUtils.AlignDown(writable.Min(s => s.LoadAddress));
                _postSealWriteStart = WaterboxUtils.AlignDown(postSealWritable.Min(s => s.LoadAddress));
                _execEnd            = WaterboxUtils.AlignUp(executable.Max(s => s.LoadAddress + s.Size));

                // validate; this may require linkscript cooperation
                // due to the segment limitations, the only thing we'd expect to catch is a custom eventually readonly section
                // in the wrong place (because the linkscript doesn't know "eventually readonly")
                if (_execEnd > _writeStart)
                {
                    throw new InvalidOperationException($"ElfLoader: Executable data to {_execEnd:X16} overlaps writable data from {_writeStart}");
                }
            }

            PrintSections();
            PrintGdbData();
            PrintTopSavableSymbols();
            Protect();
        }