{"id":4133,"date":"2010-01-05T12:48:00","date_gmt":"2010-01-05T12:48:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2010\/01\/05\/dia-based-stack-walking\/"},"modified":"2019-02-18T18:45:42","modified_gmt":"2019-02-18T18:45:42","slug":"dia-based-stack-walking","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/dia-based-stack-walking\/","title":{"rendered":"DIA based Stack Walking"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Hello, I am Manish Vasani, an SDET on the VC++ compiler backend team. In this series of posts, I will talk about call stacks and how to use the <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/x93ctkx8.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">DIA SDK<\/font><\/a><font size=\"3\"><font face=\"Calibri\"> for implementing a stack walking client that builds a call stack. If you are interested in knowing how debuggers build the call stack or want to write an application that dumps the call stack for an executing process, you may want to continue reading further. <\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">In this post I&rsquo;ll start with a brief introduction on stack walking, discuss the DIA APIs for implementing it, and then walkthrough a code sample for a DIA based stack walker. Those who are familiar with stack walking would know that apart from the DIA SDK, there are two other commonly used stack walking APIs: <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms680650(VS.85).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">StackWalk64<\/font><\/a><font face=\"Calibri\" size=\"3\"> (found in <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms679309(VS.85).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">DbgHelp<\/font><\/a><font face=\"Calibri\" size=\"3\">) and <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms680617(VS.85).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">RtlVirtualUnwind<\/font><\/a><font size=\"3\"><font face=\"Calibri\"> (found in kernel32.lib). I&rsquo;ll touch upon these two APIs at the end of the post. <\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><u><font size=\"3\"><font face=\"Calibri\">Introduction:<\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">When the Operating system executes a process, it calls into the program&rsquo;s entry point (or the starting function) and allocates a set of resources to the process. Some of these resources such as stack memory and register context are allocated per thread basis. Every new function call in the thread is allocated a part of this stack memory and has a new register context. A stack frame or an <\/font><a href=\"http:\/\/en.wikipedia.org\/wiki\/Activation_record#Structure\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">activation record<\/font><\/a><font size=\"3\"><font face=\"Calibri\"> is essentially this runtime state information for an active function call. Typical attributes associated with a stack frame are:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Function associated with the frame<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Module (binary) associated with the frame<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">3)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Return address<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">4)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Amount of stack memory allocated for arguments and locals for the function<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">5)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Base pointer (BP) for referencing the arguments passed to the function call<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">6)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Base pointer (BP) for referencing the local variables in the function (most of the time this is same as 5)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">7)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Program counter or the Instruction Pointer for currently executing instruction (IP)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">8)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Stack Pointer (SP)<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">9)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Other Register context<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">A sequence of active stack frames in an executing thread is generally referred to as a call stack. Call stacks help developers to debug runtime program errors and also denote the program state at a particular execution point. The process of building this call stack is called stack walking. Stack walking clients (such as debuggers) use the stack frame attributes to retrieve the values of function arguments, locals, etc.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><u><font size=\"3\"><font face=\"Calibri\">DIA APIs for St\nack walking:<\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">The primary functionality of the <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/x93ctkx8.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">DIA SDK<\/font><\/a><font size=\"3\"><font face=\"Calibri\"> is to provide access to the debug information in PDB files. Apart from that, the DIA SDK also provides a set of interfaces&nbsp; that can be used to implement a platform independent stack walker. These are:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dt06fh94.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">IDiaStackWalker<\/font><\/a><font size=\"3\"><font face=\"Calibri\">: This is the primary initialization interface for the DIA stack walker.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/1ca7599z.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">IDiaEnumStackFrames<\/font><\/a><font size=\"3\"><font face=\"Calibri\">: This is the stack frame enumerator interface that exposes the primary API to perform a stack walk to the next frame.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">3)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/zxsd009h.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">IDiaStackFrame<\/font><\/a><font size=\"3\"><font face=\"Calibri\">: This interface represents a stack frame and exposes attributes of the stack frame. <\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">4)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/b4kdc788.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">IDiaStackWalkHelper<\/font><\/a><font size=\"3\"><font face=\"Calibri\">: This is a helper interface for the DIA stack walker. To understand its primary purpose, let us briefly mention the two primary types of inputs required by the stack walker:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><font face=\"Calibri\" size=\"3\">i.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Run-time entities: This includes the runtime aspects such as thread&rsquo;s register context, properties of loaded image files such as <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms680349(VS.85).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">LOADED_IMAGE<\/font><\/a><font size=\"3\"><font face=\"Calibri\">, executable binary (or module) corresponding to a given virtual address, etc.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span class=\"MsoCommentReference\"><span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ii.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\">Compile-time generated entities: This includes the PDB records that provide static attributes for frames such as memory allocated for locals\/arguments, whether the function corresponding to the frame contains SEH\/C++ EH, the unwind program to execute to walk to the next frame, etc. <span class=\"MsoCommentReference\"><span><\/p>\n<p><\/span><\/span><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><font size=\"3\"><font face=\"Calibri\">DIA stack walker uses other DIA interfaces to read the compile time generated entities, i.e. PDB records. It delegates fetching the runtime entities to the DIA clients. The primary reason for this being that DIA doesn&rsquo;t maintain the runtime state information for the process. For example, a given virtual address in process&rsquo; address space might belong to any one of the modules (executable binaries) loaded in the process. Each module would have a different pdb file and hence a different DIA session to read the pdb. DIA isn&rsquo;t aware about the loaded modules for the process and hence expects its clients to provide this mapping. Most DIA stack walker clients, such as debuggers, already need to fetch and store this runtime information. Hence, it is logical to expect the clients to provide this information to DIA through the implementation of this helper interface.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><u><font size=\"3\"><font face=\"Calibri\">Code Sample Walkthrough:<\/p>\n<p><\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">I will first give the class design for the DIA based stack walker sample and then walk you through its execution flow.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><b><u><font size=\"3\"><font face=\"Calibri\">Class design: <\/p>\n<p><\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><i>MyDiaStackWalker: <\/i>This is the primary DIA stack walker class. It maintains a handle to the initialization interface (IDiaStackWalker) and the stack frame enumerator (IDiaEnumStackFrames). It also contains few helper methods for other DIA operation\ns.<b><u><\/p>\n<p><\/u><\/b><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><i>MyDiaStackWalkHelper:<\/i> This class implements the IDiaStackWalkHelper interface. I will discuss each of its method in detail later on.<b><u><\/p>\n<p><\/u><\/b><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">3)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><i>Debugger<\/i>: This is a Debugger class with a simple debugging engine. It launches the specified executable with debugging enabled and dumps the call stack at every debug break event in the executable. (Debug break events could be trigged by use of <\/font><\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/f408b4et.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">__debugbreak<\/font><\/a><font size=\"3\"><font face=\"Calibri\">() intrinsic in your source code).<b><u><\/p>\n<p><\/u><\/b><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">4)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><i>ContextManager<\/i>: This class manages the register context associated with the current stack frame of the current debuggee thread (debuggee is the process being debugged)<b><u><\/p>\n<p><\/u><\/b><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">5)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><i>ModuleManager: <\/i>This class maintains the list of modules (executable binaries) loaded in the process along with their attributes.<b><u><\/p>\n<p><\/u><\/b><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><b><u><font size=\"3\"><font face=\"Calibri\">Execution Flow:<\/p>\n<p><\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font size=\"3\"><font face=\"Calibri\"><b><u>Initialization<\/u><\/b><u>:<\/p>\n<p><\/u><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\"><font face=\"Calibri\" size=\"3\">The first step in the application is to initialize the DIA stack walker. This is done through the IDiaStackWalker interface. IDiaStackWalker provides two platform specific APIs for initializing the DIA client: <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/818xzktb.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">getEnumFrames<\/font><\/a><font face=\"Calibri\" size=\"3\"> (for x86) and <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/y7cdyb59.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">getEnumFrames2<\/font><\/a><font size=\"3\"><font face=\"Calibri\"> (for x64 and ia64 platforms). Each of these APIs take a pointer to the class that implements IDiaStackWalkHelper (<i>MyDiaStackWalkHelper<\/i>) and returns the stack frame enumerator (IDiaEnumStackFrames). You may refer to the method &ldquo;<i>MyDiaStackWalker::Initialize&rdquo; <\/i>in MyDiaStackWalker.cpp to see the initialization logic. <\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoListParagraph\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoListParagraph\"><b><span><span><font face=\"Calibri\" size=\"3\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><\/b><b><u><font size=\"3\"><font face=\"Calibri\">Walking the stack: <\/p>\n<p><\/font><\/font><\/u><\/b><\/p>\n<p class=\"MsoListParagraph\"><font size=\"3\"><font face=\"Calibri\">After the initialization, we launch the specified executable under the debugger. On hitting a debug break event, we initialize the register context and loaded modules for the debuggee. Than we call &ldquo;<i>MyDiaStackWalker::WalkCallStack&rdquo; <\/i>method to walk the call stack and retrieve attributes such as module name, function name, Instruction pointer (IP), etc. for each stack frame:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span>\/\/ method to walk all the stack frames in the call stack<\/span><span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>void<\/span><span> <b>MyDiaStackWalker::WalkCallStack<\/b>()<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>{&nbsp; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; wprintf(L<span>&#8220;nWalking call stack&#8230;n&#8221;<\/span>);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; IDiaSymbol *pFuncSym = NULL;&nbsp;&nbsp;&nbsp; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; DWORD count = <span>0<\/span>;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; BSTR szFunctionName;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; ULONGLONG ip = <span>0<\/span>;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; <span>do<\/span> {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>\/\/ Get IP for current stack frame<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&amp;n\nbsp;&nbsp;&nbsp; pContextManager-&gt;get_currentIP(&amp;ip);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>if<\/span> (!ip) {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>break<\/span>;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>\/\/ Get module for stack frame<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; Module *pModule = pModuleManager-&gt;FindModuleByVA(ip);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>\/\/ Get DIA function symbol for stack frame<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; pMyDiaStackWalkHelper-&gt;symbolForVA(ip, &amp;pFuncSym);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>\/\/ Display stack frame attributes<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>if<\/span> (pFuncSym == NULL) {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>\/\/ function symbol could be null if symbols for the module were not loaded.<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ just dump the IP for the stack frame<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wprintf(L<span>&#8220;Stack Frame %d: &#8216;%ws!%#x()&#8217;n&#8221;<\/span>, ++count, pModule-&gt;name, ip);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>continue<\/span>;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>if<\/span> (pFuncSym-&gt;get_name(&amp;szFunctionName) == S_OK) {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wprintf(L<span>&#8220;Stack Frame %d: &#8216;%ws!%ws&#8217;n&#8221;<\/span>, ++count, pModule-&gt;name, szFunctionName);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SysFreeString(szFunctionName);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; pFuncSym-&gt;Release();<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; pFuncSym = NULL; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; <span>\/\/ Walk to next stack frame<\/span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; } <span>while<\/span> (WalkStackFrame() == S_OK);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>}<\/p>\n<p><\/span><\/p>\n<p class=\"MsoListParagraph\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoListParagraph\"><font face=\"Calibri\" size=\"3\">&ldquo;<i>WalkCallStack&rdquo;<\/i> method calls into &ldquo;<i>WalkStackFrame&rdquo;<\/i> to walk each stack frame. <i>WalkStackFrame <\/i>uses the stack frame enumerator API (<\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/0ty7d2d4.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">IDiaEnumStackFrames::Next<\/font><\/a><font size=\"3\"><font face=\"Calibri\">) to do the stack walk to next frame. Following snippet shows this:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span>\/\/ MyDiaStackWalker.cpp<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>\/\/ method to walk to the next stack frame<\/span><span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>HRESULT <b>MyDiaStackWalker::WalkStackFrame<\/b>(IDiaStackFrame **ppStackFrame)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>{<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; IFVERBOSE {<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp; wprintf(L<span>&#8220;MyDiaStackWalker::WalkStackFramen&#8221;<\/span>);<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; }<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; ULONG celtFetched = <span>0<\/span>;&nbsp; <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp; IDiaStackFrame *pStackFrame = NULL;<\/p>\n<p><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello, I am Manish Vasani, an SDET on the VC++ compiler backend team. In this series of posts, I will talk about call stacks and how to use the DIA SDK for implementing a stack walking client that builds a call stack. If you are interested in knowing how debuggers build the call stack or [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[55,56,57],"class_list":["post-4133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","tag-debugging","tag-dia-sdk","tag-stack-walking"],"acf":[],"blog_post_summary":"<p>Hello, I am Manish Vasani, an SDET on the VC++ compiler backend team. In this series of posts, I will talk about call stacks and how to use the DIA SDK for implementing a stack walking client that builds a call stack. If you are interested in knowing how debuggers build the call stack or [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=4133"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4133\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=4133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=4133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=4133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}