Is there a way to access the Jedi Debug Information (JDBG) contained in an executable?
Microsoft debugging tools have pointed me to a stack chain in my binary, and i want to know what methods/procedures/functions these offsets correspond to:
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 from where. The executable was built with Jcl Debug info 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 geared around getting debug information for inside the current process, e.g.:
function GetLocationInfo(const Addr: Pointer; var Info: TJclLocationInfo): Boolean;
takes an address in my current process's address space. It the figures out which HMODULE
the address is in, e.g.:
- Stackoverflow.exe
- GDI32.dll
- USER32.dll
- KERNELBASE.dll
- dwmapi.dll
- UxTheme.dll
i was thinking i could use LoadLibrary
(which returns an HMODULE
) to manually load a module, then feed it to some of the classes that dig through module images for debug info:
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 it's protected.
i'm trying (hoping) i can write a tool where i pick the binary (*.exe), enter an address, and get returned the
- function
- method
- file
- line number
of the offset.
e.g.
[002315B5] FMain.TfrmMain.lvQuestions (Line 158, "FMain.pas" + 1) + $11
Possible?
Edit: My first, rough and ready approach, was to just extract the compressed map
file so i could look at it. But it's not saved as a resource (?):
Although a general tool would be more useful:
Update:
i tried using TJclDebugInfoList
; i realized that the array property ItemFromModule
would access 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 classes gets an underflow when it tries to convert what it assumes is a virtual address to an offset address.