Simboli pubblici e privati

Quando un file di simboli con estensione pdb o dbg di dimensioni complete viene compilato da un linker, contiene due raccolte distinte di informazioni: i dati dei simboli privati e una tabella di simboli pubblici. Queste raccolte differiscono nell'elenco di elementi che contengono e le informazioni che archiviano su ogni elemento.

I dati dei simboli privati includono gli elementi seguenti:

  • Funzioni

  • Variabili globali

  • Variabili locali

  • Informazioni sulle strutture, le classi e i tipi di dati definiti dall'utente

  • Nome del file di origine e numero di riga nel file corrispondente a ogni istruzione binaria

La tabella dei simboli pubblici contiene meno elementi:

  • Funzioni (ad eccezione delle funzioni dichiarate statiche)

  • Variabili globali specificate come extern (e qualsiasi altra variabile globale visibile tra più file di oggetti)

Come regola generale, la tabella dei simboli pubblici contiene esattamente gli elementi accessibili da un file di origine a un altro. Gli elementi visibili in un solo file oggetto, ad esempio funzioni statiche , variabili globali solo all'interno di un singolo file di origine e variabili locali, non sono incluse nella tabella dei simboli pubblici.

Queste due raccolte di dati differiscono anche nelle informazioni incluse per ogni elemento. Le informazioni seguenti vengono in genere incluse per ogni elemento contenuto nei dati dei simboli privati :

  • Nome dell'elemento

  • Indirizzo dell'elemento nella memoria virtuale

  • Tipo di dati di ogni variabile, struttura e funzione

  • Tipi e nomi dei parametri per ogni funzione

  • Ambito di ogni variabile locale

  • Simboli associati a ogni riga in ogni file di origine

  • Record di omissione del puntatore del frame (FPO) per ogni funzione usata per accedere allo stack

D'altra parte, la tabella dei simboli pubblici archivia solo le informazioni seguenti su ogni elemento incluso in esso:

  • Nome dell'elemento.

  • Indirizzo dell'elemento nello spazio di memoria virtuale del relativo modulo. Per una funzione, si tratta dell'indirizzo del punto di ingresso.

  • Record FPO (Frame Pointer Omission) per ogni funzione.

  • Può includere prefissi simboli/suffissi denominati decorazioni.

I dati dei simboli pubblici possono essere considerati come subset dei dati dei simboli privati in due modi: contiene un elenco più breve di elementi e contiene anche meno informazioni su ogni elemento. Ad esempio, i dati dei simboli pubblici non includono variabili locali.

Ogni variabile locale è inclusa solo nei dati dei simboli privati, con il relativo indirizzo, tipo di dati e ambito. Le funzioni, d'altra parte, sono incluse sia nella tabella dei simboli privati che nella tabella dei simboli pubblici, ma mentre i dati dei simboli privati includono il nome della funzione, l'indirizzo, i record FPO, i nomi dei parametri di input e i tipi e il tipo di output, la tabella dei simboli pubblici include solo il nome della funzione, l'indirizzo e il record FPO.

Esiste un'altra differenza tra i dati dei simboli privati e la tabella dei simboli pubblici. Molti degli elementi della tabella dei simboli pubblici hanno nomi decorati con un prefisso, un suffisso o entrambi. Queste decorazioni vengono aggiunte dal compilatore C, dal compilatore C++ e dall'assembler MASM. I prefissi tipici includono una serie di caratteri di sottolineatura o la stringa __imp_ (progettazione di una funzione importata). I suffisso tipici includono uno o più segni ( @ ) seguiti da indirizzi o altre stringhe di identificazione. Queste decorazioni vengono usate dal linker per disambiguare il simbolo, poiché è possibile che i nomi delle funzioni o i nomi delle variabili globali possano essere ripetuti tra moduli diversi. Queste decorazioni sono un'eccezione alla regola generale che la tabella dei simboli pubblici è un subset dei dati dei simboli privati.

File di simboli completi e file di simboli rimossi

