Veřejné a soukromé symboly

Pokud soubor symbolů .pdb nebo .dbg v plné velikosti sestaví linker, obsahuje dvě odlišné kolekce informací: data privátních symbolů a tabulku veřejných symbolů. Tyto kolekce se liší v seznamu položek, které obsahují, a informace, které o každé položce ukládají.

Data privátních symbolů zahrnují následující položky:

  • Functions

  • Globální proměnné

  • Místní proměnné

  • Informace o uživatelem definovaných strukturách, třídách a datových typech

  • Název zdrojového souboru a číslo řádku v daném souboru odpovídající jednotlivým binárním instrukcím

Tabulka veřejných symbolů obsahuje méně položek:

  • Funkce (s výjimkou funkcí deklarovaných jako statické)

  • Globální proměnné zadané jako extern (a všechny ostatní globální proměnné viditelné ve více souborech objektů)

Obecně platí, že tabulka veřejných symbolů obsahuje přesně ty položky, které jsou přístupné z jednoho zdrojového souboru do jiného. Položky viditelné pouze v jednom souboru objektu, například ve statických funkcích, proměnných globálních pouze v rámci jednoho zdrojového souboru a místní proměnné – nejsou zahrnuty do tabulky veřejných symbolů.

Tyto dvě kolekce dat se také liší v tom, jaké informace obsahují pro každou položku. Pro každou položku obsaženou v datech privátních symbolů jsou obvykle zahrnuty následující informace:

  • Název položky

  • Adresa položky ve virtuální paměti

  • Datový typ každé proměnné, struktury a funkce

  • Typy a názvy parametrů pro každou funkci

  • Rozsah každé místní proměnné

  • Symboly přidružené ke každému řádku v každém zdrojovém souboru

  • Vynechání ukazatele rámce (FPO) záznamů pro každou funkci využitou k přístupu ke zásobníku

Na druhé straně veřejná tabulka symbolů ukládá pouze následující informace o každé položce, která je v ní zahrnuta:

  • Název položky.

  • Adresa položky ve virtuálním paměťovém prostoru jeho modulu. U funkce se jedná o adresu jejího vstupního bodu.

  • Záznamy o vynechání ukazatelů rámce pro každou funkci.

  • Může obsahovat předponu symbolu nebo přípony, které se označují jako dekorace.

Data veřejných symbolů lze považovat za podmnožinu dat privátních symbolů dvěma způsoby: obsahuje kratší seznam položek a obsahuje také méně informací o každé položce. Například data veřejných symbolů neobsahují vůbec místní proměnné.

Každá místní proměnná je zahrnuta pouze v datech privátních symbolů s jeho adresou, datovým typem a oborem. Funkce jsou na druhé straně zahrnuty jak v datech privátních symbolů, tak v tabulce veřejných symbolů, ale i když data privátních symbolů zahrnují název funkce, adresu, záznamy FPO, názvy vstupních parametrů a typy a výstupní typ, veřejná tabulka symbolů zahrnuje jenom název funkce, adresu a záznam FPO.

Mezi daty privátních symbolů a tabulkou veřejných symbolů je ještě jeden rozdíl. Mnoho položek v tabulce veřejných symbolů má názvy, které jsou zdobené předponou, příponou nebo obojím. Tyto dekorace jsou přidány kompilátorem jazyka C, kompilátorem C++ a assemblerem MASM. Mezi typické předpony patří řada podtržítek nebo řetězec __imp_ (označující importovanou funkci). Typické přípony zahrnují jeden nebo více znaků ( @ ) následovaných adresami nebo jinými identifikačními řetězci. Tyto dekorace používá linker k rozlišení symbolu, protože je možné, že názvy funkcí nebo názvy globálních proměnných se mohou opakovat v různých modulech. Tyto dekorace jsou výjimkou obecného pravidla, že tabulka veřejných symbolů je podmnožinou dat privátních symbolů.

Soubory s úplnými symboly a soubory bez symbolů

Úplný soubor symbolů obsahuje jak data privátních symbolů, tak i tabulku veřejných symbolů. Tento typ souboru se někdy označuje jako soubor privátního symbolu, ale tento název je zavádějící, pro takový soubor obsahuje soukromé i veřejné symboly.

Pruhovaný soubor symbolů je menší soubor, který obsahuje pouze tabulku veřejných symbolů – nebo v některých případech pouze podmnožinu veřejné tabulky symbolů. Tento soubor se někdy označuje jako soubor veřejného symbolu.

