Scelta dei simboli pubblici da rimuovere
PDBCopy fornisce le opzioni -f e -F in modo che sia possibile rimuovere un set arbitrario di simboli pubblici da un file di simboli rimosso, lasciando solo quei simboli a cui il pubblico deve accedere per eseguire il debug.
Un uso comune di PDBCopy consiste nel creare una versione speciale del file di simboli da usare da Microsoft nel suo programma OCA (Online Crash Analysis). L'OCA può designare alcune funzioni come inert, ovvero se la funzione viene trovata nella traccia dello stack viene ignorata. Una funzione viene in genere dichiarata inert se è semplicemente una funzione wrapper o "pass-through" che non esegue calcoli significativi. Se tale funzione viene trovata nello stack in un'analisi di errore, si può presumere che questa funzione stessa non fosse in errore e alla maggior parte dei dati passati ai dati non validi o danneggiati ricevuti dalle routine in precedenza nello stack. Ignorando tali funzioni, OCA può determinare meglio la causa effettiva dell'errore o del danneggiamento.
Naturalmente, qualsiasi funzione che si desidera dichiarare "inert" deve essere inclusa nella tabella dei simboli pubblici del file di simboli usato da OCA. Tuttavia, queste non sono le uniche funzioni che devono essere incluse, come illustrato nell'esempio seguente.
Si supponga di scrivere un driver Windows e di usare PDBCopy per rimuovere tutti i simboli pubblici dal file di simboli, ad eccezione di FunctionOne e FunctionSix, due funzioni inert. L'aspettativa è che, se functionOne o FunctionSix vengono trovati nello stack dopo un arresto anomalo, verranno ignorati da OCA. Se qualsiasi altra parte del driver si trova nello stack, Microsoft ti fornirà l'indirizzo di memoria corrispondente e puoi usare l'indirizzo per eseguire il debug del driver.
Tuttavia, si supponga che il driver occupa memoria nel layout seguente:
Indirizzo | Contenuto della memoria |
---|---|
0x1000 |
Indirizzo di base del modulo |
0x2000 |
Inizio di FunctionOne |
0x203F |
Fine di FunctionOne |
0x3000 |
Inizio di FunctionSix |
0x305F |
Fine di FunctionSix |
0x7FFF |
Fine del modulo in memoria |
Se il debugger trova un indirizzo nello stack, seleziona il simbolo con l'indirizzo inferiore successivo. Poiché la tabella dei simboli pubblici contiene l'indirizzo di ogni simbolo, ma non è possibile che il debugger sappia se un indirizzo rientra effettivamente nei limiti di qualsiasi simbolo specifico.
Pertanto, se si verifica un errore all'indirizzo 0x2031, il debugger eseguito da Microsoft OCA identifica correttamente l'errore come in FunctionOne. Poiché si tratta di una funzione inert, il debugger continua a camminare lo stack per trovare la causa dell'arresto anomalo.
Tuttavia, se si verifica un errore in 0x2052, il debugger corrisponde ancora a FunctionOne, anche se si trova oltre la fine effettiva di questa funzione (0x203F).
Di conseguenza, è necessario includere nel file simbolo rimosso non solo le funzioni che si desidera esporre, ma anche i simboli immediatamente successivi a queste funzioni. In questo esempio si vuole esporre FunctionOne, FunctionTwo, FunctionSix eFunctionSeven:
Indirizzo | Contenuto della memoria |
---|---|
0x1000 |
Indirizzo di base del modulo |
0x2000 |
Inizio di FunctionOne |
0x203F |
Fine di FunctionOne |
0x2040 |
Inizio della funzioneTwo |
0x3000 |
Inizio di FunctionSix |
0x305F |
Fine di FunctionSix |
0x3060 |
Inizio di FunctionSeven |
0x7FFF |
Fine del modulo in memoria |
Se si includono tutte e quattro queste funzioni nel file di simboli rimosso, l'analisi microsoft OCA non considera erroneamente l'indirizzo 0x2052 come parte di FunctionOne. In questo esempio si presuppone che questo indirizzo faccia parte di FunctionTwo, ma che non è importante perché non è stato registrato FunctionTwo con OCA come funzione inert. L'aspetto importante è che l'indirizzo 0x2052 viene riconosciuto come non rientrano all'interno di una funzione inert, e pertanto OCA riconoscerà questo come errore significativo all'interno del driver e può informare l'utente dell'errore.
Se non si desidera pubblicizzare i nomi delle funzioni che seguono ogni funzione inert, è possibile inserire funzioni non importanti nel codice seguendo ogni funzione inert in modo che i nomi di queste funzioni possano essere inclusi nel file di simboli pubblici. Assicurarsi di verificare che queste funzioni aggiunte eseguano effettivamente le funzioni inert nello spazio indirizzi del file binario, poiché alcune routine di ottimizzazione possono modificare questa operazione o anche rimuovere completamente alcune funzioni.