private static void RealMain(Options options) { try { using var reader = new PdbFileReader(options.InputFile); if (options.Verbose) { foreach (var item in from item in reader.PublicSymbols where !item.Name.StartsWith("_") orderby item.RelativeVirtualAddress select item) { Console.WriteLine("{0}:{1:X8} {2}", item.Segment, item.RelativeVirtualAddress, options.Demangle ? item.GetUndecoratedName() : item.Name); } } else { var syms = from item in reader.PublicSymbols where !item.Name.StartsWith("_") select item; Console.WriteLine("Symbol FullCount: {0}", syms.Count()); Console.WriteLine("Symbol DistinctCount: {0}", syms.Distinct(new SymbolEqualityComparer()).Count()); var functions = reader.Functions; Console.WriteLine("Functions FullCount: {0}", functions.Count()); } } catch (Exception e) { Console.WriteLine(e.ToString()); } }
/// <summary> /// Initializes a new instance of the <see cref="PdbPointerType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="modifierOptions">The modifier options.</param> /// <param name="elementType">PDB type of object pointed to.</param> /// <param name="size">The type size in bytes.</param> /// <param name="isLValueReference"><c>true</c> if pointer is L-value reference</param> /// <param name="isRValueReference"><c>true</c> if pointer is R-value reference</param> internal PdbPointerType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions, TypeIndex elementType, ulong size, bool isLValueReference, bool isRValueReference) : base(pdb, typeIndex, modifierOptions, pdb[elementType].Name + "*", size) { ElementType = pdb[elementType]; IsLValueReference = isLValueReference; IsRValueReference = isRValueReference; }
/// <summary> /// Initializes a new instance of the <see cref="PdbType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="tagRecord">The tag record.</param> /// <param name="modifierOptions">The modifier options.</param> /// <param name="size">The type size in bytes.</param> internal PdbUserDefinedType(PdbFileReader pdb, TypeIndex typeIndex, TagRecord tagRecord, ModifierOptions modifierOptions, ulong size) : base(pdb, typeIndex, modifierOptions, tagRecord.Name.String, size) { TagRecord = tagRecord; fieldsCache = SimpleCache.CreateWithContext(this, CallEnumerateFields); staticFieldsCache = SimpleCache.CreateWithContext(this, CallEnumerateStaticFields); baseClassesCache = SimpleCache.CreateWithContext(this, CallEnumerateBaseClasses); virtualBaseClassesCache = SimpleCache.CreateWithContext(this, CallEnumerateVirtualBaseClasses); }
public BookFile Read(string filepath) { BookFile mobi = null; var reader = new PdbFileReader(filepath); mobi = reader.ReadMobiFile(); mobi.FilePath = filepath; return(mobi); }
/// <summary> /// Gets the type name from array record. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="arrayRecord">The array record.</param> private static string GetTypeName(PdbFileReader pdb, ArrayRecord arrayRecord) { PdbType elementType = pdb[arrayRecord.ElementType]; if (elementType.Size == 0) { return($"{elementType.Name}[]"); } ulong elements = arrayRecord.Size / elementType.Size; return($"{elementType.Name}[{elements}]"); }
/// <summary> /// Initializes a new instance of the <see cref="PdbSimpleType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbSimpleType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions) : base(pdb, typeIndex, modifierOptions, typeIndex.SimpleTypeName, GetSize(typeIndex)) { }
private static void RealMain(Config config, bool verbose) { // Copy input file to output file, so we do not need to touch input file again File.Copy(config.InputFile, config.OutputFile, true); using var file = File.Open(config.OutputFile, FileMode.Open, FileAccess.ReadWrite); using var exp = File.CreateText(config.DefFile); using var action = new PEAction(file); using var pdb = new PdbFileReader(config.PdbFile); using var db = new SQLiteConnection("" + new SQLiteConnectionStringBuilder { DataSource = config.FilterOutDatabase, SyncMode = SynchronizationModes.Off, NoSharedFlags = true, FailIfMissing = false }); db.Open(); var filterout = new SortedDictionary <string, uint>(StringComparer.Ordinal); var symdb = new SymbolDatabase(); Console.WriteLine("filtering ({0})", pdb.PublicSymbols.Length); // Collect all symbols Parallel.ForEach(pdb.PublicSymbols, (item) => { if (config.Filter?.Filter(item.IsCode, item.Name) ?? true) { lock (symdb) { symdb.Add((uint)item.RelativeVirtualAddress, item.Name); } } else { lock (filterout) { filterout.Add(item.Name, (uint)item.RelativeVirtualAddress); } } }); Console.WriteLine("symbols collected: {0}, filtered: {1}", symdb.Count(), filterout.Count()); // Exclude imported symbols foreach (var sym in action.GetImportSymbols()) { if (symdb.RemoveName(sym) && verbose) { Console.WriteLine("Removed {0}", sym); } else if (filterout.Remove(sym) && verbose) { Console.WriteLine("Removed {0} (filtered)", sym); } } Console.WriteLine("symbols fixed: {0}, filtered fixed: {1}", symdb.Count(), filterout.Count()); // Write to filter out db using (var transition = db.BeginTransaction()) { using (var dropCommand = db.CreateCommand()) { dropCommand.CommandText = "DROP TABLE IF EXISTS symbols"; dropCommand.Transaction = transition; dropCommand.ExecuteNonQuery(); } using (var createCommand = db.CreateCommand()) { createCommand.CommandText = "CREATE TABLE symbols(symbol TEXT PRIMARY KEY, rva INTEGER) WITHOUT ROWID"; createCommand.Transaction = transition; createCommand.ExecuteNonQuery(); } using (var insertCommand = db.CreateCommand()) { insertCommand.CommandText = "INSERT INTO symbols VALUES ($symbol, $rva)"; insertCommand.Transaction = transition; foreach (var item in filterout) { insertCommand.Parameters.AddWithValue("$symbol", item.Key); insertCommand.Parameters.AddWithValue("$rva", item.Value); insertCommand.ExecuteNonQuery(); insertCommand.Parameters.Clear(); insertCommand.Reset(); } } transition.Commit(); } // Build cache var cache = symdb.ToArray(); var sorted = symdb.Build(); // Print exported symbols exp.Write("LIBRARY " + config.DllName + "\n"); exp.Write("EXPORTS\n"); foreach (var(name, idx) in sorted) { exp.Write(string.Format("\t{0}\n", name)); } Console.WriteLine("starting rebuild PE file"); // Calculate append length uint length = 0; var expdirlength = (uint)Marshal.SizeOf <ExportDir>(); var dllnamelength = (uint)(config.DllName.Length + 1); var NumberOfFunctions = (uint)cache.Count(); var functionslength = NumberOfFunctions * 4; var NumberOfNames = (uint)cache.Select(item => item.Value.Count).Aggregate(0, (a, b) => a + b); var ordinalslength = NumberOfNames * 2; var nameslength = NumberOfNames * 4; var stringslength = (uint)sorted.Select(kv => kv.Key.Length + 1).Aggregate(0, (a, b) => a + b); Console.WriteLine("NumberOfFunctions: {0}", NumberOfFunctions); Console.WriteLine("NumberOfNames: {0}", NumberOfNames); Console.WriteLine("Length Of ExportDir: {0}", expdirlength); Console.WriteLine("Length Of DllName: {0}", dllnamelength); Console.WriteLine("Length Of Functions: {0}", functionslength); Console.WriteLine("Length Of Ordinals: {0}", ordinalslength); Console.WriteLine("Length Of Names: {0}", nameslength); Console.WriteLine("Length Of Strings: {0}", stringslength); length = expdirlength + dllnamelength + functionslength + ordinalslength + nameslength + stringslength; Console.WriteLine("Addition length: {0}", length); // Start modify header var VirtualEnd = action.GetEnding(); var OriginalSize = (uint)file.Length; action.PatchNtHeader(GetAlign(length)); action.PatchDir(0, VirtualEnd, length); { var header = new SectionHeader { }; header.SetName(".hacked"); header.Misc.VirtualSize = length; header.VirtualAddress = VirtualEnd; header.SizeOfRawData = GetAlign(length); header.PointerToRawData = OriginalSize; header.Characteristics = 0x40000040; action.AppendSection(header); } // Write export table file.SetLength(OriginalSize + GetAlign(length)); { var expdir = new ExportDir { }; expdir.Name = VirtualEnd + expdirlength; expdir.Base = 1; expdir.NumberOfFunctions = NumberOfFunctions; expdir.NumberOfNames = NumberOfNames; expdir.AddressOfFunctions = VirtualEnd + expdirlength + dllnamelength; expdir.AddressOfOrdinals = VirtualEnd + expdirlength + dllnamelength + functionslength; expdir.AddressOfNames = VirtualEnd + expdirlength + dllnamelength + functionslength + ordinalslength + stringslength; action.WriteExport(expdir); } action.Writer.WriteByteString(config.DllName); foreach (var(key, _) in cache) { action.Writer.WriteStruct(new RVA { Value = key }); } foreach (var(_, idx) in sorted) { action.Writer.WriteStruct(new Ordinal { Value = idx }); } { var strscache = new List <uint>(); var baseoff = (uint)file.Position; var baserva = VirtualEnd + expdirlength + dllnamelength + functionslength + ordinalslength; foreach (var(name, _) in sorted) { strscache.Add((uint)file.Position - baseoff + baserva); if (verbose) { Console.WriteLine("{0:X8} -> {1:X8}", file.Position, file.Position - baseoff + baserva); } action.Writer.WriteByteString(name); } foreach (var add in strscache) { action.Writer.WriteStruct(new RVA { Value = add }); } Console.WriteLine("VirtualEnd: {0} {0:X8}", VirtualEnd); Console.WriteLine("OriginalSize: {0} {0:X8}", OriginalSize); Console.WriteLine("RealAppend: {0} {0:X8}", file.Position - OriginalSize); } }
/// <summary> /// Initializes a new instance of the <see cref="PdbType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="unionRecord">The union record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbUnionType(PdbFileReader pdb, TypeIndex typeIndex, UnionRecord unionRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, unionRecord, modifierOptions, unionRecord.Size) { UnionRecord = unionRecord; }
public void TestPdb(int pdbIndex) { if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { return; } string pdbPath = GetPdbPath(pdbIndex); IDiaDataSource dia = DiaLoader.CreateDiaSource(); IDiaSession diaSession; dia.loadDataFromPdb(pdbPath); dia.openSession(out diaSession); using (PdbFileReader pdb = new PdbFileReader(pdbPath)) { // Verify UDTs IReadOnlyList <PdbType> pdbUdts = pdb.UserDefinedTypes; IDiaSymbol[] diaUdts = diaSession.globalScope.GetChildren(SymTagEnum.UDT) .Concat(diaSession.globalScope.GetChildren(SymTagEnum.Enum)) .OrderBy(s => s.constType ? 1 : 0) // Order so that we move types with ModifierRecord to the back .ThenBy(s => s.unalignedType ? 1 : 0) .ThenBy(s => s.volatileType ? 1 : 0) .ToArray(); HashSet <Tuple <uint, PdbType> > checkedTypes = new HashSet <Tuple <uint, PdbType> >(); HashSet <string> checkedUdts = new HashSet <string>(); Dictionary <string, PdbType> pdbTypesByName = new Dictionary <string, PdbType>(); foreach (PdbType pdbType in pdbUdts) { if (!pdbTypesByName.ContainsKey(pdbType.Name)) { pdbTypesByName.Add(pdbType.Name, pdbType); } } foreach (IDiaSymbol diaType in diaUdts) { string name = diaType.name; if (!checkedUdts.Contains(name)) { PdbType pdbType = pdbTypesByName[name]; CompareTypes(diaType, pdbType, checkedTypes); checkedUdts.Add(name); } } // Verify global variables IDiaSymbol[] diaGlobalVariables = diaSession.globalScope.GetChildren(SymTagEnum.Data).Where(s => s.locationType == LocationType.Static).ToArray(); Assert.Equal(diaGlobalVariables.Length, pdb.GlobalVariables.Length); for (int i = 0; i < diaGlobalVariables.Length; i++) { IDiaSymbol diaGlobalVariable = diaGlobalVariables[i]; PdbGlobalVariable pdbGlobalVariable = pdb.GlobalVariables[i]; Assert.Equal(diaGlobalVariable.name, pdbGlobalVariable.Name); Assert.Equal(diaGlobalVariable.addressSection, pdbGlobalVariable.Segment); Assert.Equal(diaGlobalVariable.addressOffset, pdbGlobalVariable.Offset); Assert.Equal(diaGlobalVariable.relativeVirtualAddress, pdbGlobalVariable.RelativeVirtualAddress); CompareTypes(diaGlobalVariable.type, pdbGlobalVariable.Type, checkedTypes); } // Verify functions IDiaSymbol[] diaFunctions = diaSession.globalScope.GetChildren(SymTagEnum.Function) .OrderBy(d => d.name) .ThenBy(d => d.relativeVirtualAddress).ToArray(); PdbFunction[] pdbFunctions = pdb.Functions .OrderBy(p => p.Name) .ThenBy(p => p.RelativeVirtualAddress).ToArray(); Assert.Equal(diaFunctions.Length, pdbFunctions.Length); for (int i = 0; i < diaFunctions.Length; i++) { IDiaSymbol diaFunction = diaFunctions[i]; PdbFunction pdbFunction = pdbFunctions[i]; Assert.Equal(diaFunction.name, pdbFunction.Name); Assert.Equal(diaFunction.addressSection, pdbFunction.Segment); Assert.Equal(diaFunction.addressOffset, pdbFunction.Offset); Assert.Equal(diaFunction.customCallingConvention, pdbFunction.HasCustomCallingConvention); Assert.Equal(diaFunction.farReturn, pdbFunction.HasFarReturn); Assert.Equal(diaFunction.framePointerPresent, pdbFunction.HasFramePointer); Assert.Equal(diaFunction.interruptReturn, pdbFunction.HasInterruptReturn); Assert.Equal(diaFunction.length, pdbFunction.CodeSize); Assert.Equal(diaFunction.noInline, pdbFunction.IsNoInline); Assert.Equal(diaFunction.notReached, pdbFunction.IsUnreachable); Assert.Equal(diaFunction.noReturn, pdbFunction.IsNoReturn); Assert.Equal(diaFunction.optimizedCodeDebugInfo, pdbFunction.HasOptimizedDebugInfo); Assert.Equal(diaFunction.relativeVirtualAddress, pdbFunction.RelativeVirtualAddress); CompareTypes(diaFunction.type, pdbFunction.FunctionType, checkedTypes); //Assert.Equal(diaFunction.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbFunction.GetUndecoratedName(NameUndecorator.Flags.Complete)); // TODO: hasAlloca // TODO: hasEH // TODO: hasEHa // TODO: hasInlAsm // TODO: hasLongJump // TODO: hasSecurityChecks // TODO: hasSEH // TODO: hasSetJump // TODO: intro // TODO: InlSpec // TODO: isNaked // TODO: isStatic // TODO: locationType // TODO: noStackOrdering // TODO: pure // TODO: token // TODO: virtual // TODO: virtualBaseOffset } // Verify publics IDiaSymbol[] diaPublicSymbols = diaSession.globalScope.GetChildren(SymTagEnum.PublicSymbol).ToArray(); Assert.Equal(diaPublicSymbols.Length, pdb.PublicSymbols.Length); for (int i = 0; i < diaPublicSymbols.Length; i++) { IDiaSymbol diaPublicSymbol = diaPublicSymbols[i]; PdbPublicSymbol pdbPublicSymbol = pdb.PublicSymbols[i]; Assert.Equal(diaPublicSymbol.name, pdbPublicSymbol.Name); Assert.Equal(diaPublicSymbol.addressSection, pdbPublicSymbol.Segment); Assert.Equal(diaPublicSymbol.addressOffset, pdbPublicSymbol.Offset); Assert.Equal(diaPublicSymbol.relativeVirtualAddress, pdbPublicSymbol.RelativeVirtualAddress); Assert.Equal(diaPublicSymbol.code, pdbPublicSymbol.IsCode); Assert.Equal(diaPublicSymbol.function, pdbPublicSymbol.IsFunction); Assert.Equal(diaPublicSymbol.managed, pdbPublicSymbol.IsManaged); Assert.Equal(diaPublicSymbol.msil, pdbPublicSymbol.IsMsil); Assert.Equal(LocationType.Static, diaPublicSymbol.locationType); Assert.True(CompareUndecoratedNames(pdbPublicSymbol.Name, diaPublicSymbol.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbPublicSymbol.GetUndecoratedName(NameUndecorator.Flags.Complete))); //Assert.Equal(diaPublicSymbol.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbPublicSymbol.GetUndecoratedName(NameUndecorator.Flags.Complete)); // TODO: diaPublicSymbol.length } } }
/// <summary> /// Initializes a new instance of the <see cref="PdbType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="enumRecord">The enum record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbEnumType(PdbFileReader pdb, TypeIndex typeIndex, EnumRecord enumRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, enumRecord, modifierOptions, pdb[enumRecord.UnderlyingType].Size) { EnumRecord = enumRecord; valuesCache = SimpleCache.CreateWithContext(this, CallEnumerateValues); }
/// <summary> /// Initializes a new instance of the <see cref="PdbFunctionType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="procedureRecord">The procedure record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbFunctionType(PdbFileReader pdb, TypeIndex typeIndex, ProcedureRecord procedureRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, modifierOptions, string.Empty, 0) { ProcedureRecord = procedureRecord; argumentsCache = SimpleCache.CreateWithContext(this, CallEnumerateArguments); }
/// <summary> /// Initializes a new instance of the <see cref="PdbArrayType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="arrayRecord">The array record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbArrayType(PdbFileReader pdb, TypeIndex typeIndex, ArrayRecord arrayRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, modifierOptions, GetTypeName(pdb, arrayRecord), arrayRecord.Size) { ArrayRecord = arrayRecord; }
/// <summary> /// Initializes a new instance of the <see cref="PdbSimplePointerType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbSimplePointerType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions) : base(pdb, typeIndex, modifierOptions, new TypeIndex(typeIndex.SimpleKind), GetPointerSize(typeIndex), isLValueReference: false, isRValueReference: false) { }
/// <summary> /// Initializes a new instance of the <see cref="PdbType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="classRecord">The class record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbClassType(PdbFileReader pdb, TypeIndex typeIndex, ClassRecord classRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, classRecord, modifierOptions, classRecord.Size) { ClassRecord = classRecord; }
/// <summary> /// Initializes a new instance of the <see cref="PdbComplexPointerType"/> class. /// </summary> /// <param name="pdb">The PDB file reader.</param> /// <param name="typeIndex">Type index.</param> /// <param name="pointerRecord">The pointer record.</param> /// <param name="modifierOptions">The modifier options.</param> internal PdbComplexPointerType(PdbFileReader pdb, TypeIndex typeIndex, PointerRecord pointerRecord, ModifierOptions modifierOptions) : base(pdb, typeIndex, CombineModifierOptions(modifierOptions, pointerRecord), pointerRecord.ReferentType, GetPointerSize(pointerRecord), pointerRecord.Mode == PointerMode.LValueReference, pointerRecord.Mode == PointerMode.RValueReference) { PointerRecord = pointerRecord; }