代码之家  ›  专栏  ›  技术社区  ›  Remko

如何使用dbghlp和pdb获取结构的字段名和偏移量

  •  2
  • Remko  · 技术社区  · 16 年前

    我希望以与windbg的dt命令相同的方式转储结构的字段和偏移量。例如,我想转储微软公共符号中的peb结构(因为windbg的dt命令有效)。

    从msdn文档中我了解到symfromname函数应该能够做到这一点,下面是我尝试过的代码,它在symfromname上失败,最后出现错误126(找不到指定的模块)。 从注册的回调中,我得到以下输出:

    CBA_SET_OPTIONS
    CBA_SET_OPTIONS
    CBA_SET_OPTIONS
    CBA_EVENT: code 0 desc DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
    
    DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
    
    CBA_DEFERRED_SYMBOL_LOAD_START: C:\Windows\Sysnative\ntdll.dll
    CBA_DEFERRED_SYMBOL_LOAD_PARTIAL: C:\Windows\Sysnative\ntdll.dll
    CBA_EVENT: code 0 desc DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk
    
    DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk
    
    CBA_EVENT: code 0 desc DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK
    
    DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK
    
    CBA_DEFERRED_SYMBOL_LOAD_COMPLETE: C:\Windows\Sysnative\ntdll.dll
    CBA_EVENT: code 0 desc DBGHELP: ntdll - public symbols  
             C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb
    
    DBGHELP: ntdll - public symbols  
             C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb
    

    代码:

    const
      Index: THandle =1;
      Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
    var
      Symbol: String;
      Filename: String;
      Path: String;
      dwBaseAddress: DWORD;
      im: IMAGEHLP_MODULE64;
      Buffer: array[0..Size] of ULONG64;
      pSymbol: PSYMBOL_INFO;
      SymbolName: array[0..MAX_SYM_NAME-1] of Char;
    begin
      ZeroMemory(@SymbolName, SizeOf(SymbolName));
      SymbolName := '_PEB';
      Filename := 'C:\Windows\Sysnative\ntdll.dll';
      Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';
    
      { Initialize }
      Win32Check(SymInitialize(Index, nil, False));
      { Register callback to get some debug info }
      Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));
    
      { Set Options }
      SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
      SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
      SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);
    
      { Set Symbol Path }
      Win32Check(SymSetSearchPathW(Index, PChar(Path)));
    
      { Load Module }
      dwBaseAddress := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);
      Win32Check(dwBaseAddress > 0);
    
      ZeroMemory(@im, SizeOf(im));
      im.SizeOfStruct := SizeOf(im);
      Win32Check(SymGetModuleInfoW64(Index, dwBaseAddress, im));
    
      ZeroMemory(@Buffer, SizeOf(Buffer));
      pSymbol := PSYMBOL_INFO(@Buffer);
      pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
      pSymbol^.MaxNameLen := MAX_SYM_NAME;
    
      Win32Check(SymFromNameW(Index, Symbolname, pSymbol));
    
      Win32Check(SymUnloadModule64(Index, dwBaseAddress));
      Win32Check(SymCleanup(Index));
    
    2 回复  |  直到 16 年前
        1
  •  3
  •   Remko    16 年前

    我使用symgettypefromname获取符号索引,然后使用symgettypeinfo获取详细信息:

    const
      Index: THandle =1;
      Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
    var
      Filename: String;
      Path: String;
      dwBaseAddress: array[0..0] of DWORD;
      im: IMAGEHLP_MODULE64;
      Buffer: array[0..Size] of ULONG64;
      pSymbol: PSYMBOL_INFO;
      SymbolName: array[0..MAX_SYM_NAME-1] of Char;
      i: Integer;
      ChildParams: TI_FINDCHILDREN_PARAMS;
      dwOffset: DWORD;
      pSymName: PChar;
    begin
      ZeroMemory(@SymbolName, SizeOf(SymbolName));
      SymbolName := '_PEB';
      Filename := 'C:\Windows\System32\ntdll.dll';
      Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';
    
      { Initialize }
      Win32Check(SymInitialize(Index, nil, False));
      { Register callback to get some debug info }
      Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));
    
      { Set Options }
      SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
      SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
      SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);
    
      { Set Symbol Path }
      Win32Check(SymSetSearchPathW(Index, PChar(Path)));
    
      { Load Module }
      dwBaseAddress[0] := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);
    
      ZeroMemory(@im, SizeOf(im));
    
      im.SizeOfStruct := SizeOf(im);
      for i := 0 to Length(dwBaseAddress)-1 do
      begin
        SymGetModuleInfoW64(Index, dwBaseAddress[i], im);
      end;
    
      ZeroMemory(@Buffer, SizeOf(Buffer));
      pSymbol := PSYMBOL_INFO(@Buffer);
      pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
      pSymbol^.MaxNameLen := MAX_SYM_NAME;
      { Get Type Info by Symbol Name (we need the index) }
      Win32Check(SymGetTypeFromNameW(Index, dwBaseAddress[0], SymbolName, pSymbol));
    
      { Get Child Count }
      ZeroMemory(@ChildParams, SizeOf(ChildParams));
      Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_GET_CHILDRENCOUNT, @ChildParams.Count));
    
      { Get Child Info }
      // TODO: Caller must reserve memory for the ChildId array (Count * SizeOf(ULONG))
      Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_FINDCHILDREN, @ChildParams));
      for i := ChildParams.Start to ChildParams.Count - 1 do
      begin
        { Get Child Name }
        Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_SYMNAME, @pSymName));
        { Get Child Offset }
        Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_OFFSET, @dwOffset));
        Memo1.Lines.Add(Format('+0x%.3x %s', [dwOffset, pSymName]));
        LocalFree(Cardinal(pSymName));
      end;
    
      for i := 0 to Length(dwBaseAddress)-1 do
      begin
        Win32Check(SymUnloadModule64(Index, dwBaseAddress[i]));
      end;
      Win32Check(SymCleanup(Index));
    end;
    

    这就是输出:

    +0x000 InheritedAddressSpace
    +0x001 ReadImageFileExecOptions
    +0x002 BeingDebugged
    +0x003 BitField
    +0x003 ImageUsesLargePages
    +0x003 IsProtectedProcess
    +0x003 IsLegacyProcess
    +0x003 IsImageDynamicallyRelocated
    +0x003 SkipPatchingUser32Forwarders
    +0x003 SpareBits
    +0x004 Mutant
    +0x008 ImageBaseAddress
    +0x00C Ldr
    +0x010 ProcessParameters
    +0x014 SubSystemData
    +0x018 ProcessHeap
    +0x01C FastPebLock
    +0x020 AtlThunkSListPtr
    +0x024 IFEOKey
    +0x028 CrossProcessFlags
    +0x028 ProcessInJob
    +0x028 ProcessInitializing
    +0x028 ProcessUsingVEH
    +0x028 ProcessUsingVCH
    +0x028 ProcessUsingFTH
    +0x028 ReservedBits0
    +0x02C KernelCallbackTable
    +0x02C UserSharedInfoPtr
    +0x030 SystemReserved
    +0x034 AtlThunkSListPtr32
    +0x038 ApiSetMap
    +0x03C TlsExpansionCounter
    +0x040 TlsBitmap
    +0x044 TlsBitmapBits
    +0x04C ReadOnlySharedMemoryBase
    +0x050 HotpatchInformation
    +0x054 ReadOnlyStaticServerData
    +0x058 AnsiCodePageData
    +0x05C OemCodePageData
    +0x060 UnicodeCaseTableData
    +0x064 NumberOfProcessors
    +0x068 NtGlobalFlag
    +0x070 CriticalSectionTimeout
    +0x078 HeapSegmentReserve
    +0x07C HeapSegmentCommit
    +0x080 HeapDeCommitTotalFreeThreshold
    +0x084 HeapDeCommitFreeBlockThreshold
    +0x088 NumberOfHeaps
    +0x08C MaximumNumberOfHeaps
    +0x090 ProcessHeaps
    +0x094 GdiSharedHandleTable
    +0x098 ProcessStarterHelper
    +0x09C GdiDCAttributeList
    +0x0A0 LoaderLock
    +0x0A4 OSMajorVersion
    +0x0A8 OSMinorVersion
    +0x0AC OSBuildNumber
    +0x0AE OSCSDVersion
    +0x0B0 OSPlatformId
    +0x0B4 ImageSubsystem
    +0x0B8 ImageSubsystemMajorVersion
    +0x0BC ImageSubsystemMinorVersion
    +0x0C0 ActiveProcessAffinityMask
    +0x0C4 GdiHandleBuffer
    +0x14C PostProcessInitRoutine
    +0x150 TlsExpansionBitmap
    +0x154 TlsExpansionBitmapBits
    +0x1D4 SessionId
    +0x1D8 AppCompatFlags
    +0x1E0 AppCompatFlagsUser
    +0x1E8 pShimData
    +0x1EC AppCompatInfo
    +0x1F0 CSDVersion
    +0x1F8 ActivationContextData
    +0x1FC ProcessAssemblyStorageMap
    +0x200 SystemDefaultActivationContextData
    +0x204 SystemAssemblyStorageMap
    +0x208 MinimumStackCommit
    +0x20C FlsCallback
    +0x210 FlsListHead
    +0x218 FlsBitmap
    +0x21C FlsBitmapBits
    +0x22C FlsHighIndex
    +0x230 WerRegistrationData
    +0x234 WerShipAssertPtr
    +0x238 pContextData
    +0x23C pImageHeaderHash
    +0x240 TracingFlags
    +0x240 HeapTracingEnabled
    +0x240 CritSecTracingEnabled
    +0x240 SpareTracingBits
    

    现在进入下一步:使用Delphi2010的rtti并使用这个机制来比较偏移量(这有助于我为绝地apilib转换头段)。

        2
  •  0
  •   Marco van de Voort    16 年前

    我并不是这些方面的专家,但C名称管理中的前导下划线有时应该是二进制格式的一部分。

    删除前导下划线是否有效?

    推荐文章