Wenn Sie die nicht verwaltete API für das .NET-Framework verwenden, um einen prozessinternen .NET-Prozess zu profilieren, ist es möglich, den IL-Anweisungszeiger nachzuschlagen, der dem nativen Anweisungszeiger der StackSnapshotCallback-Funktion entspricht?
Wie es wahrscheinlich ist, mache ich einen Schnappschuss des aktuellen Stapels und möchte Informationen zur Datei- und Zeilennummer im Stapelspeicher bereitstellen. Der Verwaltete Stack-Explorer erledigt dies, indem er ISymUnmanagedMethod::GetSequencePoints
abfragt. Das ist großartig, aber die Sequenzpunkte sind Offsets zugeordnet, und ich habe bisher angenommen, dass es Offsets vom Anfang der Methode sind (in der Zwischensprache).
In einem Follow-up-Kommentar zu seinem Blogpost Profiler Stack Walking: Grundlagen und darüber hinaus gibt David Broman an, dass diese Zuordnung mit ICorDebugCode::GetILToNativeMapping
erreicht werden kann. Dies ist jedoch nicht ideal, da das Abrufen dieser Schnittstelle von einem anderen Debuggerprozess an meinen Prozess angehängt werden muss.
Ich möchte diesen Schritt vermeiden, weil ich weiterhin meine Anwendung aus dem Visual Studio-Debugger heraus ausführen möchte, während ich diese Momentaufnahmen mache. Es macht es einfacher, auf die Zeilennummer im Ausgabefenster zu klicken und zu dem betreffenden Code zu gehen.
Die Funktionalität ist möglich .... Sie können eine Zeile mit nummerierten Stack-Traces nach Belieben innerhalb von verwaltetem Code ausgeben, die einzige Frage, auf die zugegriffen werden kann. Außerdem möchte ich die Funktionalität System::Diagnostics::StackTrace
oder System::Environment::StackTrace
nicht verwenden, da ich aus Performance-Gründen den tatsächlichen Speicherauszug des Stacks verzögern muss ... und somit die Kosten für die Auflösung der Methodennamen und den Code-Speicherort sparen für später ist wünschenswert ... zusammen mit der Fähigkeit, native und verwaltete Frames zu mischen.
Um von einem nativen Anweisungszeiger, der von ICorProfilerInfo2::DoStackSnapshot
bereitgestellt wird, in einen Zwischensprachenmethodenoffset zu übersetzen, müssen Sie zwei Schritte ausführen, da DoStackSnapshot
einen FunctionID
und nativen Anweisungszeiger als virtuelle Speicheradresse bereitstellt.
Schritt 1 besteht darin, den Befehlszeiger in einen systemeigenen Code-Offset zu konvertieren. (ein Offset vom Anfang der JITed-Methode). Dies kann mit ICorProfilerInfo2::GetCodeInfo2
Schritt 2. Sobald Sie einen Offset vom Anfang der natvie-Code-Methode haben, können Sie dies verwenden, um vom Anfang der intermediate language Methode zu einem Offset zu konvertieren, indem Sie ICorProfilerInfo2::GetILToNativeMapping
verwenden.
Dies kann dann verwendet werden, um den Code-Ort mithilfe der Symbol-APIs einer Datei- und Zeilennummer zuzuordnen
Danke Mithun Shanbhag für Richtung in der Suche nach der Lösung.
Stellen Sie sicher, dass Ihr Build Symbole generiert.
Erweitern Sie die Diskussion:
Wie es wahrscheinlich ist, mache ich einen Schnappschuss des aktuellen Stapels und möchte Informationen über die Datei- und Zeilennummer im Stapelspeicher bereitstellen.
Vorrausgesetzt - Es sieht so aus, als sei der einzige Grund, dass Sie nicht an den Prozess anhängen, dass Sie Ihr Tool oder Teile davon einfach debuggen können, während Sie es entwickeln. Diese IMO ist eine schlechte Ausrede dafür, kein besseres Design zu wählen (ICorDebug oder w / e), wenn es verfügbar ist. Der Grund dafür ist, dass Ihr Code im Prozessraum von (vermutlich) externen Binärdateien ausgeführt wird und in bekannten (oder schlimmer - unbekannten) korrupten Prozesszuständen unangenehme ("manchmal" seltene) Nebenwirkungen (einschließlich der Beschädigung anderer Daten) verursacht. Das sollte schon genug sein, aber auch sonst gibt es mehrere Randfälle mit Multithreading-Code usw., bei denen das Design umgangen werden muss.
Die meisten Leute fragen im Allgemeinen: "Was versuchst du wirklich zu tun?" als Antwort auf eine offensichtlich komplexe Art, Dinge zu tun. In meisten Fällen gibt es einen einfacheren / einfacheren Weg. Nachdem ich einen Stack-Tracer für nativen Code geschrieben habe, weiß ich, dass es unordentlich werden kann.
Vielleicht machst du vielleicht am Ende alles in Ordnung, also - nur meine $ .02