Vytváření úplných a pruhovaných souborů symbolů

Pokud vytváříte binární soubory pomocí sady Visual Studio, můžete vytvořit soubory s úplnými nebo proříznutými symboly. Informace o vytváření ořezaných (stripped) symbolů najdete v tématu /PDBSTRIPPED (ořezané soukromé symboly).

Pomocí nástroje BinPlace můžete z celého souboru symbolů vytvořit soubor se zjednodušenými symboly. Pokud se použijí nejběžnější možnosti BinPlace (-a -x -s -n), soubory se odepsaných symbolů umístí do adresáře, který je uveden za přepínačem -s , a úplné soubory symbolů se umístí do adresáře, který je uveden za přepínačem -n . Když BinPlace odstraní symbol ze souboru, ořezaná a úplná verze souboru mají stejný podpis a další identifikační informace. To vám umožní použít kteroukoli verzi pro ladění. Další informace o BinPlace naleznete v tématu BinPlace.

Pomocí nástroje PDBCopy můžete vytvořit odstraněný soubor symbolů z celého souboru symbolů odebráním dat privátních symbolů. PdBCopy může také odebrat zadanou podmnožinu tabulky veřejných symbolů. Podrobnosti najdete v PDBCopy.

Pomocí nástroje SymChk můžete určit, jestli soubor symbolů obsahuje soukromé symboly. Podrobnosti najdete v tématu SymChk.

Zobrazení veřejných a soukromých symbolů v ladicím programu

K zobrazení symbolů můžete použít WinDbg, KD nebo CDB. Pokud má jeden z těchto ladicích programů přístup k úplnému souboru symbolů, má k dispozici informace uvedené v souboru privátních symbolů i informace uvedené v souboru veřejných symbolů. Data veřejných symbolů obsahují dekorace symbolů.

Při přístupu k soukromým symbolům se data privátních symbolů vždy používají, protože tyto symboly nejsou zahrnuty do tabulky veřejných symbolů. Tyto symboly nejsou nikdy zdobeny.

Příkaz .symopt (Nastavit možnosti symbolů) lze použít k řízení možností symbolů , které určují, jak ladicí program používá veřejné a soukromé symboly. Tento příkaz například zapne informace o ladění symbolů.

 .symopt+ 0x80000000

Následující možnosti mění způsob použití veřejných a soukromých symbolů v ladicím programu.

  • Pokud je zapnutá možnost SYMOPT_UNDNAME , při zobrazení názvu veřejného symbolu se dekorace nezahrnou. Při hledání symbolů se navíc dekorace ignorují. Když je tato možnost vypnutá, dekorace se zobrazí při zobrazování veřejných symbolů a dekorace se používají při hledání. Soukromé symboly nejsou nikdy zdobeny za žádných okolností. Tato možnost je ve výchozím nastavení zapnutá ve všech ladicích programech.

  • Pokud je možnost SYMOPT_PUBLICS_ONLY zapnutá, data privátních symbolů se ignorují a použije se pouze tabulka veřejných symbolů. Tato možnost je ve výchozím nastavení vypnutá ve všech ladicích programech.

  • Pokud je zapnutá možnost SYMOPT_NO_PUBLICS, veřejná tabulka symbolů se ignoruje a vyhledávání a informace o symbolech používají pouze data soukromých symbolů. Tato možnost je ve výchozím nastavení vypnutá ve všech ladicích programech.

  • Když je zapnutá možnost SYMOPT_AUTO_PUBLICS (a SYMOPT_PUBLICS_ONLY i SYMOPT_NO_PUBLICS jsou vypnuté), provede se první hledání symbolů v datech privátních symbolů. Pokud tam najdete požadovaný symbol, hledání se ukončí. Pokud ne, prohledá se veřejná tabulka symbolů. Vzhledem k tomu, že tabulka veřejných symbolů obsahuje podmnožinu symbolů v privátních datech, obvykle to vede k ignorování veřejné tabulky symbolů.

  • Když jsou všechny možnosti SYMOPT_PUBLICS_ONLY, SYMOPT_NO_PUBLICS a SYMOPT_AUTO_PUBLICS vypnuté, prohledávají se data privátních symbolů i tabulka veřejných symbolů pokaždé, když je potřeba symbol. Pokud se ale shody nacházejí na obou místech, použije se shoda v datech privátních symbolů. Proto chování v této instanci je stejné jako při SYMOPT_AUTO_PUBLICS je zapnuto, s tím rozdílem, že použití SYMOPT_AUTO_PUBLICS může způsobit, že hledání symbolů bude trochu rychlejší.

