szimbólum táblázat, a szimbolikus gép és a verem áthaladását
programok hibakeresése
Az igazi készség írásban debuggers alapján a karakter a gép (pl. E. A kód, amely manipulálja a szimbólum táblázatot). Hibakeresés hagyományos szintű assembly nyelven érdekes az első pár perces munka, de hamar unatkozni. szimbólumtáblát (szimbólum táblázatok), más néven a hibakeresési szimbólumok (hibakeresés jelek) - ez az, ami a hexadecimális számok szöveggé, függvény nevét és a változó nevét forrás fájlokat. Karaktertáblák tartalmazhat további információt a fajta, hogy a program által használt. Ez az információ lehetővé teszi, hogy a hibakereső megjelenik a „nyers” adatok struktúrák és változók, amit meg a programban. Foglalkozni a modern szimbólum táblázatok nehéz, mert a leggyakrabban használt méret őket - PDB (Program adatbázisa - adatbázis-program) nem dokumentálták, és a jogtulajdonosok nem tervezi, hogy dokumentáljuk. Szerencsére, akkor kap legalább részleges hozzáférést biztosított a szimbólum táblát.
Format hibakeresési szimbólumok
Mielőtt belemennénk a vita a szervezet hozzáférést biztosít a szimbólum táblát, áttekintjük a különböző formátumú hibakeresés szimbólumok. Azt hiszem, hogy még a gyakorlott programozók megérteni rosszul ilyen formátumú, ezért beszéljünk erről részletesebben.
SYM - a legrégebbi formátumot használták a napon MS-DOS és 16 bites Windows. Jelenleg SYM-formátumot használjuk csak hibakeresési szimbólumokat a Windows 98 SYM-formátumot használnak csak azért, mert a nagy része a központi operációs rendszer kernel még mindig 16 bites kódot. Az egyetlen hibakereső aktívan használja a karakterek ebben a formátumban - ez WDEB386.
COFF (Common Object File Format - közös objektum formátum): Dean az első formátum karakter tábla, amelyet azért vezettek be a Windows NT 3.1 (az első változat Windows NT). Csapat Windows NT fejlesztők már tapasztalattal fejlesztése az operációs rendszer és a betölteni kívánt Windows NT segítségével néhány a meglévő eszközökkel. COFF formátum része egy nagyobb leírás, melyet a különböző szolgáltatók UNIX-alapú rendszerek, próbál létrehozni közös formátumok bináris fájlokat. Bár WINNT.H teljes leírás COFF-karakter, a Microsoft eszközök generál csak néhány ee - állami funkciók és globális változók. A Microsoft fenntartására használják forrás és online információs, de fokozatosan eltávolodott a COFF méret mellett egy modernebb formában szimbólum táblázatokat.
Format C7 vagy CodeView meg a napokban az MS-DOS részeként a rendszer a Microsoft C / C ++ programozási változat 7. Ön is hallott már a neve „CodeView”. Ez a név a régi Microsoft debugger. C7 méret módosításra került, hogy támogassa a Win32 operációs rendszer, és a nyírfajd generálhat ezt a formátumot, kezdve CL.EXE fordítóprogram a parancssorból a kulcs / Z7 vagy adja meg a elemet a legördülő C7 Compatible1 lista Debug Info a C / C ++ fül párbeszédablak ProjectSettings.
Itt és az alábbiakban beszélünk a felület IDE Microsoft Visul C ++. - Per
Ha szükséges, természetesen használhatja az S7 formátumban. de jobb nem megtenni. Lemondanak a használata a C7 formátum két okból szükséges. Először is, akkor automatikusan kikapcsol inkrementális elrendezés, ami miatt jelentősen növeli a kapcsolat ideje. Másodszor, jelentősen növelte a méretét binárisok. Akkor távolítsa el a szimbolikus keresztül információt REBASE.EXE programot. de vannak formátumok (pl EKT), melyek csökkentik automatikusan.
PDB - a leggyakoribb a manapság használt karakter formátumokat egyaránt támogatja a Visual C ++ és Visual Basic. Ellentétben a C7 méret, PDB-kód van tárolva egy külön fájlt vagy fájlokat, attól függően, hogy az alkalmazás van elrendezve. Alapértelmezésben az indító fájl Visual C ++ 6 kapcsolódik a kulcs / PDBTYPE: szeptember amely hozza információt a típusok in VC60.PDB fájlt, és a karakterek maguk - egy fájlba <имя-двоичного-файла>.DOM. Tanszék információk a fajta hibakereső szimbólumokkal felgyorsítja konfiguráció, és kevesebb lemezterületet. Azonban a dokumentáció kimondja, hogy ha építeni egy bináris fájl, amely a hibakeresés j mások, hogy minden információt a típusok és a hibakeresési szimbólumok konszolidálásra került egyetlen PDB-fájlt, akkor meg kell adni a kulcsot / PDBTYPE: CON. Szerencsére, a Visual Basic automatikusan használja ezt az opciót.
Ha érdekel a szimbolikus gép és elkezd felfedezni a lehetőségeket a programozási, előbb vagy utóbb találkozni fog a karakter egy másik típus - homár. Szimbólumok Az ilyen típusú jelennek meg csak néhány Microsoft alkalmazásokhoz. Ezek néha a megszerzése jellegű információk billenő használatával DUMPBIN.EXE segédprogramot. váltott paraméterrel / szimbólumok. (DUMPBIN.EXE terjesztett Visual C ++ programozási rendszer.) A karakter OMÁR méret teljesen dokumentált. Mint már korábban említettük, a Microsoft egy speciális belső eszköz, amely átszervezi a lefordított bináris fájlt, hogy a leggyakrabban a kód okozza a fájl elején. OMÁR -symbols van némi kapcsolat a hibakereső szimbólumokat, amelyek figyelembe veszik ezt poslekomponovochny lépést.
Az ilyen optimalizálást és a program Working Set Tuner (WST), a mellékelt Platform SDK. WST működik a funkcionális szinten, anélkül, hogy behatol a funkciókat, míg a Microsoft eszköz csökken arra a szintre, az ún alapegységek. A következő kód fragmenst az alapegység nyilakkal:
ha (IGAZ = blsError)
> <- Конец базового блока.
Hozzáférés a karakter információ
A WDBG egyszerű burkoló osztály (C ++ nyelven) használtunk, amely látható (SYMBOLENGINE.H) fájlt jegyzék 4-7. Kezdetben ez az osztály volt írva részeként BUGSLAYERUTIL.DLL könyvtárban. Ez nagyban rövidített változata API szimbolikus DBGHELP.DLL gép. de rendelkezik néhány további funkciók, hogy megfeleljen a kihívásoknak régebbi verziói IMAGEHLP.DLL szimbolikus gépek. SYMBOLENGINE.H forráskód mutatja abban az esetben kell használni ezt az osztályt a régi karakter gépek I MAGEHLP.DLL.
Listng4-7 .Fayl SYMBOLENGINE.H
"Hibakeresés Applications" (Microsoft Press)
Ez az osztály - egy rövidített változata a karakter DBGHELP.DLL gép. CNN csak azokra a funkciókra, amelyek egyedi értéke fogantyú leíró. A többi funkció a gép karakter DBGHELP.DLL globális, így azok nem tartoznak ebbe az osztályba.
Annak megállapítására, ez az állandó osztály nem fog működni a hiba SymGetLineFromAddr keresnek, akkor PDB fMile nem az első keresést.
Annak megállapítására, ez az állandó, ez az osztály fogja használni egy másik módszer inicializálása jellegű gép - BSUSymlnitialize a BUGSLAYERUTIL.DLL. Ezen túlmenően, a rögzítés folyamatát doboz működni kezd minden 32 bites Windows-rendszerek. Ha ezt a meghatározást, kivéve SYMBOLENGINE.N kell tartalmaznia BUGSLAYERUTIL.H fájlt.
// Ha be vagy IMAGEHLP.DLL vagy DBGHELP.DLL.
// Tartalmazza ezen irányelvek az esetben, ha a felhasználó elfelejti
// az elrendezés a megfelelő könyvtárak
#pragma üzenetére (lib, "dbghelp. lib")
#pragma üzenetére (lib, "változat, lib")
// A nagy ötlete wrapper osztályok struktúrák
// három dimenziós mező, jött ember újságíró MSJ Fields
// (Paul DiLascia). Köszönöm, Paul!;
// Nem tartalmazza az osztály állandó IMAGEHLP_SYMBOL, mert
// változó méretű szerkezetet.
struct CImageHlp_Module. nyilvános IMAGEHLP_MODULE
memset (e, NULL, sizeof (IMAGEHLP_MODULE));
SizeOfStruct = sizeof (IMAGEHLP_MODULE);
struct CImageHlp_Line. nyilvános IMAGEHLP_LINE
memset (e, NULL, sizeof (IMAGEHLP_LINE));
SizeOfStruct = sizeof (IMAGEHLP_LINE);
// Az osztály jellege a gép osztály CSymbolEngine
Public-konstruktor és destruktor
// Ennek használatához osztály, hívja a módszer Symlnitialize
// inicializálja a karakter a gép, majd a más módszerekkel
// helyett megfelelő szerepét DBGHELP.DLL
virtuális -CSymbolEngine (void)
Kiegészítő információk nyilvánosságra funkció
// Visszaadja a használt változat DBGHELP.DLL fájlt.
// konvertálni a visszaadott értékeket olvasható formátumban,
// paraméter szVer tartalmazni fog egy sort: 5.00.1878.1
BOOL GetlmageHlpVersion (DWORD dwMS, DWORD dwLS)
return (GetlnMemoryFileVersion (_T ( "DBGHELP.DLL"),
BOOL GetDbgHelpVersion (DWORD dwMS, DWORD dwLS)
return (GetlnMemoryFileVersion (__T ( "DBGHELP.DLL"),
// Visszaadja a változat a DLL-fájl olvasási PDB.
BOOL GetPDBReaderVersion (DWORD dwMS, DWORD dwLS)
// először ellenőrizte MSDBI.DLL fájlt.
if (TRUE == GetlnMemoryFileVersion (_T ( "MSDBI.DLL"),
else if. (IGAZ == GetlnMemoryFileVersion (_T ( "MSPDB60.DLL"),
// Most volt a sor, ellenőrizze MSPDB50.DLL.
visszatéréshez (GetlnMemoryFileVersion (_T ( "MSPDB50.DLL"),
// Munka függvény előző két funkciót.
BOOL GetlnMemoryFileVersion (LPCTSTR szFile,
HMODULE hlnstlH = GetModuleHandle (szFile);
// A teljes fájl nevét letöltött verzió
TCHAR sz mageHlp [MAX_PATH] !;
GetModuleFileName (hlnst-IH, szImageHlp, MAX_PATH);
// A méret a verzió információkat.
dwVerSize = GetFileVersionlnfoSize (szImageHlp.
ha (0 == dwVerSize)
// A méret a verzió információkat, és most kap
LPVOID IpData = (LPVOID) új TCHAR [dwVerSize];
if (HAMIS == GetFileVersionlnfo (szImageHlp.
dwVerlnfoHandle. dwVerSize. IpData))
törölni [] IpData; visszatérő (HAMIS);
// Egy egyedi érték, amelyeket használni fognak erre
// Például szimbolikus gépek. Ez az érték ne legyen
// az érték a tényleges folyamat, hanem egyszerűen - egy egyedi értéket.
Telepítése DBGHELP.DLL - csak egy része a történetnek, mert ahhoz, hogy betölti a szimbólum fájlok, akkor biztosítani kell, hogy a rendelkezésre álló, hogy a karakter a gép. Abban az esetben, szimbolikus gép DBGHELP.DLL DBG-fájlt fogja keresni azokat a következő helyeken:
- aktuális könyvtárat használja DBGHELP.DLL (nem rosszabb debugger!);
- változó _NT_SYMBOL_PATH környezetben;
- változó _NT_ALT_SYMBOL_PATH környezetben;
- Változó SYSTEMROOT környezetben.
Katalógusok, amelyek azt jelzik, környezeti változók, úgy kell megszervezni, egy bizonyos módon. Például, ha az alkalmazás áll EXE és DLL pár. könyvtárban található: C: \ MyFiles, akkor a könyvtár alatt létre kell hozni a következő alkönyvtárrendszert:
- C: \ MyFiles
- C: \ MyFiles \ szimbólumok
- C: \ MyFiles \ szimbólumok \ Exe
- C: \ MyFiles \ szimbólumok \ Dll
Két nemrégiben alkönyvtár elhelyezésére tervezett mindenkori alkalmazás DBG-fájlokat.
Az egyetlen különbség, ha dolgozik, PDB-fájlok, hogy a karakter fog keresni egy autó DBGHELP.DLL PDB -files az elsődleges alkalmazás könyvtárba, és próbálja meg betölteni az EKT ebből a könyvtárból. Ha a karakter DBGHELP.DLL gép nem lesz képes letölteni PDB-fájlok a könyvtárban, akkor próbálja keresni és letölteni őket csak a DBG-fájlok (pl. E. Ugyanabból alkönyvtárakat, ami kellett létrehozni tárolására debug fájl karakter).
Azaz, minden típusú pályázatát fájlokat egy külön alkönyvtárba DBG-fájlokat. - Szerk.
Hol vannak tárolva a bináris fájlokat az alkalmazás és a megfelelő PDB-fájlok, amelyek által létrehozott összekötő szakaszában hibakeresés épít. - Szerk.
Szerencsére mindannyiunk számára, nem kell írni az egyéni kódot át a köteget. A DBGHELP.DLL felvette egy speciális API-funkció stackwalk. amely gondoskodik az összes munkát a verem. WDBG használja ugyanúgy mint ahogy a C ++ hibakereső Vizuális. Csak az a baj - Nincs részletes dokumentációt stackframe szerkezetét. Listing 4-8 mutatják, csak azokon a területeken, ez a struktúra, amelyet ki kell tölteni. stackwalk funkció így is gondoskodott összes részletet nem lehet tudni, hogy az optimalizált kódot a verem át lehet elég nehéz feladat. Az ok ezeket a nehézségeket abban a tényben rejlik, hogy egyes funkciók a fordító végezhet optimalizálás távol a verem terület, azaz a. E. A hely, ahol tolta ki annak elemeit. Fordítóprogramok Visual C ++ és Visual Basic elég agresszív amikor végre optimalizálás, és ha tudják használni egy halom regiszter mint munkavállaló, akkor fogják csinálni. Munkájának megkönnyítése, a verem az ilyen helyzetekben, a fordító generál egy úgynevezett adat FPO (Frame Pointer kihagyása). FPO-adatok - a táblázat, amely stackwalk funkció kiszámításához használt feldolgozásával kapcsolatos azon funkciók, amelyek hiányoznak a normál terület a verem. Úgy véljük FPO-adatok azért is, mert rájuk hivatkozásokat néha előforduló MSDN és a különböző hibakereső. Lehetőség van, hogy többet tudjon a szerkezet FPO-WINNT.H adatállományban.
Listing 4-8. InitializeStackFrameWithGontext a i386CPUHELP.C
BOOL CPUHELP_DLLINTERFACE _stdcall
InitializeStackFrameWithContext (stackframe * pStack,
ASSERT (FALSE == IsBadReadPtr (pCtx, sizeof (kontextus)));
ASSERT (FALSE == IsBadWritePtr (pStack, sizeof (stackframe))
if ((TRUE == IsBadReadPtr (pCtx, sizeof (kontextus))) ||
(TRUE == IsBadWritePtr (pStack, sizeof (stackframe))))