3

実行可能ファイルに含まれるJedi Debug Information (JDBG)にアクセスする方法はありますか?

Microsoft デバッグ ツールは、バイナリ内のスタック チェーンを指摘してくれました。これらのオフセットが対応するメソッド/手順/関数を知りたいです。

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

明らかに私は電話をかけSendMessageていますが、どこからかわかりません。実行可能ファイルは、実行可能ファイルに埋め込まれた Jcl Debug 情報を使用してビルドされました。しかし、読み方がわかりません。

のいくつかの関数とクラスを見るとJclDebug.pas、すべてが現在のプロセス内のデバッグ情報を取得するように調整されているようです。たとえば、次のようになります。

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

現在のプロセスのアドレス空間でアドレスを取ります。HMODULEアドレスがどこにあるかがわかります。たとえば、次のようになります。

  • スタックオーバーフロー.exe
  • GDI32.dll
  • USER32.dll
  • KERNELBASE.dll
  • dwmapi.dll
  • UxTheme.dll

LoadLibrary(これは を返します) を使用HMODULEしてモジュールを手動でロードし、デバッグ情報を得るためにモジュール イメージを掘り下げるいくつかのクラスにそれをフィードできると考えていました。

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

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

保護されていることを除いて。

バイナリ (*.exe) を選択し、アドレスを入力して、

  • 関数
  • 方法
  • ファイル
  • 行番号

オフセットの。

例えば

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

可能?


編集:map私の最初のラフで準備の整ったアプローチは、圧縮ファイルを抽出して、それを見ることができるようにすることでした。ただし、リソースとして保存されません ( ? ):

ここに画像の説明を入力

一般的なツールの方が便利ですが:

ここに画像の説明を入力


更新

使ってみTJclDebugInfoListた; ItemFromModule配列プロパティが保護されたメソッドにアクセスすることに気付きました:

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;

ただし、下位クラスの 1 つのコードTJclDebugInfoSourceが、仮想アドレスであると想定しているものをオフセット アドレスに変換しようとすると、アンダーフローが発生します。

4

3 に答える 3

2

から取得したハンドルをTJclDebugInfoBinary使用して、オブジェクトを作成します。それからそれを呼び出します。現在のアドレス空間から対応するモジュールにアドレスをマップするいくつかのヘルパーメソッドがあることを除けば、これですべてです。一方、手動で行う場合は、アドレスがどのモジュールに属しているかを既に知っている必要があります。(しかし、クラッシュ ダンプは既にその部分を伝えているので、リスト クラスの助けは必要ありません。)HModuleLoadLibraryGetLocationInfoTJclDebugInfoList

クラッシュ時のモジュールのベースアドレスは、 でロードしたときと同じにはならないため、おそらくアドレスをマッサージする必要がありますLoadLibrary

JCL デバッグ情報はリソースに格納されません。JCLDEBUG という名前の PE セクションに格納されます。JclDebug.pasPeMapImgFindSection32のとPeMapImgFindSectionFromModuleの使用を参照してください。

于 2011-05-17T18:00:48.477 に答える
1

私はそのようなツールを少し前に作成しました。再び見つけることができるかどうかはわかりませんが、少なくとも可能です:-)

一方、jclDebug.pas を使用していくつかのツールを作成したことを思い出しました。「オフライン」スタック トレースを可能にするために、いくつかの変更を加えました。あなたはこれらを見ることができます:

ライブ プロセス スタック ビューアー: http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer

ミニダンプ リーダー (exe からのオフライン読み取り .map または埋め込み jdbg 情報を使用): http://code.google.com/p/asmprofiler/source/browse/#svn%2Ftrunk%2FMiniDumpReader

于 2011-05-18T06:36:01.057 に答える