Un file simbolo completo contiene sia i dati dei simboli privati che la tabella dei simboli pubblici. Questo tipo di file viene talvolta definito come file di simbolo privato, ma questo nome è fuorviante, per tale file contiene simboli privati e pubblici.

Un file di simboli rimosso è un file più piccolo che contiene solo la tabella dei simboli pubblici, oppure, in alcuni casi, solo un subset della tabella dei simboli pubblici. Questo file viene talvolta definito file di simbolo pubblico.

Creazione di file di simboli completi e rimossi

Se si compilano i file binari con Visual Studio, è possibile creare file simboli completi o rimossi. Per informazioni sulla compilazione di simboli rimossi, vedere /PDBSTRIPPED (Strip Private Symbols).

Usando lo strumento BinPlace, è possibile creare un file di simboli rimosso da un file simbolo completo. Quando vengono usate le opzioni BinPlace più comuni (-a -x -s -n), i file di simboli rimossi vengono inseriti nella directory elencata dopo l'opzione - s e i file di simboli completi vengono inseriti nella directory elencata dopo l'opzione -n . Quando BinPlace esegue la striping di un file di simboli, le versioni rimosse e complete del file vengono fornite firme identiche e altre informazioni di identificazione. In questo modo è possibile usare entrambe le versioni per il debug. Per altre informazioni su BinPlace, vedere BinPlace.

Usando lo strumento PDBCopy, è possibile creare un file di simboli rimosso da un file simbolo completo rimuovendo i dati dei simboli privati. PDBCopy può anche rimuovere un subset specificato della tabella dei simboli pubblici. Per informazioni dettagliate, vedere PDBCopy.

Usando lo strumento SymChk, è possibile determinare se un file di simboli contiene simboli privati. Per informazioni dettagliate, vedere SymChk.

Visualizzazione di simboli pubblici e privati nel debugger

È possibile usare WinDbg, KD o CDB per visualizzare i simboli. Quando uno di questi debugger ha accesso a un file di simboli completo, contiene sia le informazioni elencate nei dati dei simboli privati che le informazioni elencate nella tabella dei simboli pubblici. I dati dei simboli pubblici contengono decorazioni dei simboli.

Quando si accede ai simboli privati, i dati dei simboli privati vengono sempre usati perché questi simboli non sono inclusi nella tabella dei simboli pubblici. Questi simboli non vengono mai decorati.

Il comando con estensione symopt (Set Symbol Options) può essere usato per controllare le opzioni dei simboli che determinano il modo in cui vengono usati i simboli pubblici e privati dal debugger. Ad esempio, questo comando attiva le informazioni di debug dei simboli.

 .symopt+ 0x80000000

Le opzioni seguenti modificano il modo in cui vengono usati simboli pubblici e privati nel debugger.

  • Quando l'opzione SYMOPT_UNDNAME è attiva, le decorazioni non vengono incluse quando viene visualizzato il nome di un simbolo pubblico. Inoltre, quando si cerca simboli, le decorazioni vengono ignorate. Quando questa opzione è disattivata, le decorazioni vengono visualizzate durante la visualizzazione di simboli pubblici e le decorazioni vengono usate nelle ricerche. I simboli privati non vengono mai decorati in nessuna circostanza. Questa opzione è attivata per impostazione predefinita in tutti i debugger.

  • Quando l'opzione SYMOPT_PUBLICS_ONLY è attiva, i dati dei simboli privati vengono ignorati e viene usata solo la tabella dei simboli pubblici. Questa opzione è disattivata per impostazione predefinita in tutti i debugger.

  • Quando l'opzione SYMOPT_NO_PUBLICS è attiva, la tabella dei simboli pubblici viene ignorata e le informazioni sui simboli e le ricerche usano solo i dati dei simboli privati. Questa opzione è disattivata per impostazione predefinita in tutti i debugger.

  • Quando l'opzione SYMOPT_AUTO_PUBLICS è attiva (e sia SYMOPT_PUBLICS_ONLY che SYMOPT_NO_PUBLICS sono disattivate), la prima ricerca dei simboli viene eseguita nei dati dei simboli privati. Se viene trovato il simbolo desiderato, la ricerca termina. In caso contrario, la tabella dei simboli pubblici viene eseguita la ricerca. Poiché la tabella dei simboli pubblici contiene un subset dei simboli nei dati privati, in genere ciò comporta l'ignorare nella tabella dei simboli pubblici.

  • Quando le SYMOPT_PUBLICS_ONLY, SYMOPT_NO_PUBLICS e le opzioni di SYMOPT_AUTO_PUBLICS sono disattivate, i dati dei simboli privati e la tabella dei simboli pubblici vengono cercati ogni volta che è necessario un simbolo. Tuttavia, quando le corrispondenze vengono trovate in entrambe le posizioni, viene usata la corrispondenza nei dati dei simboli privati. Pertanto, il comportamento in questa istanza è uguale a quando SYMOPT_AUTO_PUBLICS è attivo, ad eccezione del fatto che l'uso di SYMOPT_AUTO_PUBLICS può causare una ricerca dei simboli leggermente più veloce.

