الوصول إلى معلومات JCL Debug الموجودة في الملف القابل للتنفيذ؟

StackOverflow https://stackoverflow.com/questions/6019698

سؤال

هل هناك طريقة للوصول إلى معلومات تصحيح جيدي (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 العنوان موجود، على سبيل المثال:

  • Stackoverflow.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 الملف حتى أتمكن من الاطلاع عليه.ولكن لا يتم حفظه كمورد (?):

enter image description here

على الرغم من أن الأداة العامة ستكون أكثر فائدة:

enter image description here


تحديث:

حاولت استخدام 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;

إلا أن الكود الموجود في أحد TJclDebugInfoSource تحصل الفئات التابعة على تدفق ناقص عندما تحاول تحويل ما تفترض أنه عنوان افتراضي إلى عنوان إزاحة.

هل كانت مفيدة؟

المحلول

إنشاء TJclDebugInfoBinary الكائن باستخدام HModule التعامل الذي تحصل عليه من LoadLibrary.ثم اتصل GetLocationInfo عليه.هذا كل شئ TJclDebugInfoList كان من الممكن أن يتم ذلك على أي حال، إلا أنه يحتوي على بعض الطرق المساعدة لتعيين العناوين من مساحة العنوان الحالية إلى الوحدات التي تتوافق معها، بينما عندما تفعل ذلك يدويًا، سيتعين عليك معرفة الوحدة النمطية التي تنتمي إليها العناوين بالفعل.(لكن ملف تفريغ الأعطال أخبرك بالفعل بهذا الجزء، لذلك لا تحتاج إلى مساعدة فئة القائمة.)

ربما سيتعين عليك تدليك العناوين لأن العنوان الأساسي للوحدة في وقت التعطل لن يكون هو نفسه عندما قمت بتحميلها LoadLibrary.

لا يتم تخزين معلومات تصحيح JCL في أحد الموارد.يتم تخزينه في قسم PE المسمى JCLDEBUG.شاهد استخدامات PeMapImgFindSection32 و PeMapImgFindSectionFromModule في JclDebug.pas.

نصائح أخرى

لقد صنعت مثل هذه الأداة منذ فترة، ولا أعرف إذا كان بإمكاني العثور عليها مرة أخرى، ولكن على الأقل هذا ممكن :-)

من ناحية أخرى، قمت بإنشاء العديد من الأدوات باستخدام jclDebug.pas، والآن أتذكر:لقد قمت بإجراء بعض التغييرات عليه لجعل تتبع المكدس "غير متصل" ممكنًا.يمكنك إلقاء نظرة على هذه:

عارض مكدس العمليات المباشرة:http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer

قارئ Minidump (باستخدام خريطة القراءة دون الاتصال بالإنترنت أو معلومات jdbg المضمنة من exe):http://code.google.com/p/asmprofiler/source/browse/#svn%2Ftrunk%2FMiniDumpReader

هذا هو الكود الذي يمكن أن يوفر معلومات تصحيح الأخطاء حول عنوان في الوحدة النمطية

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;

ومثال عملي، إزاحة من Process Explorer:

enter image description here

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

عائدات:

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

أو بأسلوب JclDebug:

[0266CB17] BalloonHint.TBalloonHint.SetVisible (السطر 281، "BalloonHint.pas") + $0

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top