Auswählen der zu entfernenden öffentlichen Symbole
PDBCopy stellt die Optionen -f und -F bereit, sodass Sie einen beliebigen Satz öffentlicher Symbole aus einer Stripped-Symboldatei entfernen können, sodass nur die Symbole übrig bleiben, auf die Ihre Zielgruppe zugreifen muss, um ihr Debuggen durchzuführen.
Eine häufige Verwendung von PDBCopy besteht darin, eine spezielle Version Ihrer Symboldatei zur Verwendung durch Microsoft im OCA-Programm (Online Crash Analysis) zu erstellen. OCA kann bestimmte Funktionen als inert festlegen, was bedeutet, dass sie ignoriert wird, wenn die Funktion auf der Stapelverfolgung gefunden wird. Eine Funktion wird in der Regel als inert deklariert, wenn es sich lediglich um einen Wrapper oder eine "Passthrough"-Funktion handelt, die keine wesentlichen Berechnungen ausführt. Wenn eine solche Funktion in einer Fehleranalyse auf dem Stapel gefunden wird, kann davon ausgegangen werden, dass diese Funktion selbst nicht fehlerhaft war und höchstens ungültige oder beschädigte Daten übergeben hat, die sie zuvor auf dem Stapel von Routinen empfangen hat. Durch Ignorieren solcher Funktionen kann OCA die tatsächliche Ursache des Fehlers oder der Beschädigung besser ermitteln.
Natürlich muss jede Funktion, die Sie als "inert" deklarieren möchten, in die öffentliche Symboltabelle der von OCA verwendeten Symboldatei aufgenommen werden. Dies sind jedoch nicht die einzigen Funktionen, die eingeschlossen werden müssen, wie das folgende Beispiel zeigt.
Angenommen, Sie schreiben einen Windows-Treiber und verwenden PDBCopy, um alle öffentlichen Symbole aus der Symboldatei zu entfernen, mit Ausnahme von FunctionOne und FunctionSix, zwei inerten Funktionen. Sie erwarten, dass sie von OCA ignoriert werden, wenn entweder FunctionOne oder FunctionSix nach einem Absturz auf dem Stapel gefunden werden. Wenn sich ein anderer Teil Ihres Treibers im Stapel befindet, stellt Microsoft Ihnen die entsprechende Speicheradresse zur Verfügung, und Sie können die Adresse verwenden, um Ihren Treiber zu debuggen.
Angenommen, Ihr Treiber belegt Arbeitsspeicher im folgenden Layout:
Adresse | Inhalt des Arbeitsspeichers |
---|---|
0x1000 |
Basisadresse des Moduls |
0x2000 |
Beginn von FunctionOne |
0x203F |
Ende von FunctionOne |
0x3000 |
Anfang von FunctionSix |
0x305F |
Ende von FunctionSix |
0x7FFF |
Ende des Moduls im Arbeitsspeicher |
Wenn der Debugger eine Adresse auf dem Stapel findet, wählt er das Symbol mit der nächsten unteren Adresse aus. Da die öffentliche Symboltabelle die Adresse jedes Symbols enthält, aber keine Größeninformationen enthält, kann der Debugger nicht wissen, ob eine Adresse tatsächlich innerhalb der Grenzen eines bestimmten Symbols liegt.
Wenn daher ein Fehler an der Adresse 0x2031 auftritt, identifiziert der von Microsoft OCA ausgeführte Debugger den Fehler korrekt als in FunctionOne liegt. Da es sich um eine inerte Funktion handelt, führt der Debugger den Stapel weiter, um die Ursache des Absturzes zu ermitteln.
Wenn jedoch bei 0x2052 ein Fehler auftritt, stimmt der Debugger diese Adresse trotzdem mit FunctionOne überein, auch wenn sie über das tatsächliche Ende dieser Funktion hinaus liegt (0x203F).
Daher müssen Sie nicht nur die Funktionen, die Sie verfügbar machen möchten, sondern auch die Symbole, die unmittelbar auf diese Funktionen folgen, in die Datei mit dem entfernten Symbol aufnehmen. In diesem Beispiel möchten Sie FunctionOne, FunctionTwo, FunctionSix und FunctionSeven verfügbar machen:
Adresse | Inhalt des Arbeitsspeichers |
---|---|
0x1000 |
Basisadresse des Moduls |
0x2000 |
Beginn von FunctionOne |
0x203F |
Ende von FunctionOne |
0x2040 |
Anfang von FunctionTwo |
0x3000 |
Anfang von FunctionSix |
0x305F |
Ende von FunctionSix |
0x3060 |
Anfang von FunctionSeven |
0x7FFF |
Ende des Moduls im Arbeitsspeicher |
Wenn Sie alle vier Funktionen in die Stripped-Symboldatei aufnehmen, wird die Adresse 0x2052 nicht versehentlich von der Microsoft OCA-Analyse als Teil von FunctionOne behandelt. In diesem Beispiel wird davon ausgegangen, dass diese Adresse Teil von FunctionTwo ist, aber das ist nicht wichtig, da Sie FunctionTwo nicht bei OCA als inerte Funktion registriert haben. Wichtig ist, dass die Adresse 0x2052 als nicht in eine inerte Funktion fällt, und daher erkennt die OCA dies als einen sinnvollen Fehler in Ihrem Treiber und kann Sie über den Fehler informieren.
Wenn Sie die Namen der Funktionen nach jeder inerten Funktion nicht veröffentlichen möchten, können Sie nach jeder inerten Funktion unwichtige Funktionen in Ihren Code einfügen, sodass die Namen dieser Funktionen in Ihre öffentliche Symboldatei aufgenommen werden können. Vergewissern Sie sich, dass diese hinzugefügten Funktionen tatsächlich Ihren inerten Funktionen im Adressraum Ihrer Binärdatei folgen, da einige Optimierungsroutinen dies ändern oder sogar einige Funktionen vollständig entfernen können.