Access to JCL debug information contained in an executable?

Is there a way to access the Jugi Debug Information (JDBG) contained in the executable?

Microsoft's debugging tools pointed me to the stack chain in my binary, and I want to know which methods / procedures / functions correspond to these offsets:

user32.dll!SendMessageA+0x4c StackOverflow.exe+0x179263 StackOverflow.exe+0x2315b5 StackOverflow.exe+0x1fc82 StackOverflow.exe+0x50388 StackOverflow.exe+0x541fe user32.dll!gapfnScSendMessage+0x332 

Obviously I'm calling SendMessage , but I don't know where from. The executable was created with Jcl Debug information embedded in the executable; but I can’t figure out how to read it.

Looking at some of the functions and classes in JclDebug.pas , everything seems to be focused on getting debug information inside the current process, for example:

 function GetLocationInfo(const Addr: Pointer; var Info: TJclLocationInfo): Boolean; 

accepts an address in my current process address space. These are the numbers in which HMODULE is the address, for example:

  • Stackoverflow.exe
  • Gdi32.dll
  • USER32.dll
  • KERNELBASE.dll
  • dwmapi.dll
  • UXTheme.dll

I thought I could use LoadLibrary (which returns an HMODULE ) to manually load a module, and then pass it to some classes that look at module images for debugging information:

 module := LoadLibrary('C:\Users\Ian\Desktop\StackOverflow.exe'); 

and

 TJclDebugInfoList = class(TObjectList) private function GetItemFromModule(const Module: HMODULE): TJclDebugInfoSource; ... protected function CreateDebugInfo(const Module: HMODULE): TJclDebugInfoSource; ... end; 

except protected.

I try (hopefully), I can write a tool where I select the binary (* .exe), enter the address and return

  • Function
  • method
  • file
  • line number

displacement.

eg.

 [002315B5] FMain.TfrmMain.lvQuestions (Line 158, "FMain.pas" + 1) + $11 

Possible?


Edit: My first, rough and off-the-shelf approach was to simply extract the compressed map file so that I can look at it. But it is not saved as a resource (?):

enter image description here

Although a general tool would be more useful:

enter image description here


Update

I tried using TJclDebugInfoList ; I realized that the property of the ItemFromModule array will gain access to the protected method:

 function GetModuleLocationInfo(filename: string; Addr: Pointer): TJclLocationInfo; var module: HMODULE; infoList: TJclDebugInfoList; infoSource: TJclDebugInfoSource; Address: Pointer; locationInfo: TJclLocationInfo; AddressOffset: Integer; begin module := LoadLibrary(filename); if module = 0 then RaiseLastWin32Error; try infoList := TJclDebugInfoList.Create; try infoSource := infoList.ItemFromModule[module]; if source = nil then raise Exception.Create('Could not find debug info source for module '+IntToStr(module)); if not source.GetLocationInfo(Addr, {var}locationInfo) then raise Exception.Create('Could not get location info for address $'+IntToHex(Integer(Address), 8)); Result := locationInfo; finally infoList.Free; end; finally FreeLibrary(module); end; end; 

Except that the code in one of the TJclDebugInfoSource descendant TJclDebugInfoSource receives a lower thread when it tries to translate what it assumes is a virtual address to an offset address.

+3
source share
3 answers

Create a TJclDebugInfoBinary object using the HModule handle that you get from LoadLibrary . Then type GetLocationInfo . That all TJclDebugInfoList would be done anyway, except that it has helper methods for matching addresses from the current address space with their respective modules, whereas when you do this manually, you will already have to know which module the address belongs to. (But the crash dump already told you this part, so you don't need the help of the list class.)

You will probably have to massage the addresses, because the base address of the module during the failure will not be the same as when you loaded it using LoadLibrary .

JCL debugging information is not stored in the resource. It is stored in a PE section named JCLDEBUG. See Using PeMapImgFindSection32 and PeMapImgFindSectionFromModule in JclDebug.pas.

+2
source

I made such a tool some time ago, I don’t know if I can find it again, but at least it is possible :-)

On the other hand, I made several tools using jclDebug.pas, and now I remember: I made some changes to make the offline stack trace possible. You can look at them:

Real-time file viewer: http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer

Reading Minidump (using standalone .map reading or exe's built-in jdbg information): http://code.google.com/p/asmprofiler/source/browse/#svn%2Ftrunk%2FMiniDumpReader

+1
source

Here the code can provide debug address information in the module

 function GetModuleLocationInfo(filename: string; AddressOffset: Pointer; AssumeOffsetIsRelativeToStartOfCodeSection: Boolean=False): TJclLocationInfo; var module: HMODULE; infoList: TJclDebugInfoList; infoSource: TJclDebugInfoSource; Address: Pointer; locationInfo: TJclLocationInfo; begin //Code is public domain. No attribution required. module := LoadLibrary(PChar(filename)); if module = 0 then RaiseLastWin32Error; try infoList := TJclDebugInfoList.Create; try infoSource := infoList.ItemFromModule[module]; if infoSource = nil then raise Exception.Create('Could not find debug info source for module '+IntToStr(module)); DWORD(Address) := DWORD(AddressOffset) + DWORD(module) + DWORD(ModuleCodeOffset); if not infoSource.GetLocationInfo(Address, {var}locationInfo) then raise Exception.Create('Could not get location info for address $'+IntToHex(Integer(Address), 8)); Result := locationInfo; finally infoList.Free; end; finally FreeLibrary(module); end; end; 

And a practical example, an offset from Process Explorer:

enter image description here

 GetModuleLocationInfo('C:\Program Files (x86)\Avatar\HelpDesk.exe', 0xdcb17); 

returns:

 TJclLocationInfo Address: $266CB17 UnitName: 'BalloonHint' ProcedureName: 'TBalloonHint.SetVisible' OffsetFromProcName: 83 LineNumber: 281 OffsetFromLineNumber: 0 SourceName: 'BalloonHint.pas' DebugInfo: $1F25C74 

Or in the style of JclDebug:

[0266CB17] BalloonHint.TBalloonHint.SetVisible (line 281, "BalloonHint.pas") + $ 0

+1
source

All Articles