Ecco un esempio in cui viene usato il comando x (Esamina simboli) tre volte. La prima volta, vengono usate le opzioni dei simboli predefinite e quindi le informazioni vengono acquisite dai dati dei simboli privati. Si noti che include informazioni sull'indirizzo, le dimensioni e il tipo di dati della matrice digitandoString. Successivamente, viene usato il comando .symopt+ 4000, causando all'utente di ignorare i dati dei simboli privati. Quando viene eseguito di nuovo il comando x , viene usata la tabella dei simboli pubblici; questa volta non è disponibile alcuna dimensione e informazioni sul tipo di dati per la digitazionestring. Infine, viene usato il comando .symopt- 2, che causa l'inclusione del debugger. Quando il comando x viene eseguito questa ultima volta, viene visualizzata la versione decorata del nome della funzione , _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> 

Visualizzazione di simboli pubblici e privati con lo strumento DBH

Un altro modo per visualizzare i simboli consiste nell'usare lo strumento DBH . Visualizzare le opzioni della Guida usando l'opzione /? .

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

Usare uno strumento come Tlist per elencare gli ID di processo e l'opzione -p da collegare a un processo esistente.

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

DBH usa le stesse opzioni di simboli del debugger. Analogamente al debugger, DBH lascia SYMOPT_PUBLICS_ONLY e SYMOPT_NO_PUBLICS disattivata per impostazione predefinita e attiva SYMOPT_UNDNAME e SYMOPT_AUTO_PUBLICS per impostazione predefinita. Queste impostazioni predefinite possono essere sostituite da un'opzione della riga di comando o da un comando DBH.

Di seguito è riportato un esempio in cui il componente aggiuntivo del comando DBH 414fe0 viene usato tre volte. La prima volta vengono usate le opzioni dei simboli predefinite e quindi le informazioni vengono ricavate dai dati dei simboli privati. Si noti che sono incluse informazioni sull'indirizzo, le dimensioni e il tipo di dati della funzione fgets. Viene quindi usato il comando symopt +4000, che fa sì che DBH ignori i dati dei simboli privati. Quando il componente aggiuntivo 414fe0 viene eseguito di nuovo, viene usata la tabella dei simboli pubblici; questa volta non sono presenti informazioni sulle dimensioni e sul tipo di dati per le funzioni fget. Infine, viene usato il comando symopt -2, che fa sì che DBH includa decorazioni. Quando il componente aggiuntivo 414fe0 viene eseguito questa ultima volta, viene visualizzata la versione decorata del nome della funzione , _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 

Informazioni aggiuntive

Per altre informazioni sui simboli, vedere sintassi dei simboli e corrispondenza dei simboli, opzioni dei simboli, abbreviazioni dello stato dei simboli e caricamento posticipato dei simboli.