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()); }
/// <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); }
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(); }