{"id":11263,"date":"2011-03-09T07:00:00","date_gmt":"2011-03-09T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/03\/09\/how-to-rescue-a-broken-stack-trace-recovering-the-ebp-chain\/"},"modified":"2020-12-09T06:30:06","modified_gmt":"2020-12-09T14:30:06","slug":"how-to-rescue-a-broken-stack-trace-recovering-the-ebp-chain","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110309-00\/?p=11263","title":{"rendered":"How to rescue a broken stack trace: Recovering the EBP chain"},"content":{"rendered":"<p>When debugging, you may find that the stack trace falls apart:<\/p>\n<pre>ChildEBP RetAddr\r\n001af118 773806a0 ntdll!KiFastSystemCallRet\r\n001af11c 7735b18c ntdll!ZwWaitForSingleObject+0xc\r\n001af180 7735b071 ntdll!RtlpWaitOnCriticalSection+0x154\r\n001af1a8 2f6db1a9 ntdll!RtlEnterCriticalSection+0x152\r\n001af1b4 2fe8d533 ABC!CCriticalSection::Lock+0x12\r\n001af1d0 2fe8d56a ABC!CMessageList::Lock+0x24\r\n001af234 2f6e47ac ABC!CMessageWindow::UpdateMessageList+0x231\r\n001af274 2f6f040e ABC!CMessageWindow::UpdateContents+0x84\r\n001af28c 2f6e4474 ABC!CMessageWindow::Refresh+0x1a8\r\n001af360 2f6e4359 ABC!CMessageWindow::OnChar+0x4c\r\n001af384 761a1a10 ABC!CMessageWindow::WndProc+0xb31\r\n00000000 00000000 USER32!GetMessageW+0x6e\r\n<\/pre>\n<p>This can&#8217;t possibly be the complete stack. I mean, where&#8217;s the thread procedure? That should be at the start of the stack for any thread.<\/p>\n<p>What happened is that the EBP chain got broken, and the debugger can&#8217;t walk the stack any further. If the code was compiled with frame pointer optimization (FPO), then the compiler will not create EBP frames, permitting it to use EBP as a general purpose register instead. This is great for optimization, but it causes trouble for the debugger when it tries to take a stack trace through code compiled with FPO for which it does not have the necessary information to decode these types of stacks.<\/p>\n<p><b>Begin digression<\/b>: Traditionally, every function began with the sequence<\/p>\n<pre>        push ebp      ;; save caller's EBP\r\n        mov ebp, esp  ;; set our EBP to point to this \"frame\"\r\n        sub esp, n    ;; reserve space for local variables\r\n<\/pre>\n<p>and ended with<\/p>\n<pre>        mov esp, ebp  ;; discard local variables\r\n        pop ebp       ;; recover caller's EBP\r\n        ret n\r\n<\/pre>\n<p>This pattern is so common that the x86 has dedicated instructions for it. The <code>ENTER n,0<\/code> instruction does the <code>push \/ mov \/ sub<\/code>, and the <code>LEAVE<\/code> instruction does the <code>mov \/ pop<\/code>. (In C\/C++, the value after the comma is always zero.)<\/p>\n<p>if you look at what this does to the stack, you see that this establishes a linked list of what are called <i>EBP frames<\/i>. Suppose you have the following code fragment:<\/p>\n<pre>void Top(int a, int b)\r\n{\r\n int toplocal = b + 5;\r\n Middle(a, local);\r\n}\r\n\r\nvoid Middle(int c, int d)\r\n{\r\n Bottom(c+d);\r\n}\r\n\r\nvoid Bottom(int e)\r\n{\r\n int bottomlocal1, bottomlocal2;\r\n ...\r\n}\r\n<\/pre>\n<p>When execution reaches the <code>...<\/code> inside function <code>Bottom<\/code> the stack looks like the following. (I put higher addresses at the top; the stack grows downward. I also assume that the calling convention is <code>__stdcall<\/code> and that the code is compiled with absolutely no optimization.)<\/p>\n<table class=\"cp3\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td rowspan=\"6\" valign=\"center\"><code>Top<\/code>&#8216;s stack frame<\/td>\n<td style=\"border-top: solid .75pt black; border-left: solid .75pt black; border-bottom: solid .75pt black;\" rowspan=\"6\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8F8<\/code><\/td>\n<td valign=\"baseline\">parameter <code>b<\/code> passed to <code>Top<\/code><\/td>\n<td rowspan=\"4\" valign=\"bottom\">During execution of <code>Top<\/code>,<br \/>\n\u2190<code>EBP = 0040F8EC<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8F4<\/code><\/td>\n<td valign=\"baseline\">parameter <code>a<\/code> passed to <code>Top<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8F0<\/code><\/td>\n<td valign=\"baseline\">return address of <code>Top<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8EC<\/code><\/td>\n<td valign=\"baseline\">EBP of <code>Top<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8E8<\/code><\/td>\n<td valign=\"baseline\"><code>toplocal<\/code><\/td>\n<\/tr>\n<tr>\n<td rowspan=\"5\" valign=\"center\"><code>Middle<\/code>&#8216;s stack frame<\/td>\n<td style=\"border-top: solid .75pt black; border-left: solid .75pt black; border-bottom: solid .75pt black;\" rowspan=\"5\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8E4<\/code><\/td>\n<td valign=\"baseline\">parameter <code>d<\/code> passed to <code>Middle<\/code><\/td>\n<td rowspan=\"4\" valign=\"bottom\">During execution of <code>Middle<\/code>,<br \/>\n\u2190<code>EBP = 0040F8D8<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8E0<\/code><\/td>\n<td valign=\"baseline\">parameter <code>c<\/code> passed to <code>Middle<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8DC<\/code><\/td>\n<td valign=\"baseline\">return address of <code>Middle<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8D8<\/code><\/td>\n<td valign=\"baseline\"><code>0040F8EC<\/code> = EBP of <code>Middle<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"7\" valign=\"center\"><code>Bottom<\/code>&#8216;s stack frame<\/td>\n<td style=\"border-top: solid .75pt black; border-left: solid .75pt black; border-bottom: solid .75pt black;\" rowspan=\"7\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8D4<\/code><\/td>\n<td valign=\"baseline\">parameter <code>e<\/code> passed to <code>Bottom<\/code><\/td>\n<td rowspan=\"3\" valign=\"bottom\">During execution of <code>Bottom<\/code>,<br \/>\n\u2190<code>EBP = 0040F8CC<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8D0<\/code><\/td>\n<td valign=\"baseline\">return address of <code>Bottom<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8CC<\/code><\/td>\n<td valign=\"baseline\"><code>0040F8D8<\/code> = EBP of <code>Bottom<\/code>&#8216;s caller<\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8C8<\/code><\/td>\n<td valign=\"baseline\"><code>bottomlocal1<\/code><\/td>\n<\/tr>\n<tr>\n<td valign=\"baseline\"><code>0040F8C4<\/code><\/td>\n<td valign=\"baseline\"><code>bottomlocal2<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Each stack frame is identified by the <code>EBP<\/code> value which the function uses during its execution.<\/p>\n<p>The structure of each stack frame is therefore<\/p>\n<table class=\"cp3\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td><code>[ebp+n]<\/code><\/td>\n<td>Offsets greater than 4 access parameters<\/td>\n<\/tr>\n<tr>\n<td><code>[ebp+4]<\/code><\/td>\n<td>Offset 4 is the return address<\/td>\n<\/tr>\n<tr>\n<td><code>[ebp+0]<\/code><\/td>\n<td>Zero offset accesses caller&#8217;s <code>EBP<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>[ebp-n]<\/code><\/td>\n<td>Negative offsets access locals<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>And the stack frames are all connected to each other in the form of a linked list threaded through the <code>EBP<\/code> values. This linked list is known as the <i>EBP chain<\/i>. <b>End digression<\/b>.<\/p>\n<p>To recover from the broken EBP chain, start dumping the stack a little before things go bad (in this case, I would start at <code>001af384-80<\/code>) and then look for something that looks like a valid stack frame. Since the parameters and locals to a function can be pretty much anything, all you have left to work with is the <code>EBP<\/code> and the return address. In other words, you are looking for pairs of values of the form<\/p>\n<pre>\u00abpointer a little higher up the stack\u00bb.\r\n\u00abcode address\u00bb\r\n<\/pre>\n<p>In this case, I got lucky and didn&#8217;t have to go very far:<\/p>\n<pre>  001af474  00000000\r\n -001af478  001af494\r\n\/ 001af47c  14f4fba8 <u>DEF!SubclassBase::CallOriginalWndProc+0x1a<\/u>\r\n| 001af480  2f6e4317 ABC!CMessageWindow::WndProc\r\n| 001af484  00970338\r\n| 001af488  0000000f\r\n| 001af48c  00000000\r\n\\ 001af490  00000000\r\n &gt;001af494  001af4f0\r\n  001af498  14f4fcd6 <u>DEF!SubclassBase::ForwardMessage+0x23<\/u>\r\n  001af49c  00970338\r\n  001af4a0  0000000f\r\n  001af4a4  00000000\r\n  001af4a8  00000000\r\n  001af4ac  00000000\r\n  001af4b0  2f6e4317 ABC!CMessageWindow::WndProc\r\n  001af4b4  ed758311\r\n  001af4b8  00000000\r\n  001af4bc  15143f70\r\n  001af4c0  00000000\r\n  001af4c4  14f4fb8e DEF!CView::SortItems+0x96\r\n  001af4c8  00000000\r\n  001af4cc  2f6e4317 ABC!CMessageWindow::WndProc\r\n  001af4d0  00000000\r\n<\/pre>\n<p>At stack address <code>001af478<\/code>, we have a pointer to memory higher up the stack followed by a code address. if you follow that pointer, it points to another instance of the same pattern: A pointer higher up the stack followed by the code address.<\/p>\n<p>Once you find where the EBP chain resumes, you can ask the debugger to resume its stack trace from that point with the <code>=n<\/code> option to the <code>k<\/code> command.<\/p>\n<pre>0:000&gt; k=001af478\r\nChildEBP RetAddr\r\n001af478 14f4fba8 ntdll!KiFastSystemCallRet\r\n001af494 14f4fcd6 DEF!SubclassBase::CallOriginalWndProc+0x1a\r\n001af4f0 14f4fc8b DEF!SubclassBase::ForwardMessage+0x23\r\n001af514 14f32dd1 DEF!SubclassBase::ForwardChar+0x59\r\n001af530 14f4fcd6 DEF!SubclassBase::OnChar+0x3c\r\n001af58c 14f4fd76 DEF!HelpSubclass::WndProc+0x51\r\n001af5e4 761a1a10 DEF!SubclassBase::s_WndProc+0x1b\r\n001af610 761a1ae8 USER32!GetMessageW+0x6e\r\n001af688 761a1c03 USER32!GetMessageW+0x146\r\n001af6e4 761a3656 USER32!GetMessageW+0x261\r\n001af70c 77380e6e USER32!OffsetRect+0x4d\r\n001af784 761a2a98 ntdll!KiUserCallbackDispatcher+0x2e\r\n001af794 698fd0aa USER32!DispatchMessageW+0xf\r\n001af7a4 2f7bf15c ABC!CThread::DispatchMessageW+0x23\r\n001af7e0 2f7befc9 ABC!CMessageWindow::MessageLoop+0x3a2\r\n001af808 2ff56d20 ABC!CMessageWindow::ThreadProc+0x9f\r\n001af898 75c2384b ABC!CMessageWindow::s_ThreadProc+0x10\r\n001af8a4 7735a9bd kernel32!BaseThreadInitThunk+0x12\r\n001af8e4 00000000 ntdll!LdrInitializeThunk+0x4d\r\n<\/pre>\n<p>When you do this, make sure to ignore the first line of the resumed stack trace, since that is based on your current <code>EIP<\/code>, not the return address stored in the stack frame.<\/p>\n<p>Today was really just a warm-up for another debugging technique that I haven&#8217;t finished writing up yet, so you&#8217;re just going to be in suspense for another two years or so, though if you attended <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20101201-01\/?p=12143\"> my TechEd China talk<\/a>, you already know where I&#8217;m going.<\/p>\n<p><b>Bonus reading<\/b>: In Ryan Mangipano&#8217;s two-part series on kernel mode stack overflows, <a href=\"https:\/\/docs.microsoft.com\/en-us\/archive\/blogs\/ntdebugging\/part-2-got-stack-no-we-ran-out-and-kv-wont-tell-me-why\"> the second part does a bit of EBP chain chasing<\/a>. (Feel free to read <a href=\"https:\/\/docs.microsoft.com\/en-us\/archive\/blogs\/ntdebugging\/part-1-got-stack-no-we-ran-out-of-kernel-mode-stack-and-kv-wont-tell-me-why\"> the first part<\/a>, as well as <a href=\"https:\/\/docs.microsoft.com\/en-us\/archive\/blogs\/ntdebugging\/kernel-stack-overflows\"> earlier discussion on the subject of stack overflows<\/a>.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Stack frames are threaded through EBP.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-11263","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Stack frames are threaded through EBP.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=11263"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11263\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=11263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11263"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}