Tady je příklad, ve kterém se třikrát používá příkaz x (Prozkoumat symboly ). Při prvním použití se použijí výchozí možnosti symbolů, takže informace pocházejí z dat privátních symbolů. Všimněte si, že obsahuje informace o adrese, velikosti a datovém typu pole typingString. Dále se příkaz .symopt+ 4000 používá, což způsobí, že ladicí program ignoruje data privátních symbolů. Když se příkaz x spustí znovu, použije se tabulka veřejných symbolů; tentokrát neexistuje žádná velikost a informace o datovém typu pro typingString. Nakonec se použije příkaz .symopt- 2, což způsobí, že ladicí program zahrne dekorace. Když se příkaz x spustí naposledy, zobrazí se dekorovaná verze názvu funkce _typingString.

0:000> x /t /d *!*typingstring* 
00434420 char [128] TimeTest!typingString = char [128] ""

0:000> .symopt+ 4000

0:000> x /t /d *!*typingstring* 
00434420 <NoType> TimeTest!typingString = <no type information>

0:000> .symopt- 2

0:000> x /t /d *!*typingstring* 
00434420 <NoType> TimeTest!_typingString = <no type information> 

Zobrazení veřejných a privátních symbolů pomocí nástroje DBH

Dalším způsobem zobrazení symbolů je použití nástroje DBH . Zobrazte možnosti nápovědy pomocí této /? možnosti.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh /?
dbh dbghelp shell
usage: dbh [-n] [-c] [-d] [-?] [-??] [-p] [targetmodule] [command]
       [-n]             display noisy symbol spew
       [-d]             use decorated publics
       [-p:XXXX]        attaches to process ID XXXX
       [-s:SSSS]        set symbol path to SSSS
       [-c]             callbacks return false
       [targetmodule]   load symbols for specified module
       [command]        execute command and exit
       [-?]             display these usage instructions
       [-??]            display detailed usage instructions

Pomocí nástroje, jako je Tlist, vypisujte ID procesů a možnost -p použijte k připojení k existujícímu procesu.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh -p:4308

DBH používá stejné možnosti symbolů jako ladicí program. Stejně jako ladicí program, DBH ve výchozím nastavení ponechává SYMOPT_PUBLICS_ONLY a SYMOPT_NO_PUBLICS vypnuté a zapíná SYMOPT_UNDNAME a SYMOPT_AUTO_PUBLICS ve výchozím nastavení. Tyto výchozí hodnoty lze přepsat pomocí možnosti příkazového řádku nebo pomocí příkazu DBH.

Tady je příklad, ve kterém se třikrát používá příkaz DBH addr 414fe0. Při prvním použití se použijí výchozí možnosti symbolů, takže informace pocházejí z dat privátních symbolů. Všimněte si, že to zahrnuje informace o adrese, velikosti a datovém typu funkce fgets. Dále se použije příkaz symopt +4000, což způsobí, že DBH ignoruje data privátních symbolů. Při opětovném spuštění adresy 414fe0 se použije tabulka veřejných symbolů; tentokrát není k dispozici žádná velikost a informace o datovém typu pro funkci fgets. Nakonec se použije příkaz symopt -2, což způsobí, že DBH bude obsahovat dekorace. Když je spuštěna adresa 414fe0 tentokrát, zobrazí se upravená verze názvu funkce _fgets.

pid:4308 mod:TimeTest[400000]: addr 414fe0

fgets
   name : fgets
   addr :   414fe0
   size : 113
  flags : 0
   type : 7e
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagFunction (5)
  index : 7d

pid:4308 mod:TimeTest[400000]: symopt +4000

Symbol Options: 0x10c13
Symbol Options: 0x14c13

pid:4308 mod:TimeTest[400000]: addr 414fe0

fgets
   name : fgets
   addr :   414fe0
   size : 0
  flags : 0
   type : 0
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagPublicSymbol (a)
  index : 7f

pid:4308 mod:TimeTest[400000]: symopt -2

Symbol Options: 0x14c13
Symbol Options: 0x14c11

pid:4308 mod:TimeTest[400000]: addr 414fe0

_fgets
   name : _fgets
   addr :   414fe0
   size : 0
  flags : 0
   type : 0
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagPublicSymbol (a)
  index : 7f 

Další informace

Další informace o symbolech najdete v tématu Syntaxe symbolů a Porovnávání symbolů, Možnosti symbolů, Zkratky stavu symbolů a Načítání odložených symbolů.