Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2010 Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | |
michael@0 | 30 | // stackwalker_x86.cc: x86-specific stackwalker. |
michael@0 | 31 | // |
michael@0 | 32 | // See stackwalker_x86.h for documentation. |
michael@0 | 33 | // |
michael@0 | 34 | // Author: Mark Mentovai |
michael@0 | 35 | |
michael@0 | 36 | #include <assert.h> |
michael@0 | 37 | #include <string> |
michael@0 | 38 | |
michael@0 | 39 | #include "common/scoped_ptr.h" |
michael@0 | 40 | #include "google_breakpad/processor/call_stack.h" |
michael@0 | 41 | #include "google_breakpad/processor/code_modules.h" |
michael@0 | 42 | #include "google_breakpad/processor/memory_region.h" |
michael@0 | 43 | #include "google_breakpad/processor/source_line_resolver_interface.h" |
michael@0 | 44 | #include "google_breakpad/processor/stack_frame_cpu.h" |
michael@0 | 45 | #include "common/logging.h" |
michael@0 | 46 | #include "processor/postfix_evaluator-inl.h" |
michael@0 | 47 | #include "processor/stackwalker_x86.h" |
michael@0 | 48 | #include "processor/windows_frame_info.h" |
michael@0 | 49 | #include "processor/cfi_frame_info.h" |
michael@0 | 50 | |
michael@0 | 51 | namespace google_breakpad { |
michael@0 | 52 | |
michael@0 | 53 | |
michael@0 | 54 | const StackwalkerX86::CFIWalker::RegisterSet |
michael@0 | 55 | StackwalkerX86::cfi_register_map_[] = { |
michael@0 | 56 | // It may seem like $eip and $esp are callee-saves, because (with Unix or |
michael@0 | 57 | // cdecl calling conventions) the callee is responsible for having them |
michael@0 | 58 | // restored upon return. But the callee_saves flags here really means |
michael@0 | 59 | // that the walker should assume they're unchanged if the CFI doesn't |
michael@0 | 60 | // mention them, which is clearly wrong for $eip and $esp. |
michael@0 | 61 | { ToUniqueString("$eip"), ToUniqueString(".ra"), false, |
michael@0 | 62 | StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip }, |
michael@0 | 63 | { ToUniqueString("$esp"), ToUniqueString(".cfa"), false, |
michael@0 | 64 | StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp }, |
michael@0 | 65 | { ToUniqueString("$ebp"), NULL, true, |
michael@0 | 66 | StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp }, |
michael@0 | 67 | { ToUniqueString("$eax"), NULL, false, |
michael@0 | 68 | StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax }, |
michael@0 | 69 | { ToUniqueString("$ebx"), NULL, true, |
michael@0 | 70 | StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx }, |
michael@0 | 71 | { ToUniqueString("$ecx"), NULL, false, |
michael@0 | 72 | StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx }, |
michael@0 | 73 | { ToUniqueString("$edx"), NULL, false, |
michael@0 | 74 | StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx }, |
michael@0 | 75 | { ToUniqueString("$esi"), NULL, true, |
michael@0 | 76 | StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi }, |
michael@0 | 77 | { ToUniqueString("$edi"), NULL, true, |
michael@0 | 78 | StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi }, |
michael@0 | 79 | }; |
michael@0 | 80 | |
michael@0 | 81 | StackwalkerX86::StackwalkerX86(const SystemInfo* system_info, |
michael@0 | 82 | const MDRawContextX86* context, |
michael@0 | 83 | MemoryRegion* memory, |
michael@0 | 84 | const CodeModules* modules, |
michael@0 | 85 | StackFrameSymbolizer* resolver_helper) |
michael@0 | 86 | : Stackwalker(system_info, memory, modules, resolver_helper), |
michael@0 | 87 | context_(context), |
michael@0 | 88 | cfi_walker_(cfi_register_map_, |
michael@0 | 89 | (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) { |
michael@0 | 90 | if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { |
michael@0 | 91 | // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid. |
michael@0 | 92 | // Mark memory_ = NULL, which will cause stackwalking to fail. |
michael@0 | 93 | BPLOG(ERROR) << "Memory out of range for stackwalking: " << |
michael@0 | 94 | HexString(memory_->GetBase()) << "+" << |
michael@0 | 95 | HexString(memory_->GetSize()); |
michael@0 | 96 | memory_ = NULL; |
michael@0 | 97 | } |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | StackFrameX86::~StackFrameX86() { |
michael@0 | 101 | if (windows_frame_info) |
michael@0 | 102 | delete windows_frame_info; |
michael@0 | 103 | windows_frame_info = NULL; |
michael@0 | 104 | if (cfi_frame_info) |
michael@0 | 105 | delete cfi_frame_info; |
michael@0 | 106 | cfi_frame_info = NULL; |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | uint64_t StackFrameX86::ReturnAddress() const |
michael@0 | 110 | { |
michael@0 | 111 | assert(context_validity & StackFrameX86::CONTEXT_VALID_EIP); |
michael@0 | 112 | return context.eip; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | StackFrame* StackwalkerX86::GetContextFrame() { |
michael@0 | 116 | if (!context_) { |
michael@0 | 117 | BPLOG(ERROR) << "Can't get context frame without context"; |
michael@0 | 118 | return NULL; |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | StackFrameX86* frame = new StackFrameX86(); |
michael@0 | 122 | |
michael@0 | 123 | // The instruction pointer is stored directly in a register, so pull it |
michael@0 | 124 | // straight out of the CPU context structure. |
michael@0 | 125 | frame->context = *context_; |
michael@0 | 126 | frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL; |
michael@0 | 127 | frame->trust = StackFrame::FRAME_TRUST_CONTEXT; |
michael@0 | 128 | frame->instruction = frame->context.eip; |
michael@0 | 129 | |
michael@0 | 130 | return frame; |
michael@0 | 131 | } |
michael@0 | 132 | |
michael@0 | 133 | StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( |
michael@0 | 134 | const vector<StackFrame*> &frames, |
michael@0 | 135 | WindowsFrameInfo* last_frame_info, |
michael@0 | 136 | bool stack_scan_allowed) { |
michael@0 | 137 | StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE; |
michael@0 | 138 | |
michael@0 | 139 | StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); |
michael@0 | 140 | |
michael@0 | 141 | // Save the stack walking info we found, in case we need it later to |
michael@0 | 142 | // find the callee of the frame we're constructing now. |
michael@0 | 143 | last_frame->windows_frame_info = last_frame_info; |
michael@0 | 144 | |
michael@0 | 145 | // This function only covers the full STACK WIN case. If |
michael@0 | 146 | // last_frame_info is VALID_PARAMETER_SIZE-only, then we should |
michael@0 | 147 | // assume the traditional frame format or use some other strategy. |
michael@0 | 148 | if (last_frame_info->valid != WindowsFrameInfo::VALID_ALL) |
michael@0 | 149 | return NULL; |
michael@0 | 150 | |
michael@0 | 151 | // This stackwalker sets each frame's %esp to its value immediately prior |
michael@0 | 152 | // to the CALL into the callee. This means that %esp points to the last |
michael@0 | 153 | // callee argument pushed onto the stack, which may not be where %esp points |
michael@0 | 154 | // after the callee returns. Specifically, the value is correct for the |
michael@0 | 155 | // cdecl calling convention, but not other conventions. The cdecl |
michael@0 | 156 | // convention requires a caller to pop its callee's arguments from the |
michael@0 | 157 | // stack after the callee returns. This is usually accomplished by adding |
michael@0 | 158 | // the known size of the arguments to %esp. Other calling conventions, |
michael@0 | 159 | // including stdcall, thiscall, and fastcall, require the callee to pop any |
michael@0 | 160 | // parameters stored on the stack before returning. This is usually |
michael@0 | 161 | // accomplished by using the RET n instruction, which pops n bytes off |
michael@0 | 162 | // the stack after popping the return address. |
michael@0 | 163 | // |
michael@0 | 164 | // Because each frame's %esp will point to a location on the stack after |
michael@0 | 165 | // callee arguments have been PUSHed, when locating things in a stack frame |
michael@0 | 166 | // relative to %esp, the size of the arguments to the callee need to be |
michael@0 | 167 | // taken into account. This seems a little bit unclean, but it's better |
michael@0 | 168 | // than the alternative, which would need to take these same things into |
michael@0 | 169 | // account, but only for cdecl functions. With this implementation, we get |
michael@0 | 170 | // to be agnostic about each function's calling convention. Furthermore, |
michael@0 | 171 | // this is how Windows debugging tools work, so it means that the %esp |
michael@0 | 172 | // values produced by this stackwalker directly correspond to the %esp |
michael@0 | 173 | // values you'll see there. |
michael@0 | 174 | // |
michael@0 | 175 | // If the last frame has no callee (because it's the context frame), just |
michael@0 | 176 | // set the callee parameter size to 0: the stack pointer can't point to |
michael@0 | 177 | // callee arguments because there's no callee. This is correct as long |
michael@0 | 178 | // as the context wasn't captured while arguments were being pushed for |
michael@0 | 179 | // a function call. Note that there may be functions whose parameter sizes |
michael@0 | 180 | // are unknown, 0 is also used in that case. When that happens, it should |
michael@0 | 181 | // be possible to walk to the next frame without reference to %esp. |
michael@0 | 182 | |
michael@0 | 183 | uint32_t last_frame_callee_parameter_size = 0; |
michael@0 | 184 | int frames_already_walked = frames.size(); |
michael@0 | 185 | if (frames_already_walked >= 2) { |
michael@0 | 186 | const StackFrameX86* last_frame_callee |
michael@0 | 187 | = static_cast<StackFrameX86*>(frames[frames_already_walked - 2]); |
michael@0 | 188 | WindowsFrameInfo* last_frame_callee_info |
michael@0 | 189 | = last_frame_callee->windows_frame_info; |
michael@0 | 190 | if (last_frame_callee_info && |
michael@0 | 191 | (last_frame_callee_info->valid |
michael@0 | 192 | & WindowsFrameInfo::VALID_PARAMETER_SIZE)) { |
michael@0 | 193 | last_frame_callee_parameter_size = |
michael@0 | 194 | last_frame_callee_info->parameter_size; |
michael@0 | 195 | } |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | // Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used |
michael@0 | 199 | // in each program string, and their previous values are known, so set them |
michael@0 | 200 | // here. |
michael@0 | 201 | PostfixEvaluator<uint32_t>::DictionaryType dictionary; |
michael@0 | 202 | // Provide the current register values. |
michael@0 | 203 | dictionary.set(ustr__ZSebp(), last_frame->context.ebp); |
michael@0 | 204 | dictionary.set(ustr__ZSesp(), last_frame->context.esp); |
michael@0 | 205 | // Provide constants from the debug info for last_frame and its callee. |
michael@0 | 206 | // .cbCalleeParams is a Breakpad extension that allows us to use the |
michael@0 | 207 | // PostfixEvaluator engine when certain types of debugging information |
michael@0 | 208 | // are present without having to write the constants into the program |
michael@0 | 209 | // string as literals. |
michael@0 | 210 | dictionary.set(ustr__ZDcbCalleeParams(), last_frame_callee_parameter_size); |
michael@0 | 211 | dictionary.set(ustr__ZDcbSavedRegs(), last_frame_info->saved_register_size); |
michael@0 | 212 | dictionary.set(ustr__ZDcbLocals(), last_frame_info->local_size); |
michael@0 | 213 | |
michael@0 | 214 | uint32_t raSearchStart = last_frame->context.esp + |
michael@0 | 215 | last_frame_callee_parameter_size + |
michael@0 | 216 | last_frame_info->local_size + |
michael@0 | 217 | last_frame_info->saved_register_size; |
michael@0 | 218 | |
michael@0 | 219 | uint32_t raSearchStartOld = raSearchStart; |
michael@0 | 220 | uint32_t found = 0; // dummy value |
michael@0 | 221 | // Scan up to three words above the calculated search value, in case |
michael@0 | 222 | // the stack was aligned to a quadword boundary. |
michael@0 | 223 | if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) && |
michael@0 | 224 | last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT && |
michael@0 | 225 | last_frame->windows_frame_info != NULL && |
michael@0 | 226 | last_frame_info->type_ == WindowsFrameInfo::STACK_INFO_FPO && |
michael@0 | 227 | raSearchStartOld == raSearchStart && |
michael@0 | 228 | found == last_frame->context.eip) { |
michael@0 | 229 | // The context frame represents an FPO-optimized Windows system call. |
michael@0 | 230 | // On the top of the stack we have a pointer to the current instruction. |
michael@0 | 231 | // This means that the callee has returned but the return address is still |
michael@0 | 232 | // on the top of the stack which is very atypical situaltion. |
michael@0 | 233 | // Skip one slot from the stack and do another scan in order to get the |
michael@0 | 234 | // actual return address. |
michael@0 | 235 | raSearchStart += 4; |
michael@0 | 236 | ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3); |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | // The difference between raSearch and raSearchStart is unknown, |
michael@0 | 240 | // but making them the same seems to work well in practice. |
michael@0 | 241 | dictionary.set(ustr__ZDraSearchStart(), raSearchStart); |
michael@0 | 242 | dictionary.set(ustr__ZDraSearch(), raSearchStart); |
michael@0 | 243 | |
michael@0 | 244 | dictionary.set(ustr__ZDcbParams(), last_frame_info->parameter_size); |
michael@0 | 245 | |
michael@0 | 246 | // Decide what type of program string to use. The program string is in |
michael@0 | 247 | // postfix notation and will be passed to PostfixEvaluator::Evaluate. |
michael@0 | 248 | // Given the dictionary and the program string, it is possible to compute |
michael@0 | 249 | // the return address and the values of other registers in the calling |
michael@0 | 250 | // function. Because of bugs described below, the stack may need to be |
michael@0 | 251 | // scanned for these values. The results of program string evaluation |
michael@0 | 252 | // will be used to determine whether to scan for better values. |
michael@0 | 253 | string program_string; |
michael@0 | 254 | bool recover_ebp = true; |
michael@0 | 255 | |
michael@0 | 256 | trust = StackFrame::FRAME_TRUST_CFI; |
michael@0 | 257 | if (!last_frame_info->program_string.empty()) { |
michael@0 | 258 | // The FPO data has its own program string, which will tell us how to |
michael@0 | 259 | // get to the caller frame, and may even fill in the values of |
michael@0 | 260 | // nonvolatile registers and provide pointers to local variables and |
michael@0 | 261 | // parameters. In some cases, particularly with program strings that use |
michael@0 | 262 | // .raSearchStart, the stack may need to be scanned afterward. |
michael@0 | 263 | program_string = last_frame_info->program_string; |
michael@0 | 264 | } else if (last_frame_info->allocates_base_pointer) { |
michael@0 | 265 | // The function corresponding to the last frame doesn't use the frame |
michael@0 | 266 | // pointer for conventional purposes, but it does allocate a new |
michael@0 | 267 | // frame pointer and use it for its own purposes. Its callee's |
michael@0 | 268 | // information is still accessed relative to %esp, and the previous |
michael@0 | 269 | // value of %ebp can be recovered from a location in its stack frame, |
michael@0 | 270 | // within the saved-register area. |
michael@0 | 271 | // |
michael@0 | 272 | // Functions that fall into this category use the %ebp register for |
michael@0 | 273 | // a purpose other than the frame pointer. They restore the caller's |
michael@0 | 274 | // %ebp before returning. These functions create their stack frame |
michael@0 | 275 | // after a CALL by decrementing the stack pointer in an amount |
michael@0 | 276 | // sufficient to store local variables, and then PUSHing saved |
michael@0 | 277 | // registers onto the stack. Arguments to a callee function, if any, |
michael@0 | 278 | // are PUSHed after that. Walking up to the caller, therefore, |
michael@0 | 279 | // can be done solely with calculations relative to the stack pointer |
michael@0 | 280 | // (%esp). The return address is recovered from the memory location |
michael@0 | 281 | // above the known sizes of the callee's parameters, saved registers, |
michael@0 | 282 | // and locals. The caller's stack pointer (the value of %esp when |
michael@0 | 283 | // the caller executed CALL) is the location immediately above the |
michael@0 | 284 | // saved return address. The saved value of %ebp to be restored for |
michael@0 | 285 | // the caller is at a known location in the saved-register area of |
michael@0 | 286 | // the stack frame. |
michael@0 | 287 | // |
michael@0 | 288 | // For this type of frame, MSVC 14 (from Visual Studio 8/2005) in |
michael@0 | 289 | // link-time code generation mode (/LTCG and /GL) can generate erroneous |
michael@0 | 290 | // debugging data. The reported size of saved registers can be 0, |
michael@0 | 291 | // which is clearly an error because these frames must, at the very |
michael@0 | 292 | // least, save %ebp. For this reason, in addition to those given above |
michael@0 | 293 | // about the use of .raSearchStart, the stack may need to be scanned |
michael@0 | 294 | // for a better return address and a better frame pointer after the |
michael@0 | 295 | // program string is evaluated. |
michael@0 | 296 | // |
michael@0 | 297 | // %eip_new = *(%esp_old + callee_params + saved_regs + locals) |
michael@0 | 298 | // %ebp_new = *(%esp_old + callee_params + saved_regs - 8) |
michael@0 | 299 | // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 |
michael@0 | 300 | program_string = "$eip .raSearchStart ^ = " |
michael@0 | 301 | "$ebp $esp .cbCalleeParams + .cbSavedRegs + 8 - ^ = " |
michael@0 | 302 | "$esp .raSearchStart 4 + ="; |
michael@0 | 303 | } else { |
michael@0 | 304 | // The function corresponding to the last frame doesn't use %ebp at |
michael@0 | 305 | // all. The callee frame is located relative to %esp. |
michael@0 | 306 | // |
michael@0 | 307 | // The called procedure's instruction pointer and stack pointer are |
michael@0 | 308 | // recovered in the same way as the case above, except that no |
michael@0 | 309 | // frame pointer (%ebp) is used at all, so it is not saved anywhere |
michael@0 | 310 | // in the callee's stack frame and does not need to be recovered. |
michael@0 | 311 | // Because %ebp wasn't used in the callee, whatever value it has |
michael@0 | 312 | // is the value that it had in the caller, so it can be carried |
michael@0 | 313 | // straight through without bringing its validity into question. |
michael@0 | 314 | // |
michael@0 | 315 | // Because of the use of .raSearchStart, the stack will possibly be |
michael@0 | 316 | // examined to locate a better return address after program string |
michael@0 | 317 | // evaluation. The stack will not be examined to locate a saved |
michael@0 | 318 | // %ebp value, because these frames do not save (or use) %ebp. |
michael@0 | 319 | // |
michael@0 | 320 | // %eip_new = *(%esp_old + callee_params + saved_regs + locals) |
michael@0 | 321 | // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 |
michael@0 | 322 | // %ebp_new = %ebp_old |
michael@0 | 323 | program_string = "$eip .raSearchStart ^ = " |
michael@0 | 324 | "$esp .raSearchStart 4 + ="; |
michael@0 | 325 | recover_ebp = false; |
michael@0 | 326 | } |
michael@0 | 327 | |
michael@0 | 328 | // Now crank it out, making sure that the program string set at least the |
michael@0 | 329 | // two required variables. |
michael@0 | 330 | PostfixEvaluator<uint32_t> evaluator = |
michael@0 | 331 | PostfixEvaluator<uint32_t>(&dictionary, memory_); |
michael@0 | 332 | PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity; |
michael@0 | 333 | if (!evaluator.Evaluate(program_string, &dictionary_validity) || |
michael@0 | 334 | !dictionary_validity.have(ustr__ZSeip()) || |
michael@0 | 335 | !dictionary_validity.have(ustr__ZSesp())) { |
michael@0 | 336 | // Program string evaluation failed. It may be that %eip is not somewhere |
michael@0 | 337 | // with stack frame info, and %ebp is pointing to non-stack memory, so |
michael@0 | 338 | // our evaluation couldn't succeed. We'll scan the stack for a return |
michael@0 | 339 | // address. This can happen if the stack is in a module for which |
michael@0 | 340 | // we don't have symbols, and that module is compiled without a |
michael@0 | 341 | // frame pointer. |
michael@0 | 342 | uint32_t location_start = last_frame->context.esp; |
michael@0 | 343 | uint32_t location, eip; |
michael@0 | 344 | if (!stack_scan_allowed |
michael@0 | 345 | || !ScanForReturnAddress(location_start, &location, &eip)) { |
michael@0 | 346 | // if we can't find an instruction pointer even with stack scanning, |
michael@0 | 347 | // give up. |
michael@0 | 348 | return NULL; |
michael@0 | 349 | } |
michael@0 | 350 | |
michael@0 | 351 | // This seems like a reasonable return address. Since program string |
michael@0 | 352 | // evaluation failed, use it and set %esp to the location above the |
michael@0 | 353 | // one where the return address was found. |
michael@0 | 354 | dictionary.set(ustr__ZSeip(), eip); |
michael@0 | 355 | dictionary.set(ustr__ZSesp(), location + 4); |
michael@0 | 356 | trust = StackFrame::FRAME_TRUST_SCAN; |
michael@0 | 357 | } |
michael@0 | 358 | |
michael@0 | 359 | // Since this stack frame did not use %ebp in a traditional way, |
michael@0 | 360 | // locating the return address isn't entirely deterministic. In that |
michael@0 | 361 | // case, the stack can be scanned to locate the return address. |
michael@0 | 362 | // |
michael@0 | 363 | // However, if program string evaluation resulted in both %eip and |
michael@0 | 364 | // %ebp values of 0, trust that the end of the stack has been |
michael@0 | 365 | // reached and don't scan for anything else. |
michael@0 | 366 | if (dictionary.get(ustr__ZSeip()) != 0 || |
michael@0 | 367 | dictionary.get(ustr__ZSebp()) != 0) { |
michael@0 | 368 | int offset = 0; |
michael@0 | 369 | |
michael@0 | 370 | // This scan can only be done if a CodeModules object is available, to |
michael@0 | 371 | // check that candidate return addresses are in fact inside a module. |
michael@0 | 372 | // |
michael@0 | 373 | // TODO(mmentovai): This ignores dynamically-generated code. One possible |
michael@0 | 374 | // solution is to check the minidump's memory map to see if the candidate |
michael@0 | 375 | // %eip value comes from a mapped executable page, although this would |
michael@0 | 376 | // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad |
michael@0 | 377 | // client doesn't currently write (it would need to call MiniDumpWriteDump |
michael@0 | 378 | // with the MiniDumpWithFullMemoryInfo type bit set). Even given this |
michael@0 | 379 | // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce |
michael@0 | 380 | // an independent execute privilege on memory pages. |
michael@0 | 381 | |
michael@0 | 382 | uint32_t eip = dictionary.get(ustr__ZSeip()); |
michael@0 | 383 | if (modules_ && !modules_->GetModuleForAddress(eip)) { |
michael@0 | 384 | // The instruction pointer at .raSearchStart was invalid, so start |
michael@0 | 385 | // looking one 32-bit word above that location. |
michael@0 | 386 | uint32_t location_start = dictionary.get(ustr__ZDraSearchStart()) + 4; |
michael@0 | 387 | uint32_t location; |
michael@0 | 388 | if (stack_scan_allowed |
michael@0 | 389 | && ScanForReturnAddress(location_start, &location, &eip)) { |
michael@0 | 390 | // This is a better return address that what program string |
michael@0 | 391 | // evaluation found. Use it, and set %esp to the location above the |
michael@0 | 392 | // one where the return address was found. |
michael@0 | 393 | dictionary.set(ustr__ZSeip(), eip); |
michael@0 | 394 | dictionary.set(ustr__ZSesp(), location + 4); |
michael@0 | 395 | offset = location - location_start; |
michael@0 | 396 | trust = StackFrame::FRAME_TRUST_CFI_SCAN; |
michael@0 | 397 | } |
michael@0 | 398 | } |
michael@0 | 399 | |
michael@0 | 400 | if (recover_ebp) { |
michael@0 | 401 | // When trying to recover the previous value of the frame pointer (%ebp), |
michael@0 | 402 | // start looking at the lowest possible address in the saved-register |
michael@0 | 403 | // area, and look at the entire saved register area, increased by the |
michael@0 | 404 | // size of |offset| to account for additional data that may be on the |
michael@0 | 405 | // stack. The scan is performed from the highest possible address to |
michael@0 | 406 | // the lowest, because the expectation is that the function's prolog |
michael@0 | 407 | // would have saved %ebp early. |
michael@0 | 408 | uint32_t ebp = dictionary.get(ustr__ZSebp()); |
michael@0 | 409 | |
michael@0 | 410 | // When a scan for return address is used, it is possible to skip one or |
michael@0 | 411 | // more frames (when return address is not in a known module). One |
michael@0 | 412 | // indication for skipped frames is when the value of %ebp is lower than |
michael@0 | 413 | // the location of the return address on the stack |
michael@0 | 414 | bool has_skipped_frames = |
michael@0 | 415 | (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset); |
michael@0 | 416 | |
michael@0 | 417 | uint32_t value; // throwaway variable to check pointer validity |
michael@0 | 418 | if (has_skipped_frames || !memory_->GetMemoryAtAddress(ebp, &value)) { |
michael@0 | 419 | int fp_search_bytes = last_frame_info->saved_register_size + offset; |
michael@0 | 420 | uint32_t location_end = last_frame->context.esp + |
michael@0 | 421 | last_frame_callee_parameter_size; |
michael@0 | 422 | |
michael@0 | 423 | for (uint32_t location = location_end + fp_search_bytes; |
michael@0 | 424 | location >= location_end; |
michael@0 | 425 | location -= 4) { |
michael@0 | 426 | if (!memory_->GetMemoryAtAddress(location, &ebp)) |
michael@0 | 427 | break; |
michael@0 | 428 | |
michael@0 | 429 | if (memory_->GetMemoryAtAddress(ebp, &value)) { |
michael@0 | 430 | // The candidate value is a pointer to the same memory region |
michael@0 | 431 | // (the stack). Prefer it as a recovered %ebp result. |
michael@0 | 432 | dictionary.set(ustr__ZSebp(), ebp); |
michael@0 | 433 | break; |
michael@0 | 434 | } |
michael@0 | 435 | } |
michael@0 | 436 | } |
michael@0 | 437 | } |
michael@0 | 438 | } |
michael@0 | 439 | |
michael@0 | 440 | // Create a new stack frame (ownership will be transferred to the caller) |
michael@0 | 441 | // and fill it in. |
michael@0 | 442 | StackFrameX86* frame = new StackFrameX86(); |
michael@0 | 443 | |
michael@0 | 444 | frame->trust = trust; |
michael@0 | 445 | frame->context = last_frame->context; |
michael@0 | 446 | frame->context.eip = dictionary.get(ustr__ZSeip()); |
michael@0 | 447 | frame->context.esp = dictionary.get(ustr__ZSesp()); |
michael@0 | 448 | frame->context.ebp = dictionary.get(ustr__ZSebp()); |
michael@0 | 449 | frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | |
michael@0 | 450 | StackFrameX86::CONTEXT_VALID_ESP | |
michael@0 | 451 | StackFrameX86::CONTEXT_VALID_EBP; |
michael@0 | 452 | |
michael@0 | 453 | // These are nonvolatile (callee-save) registers, and the program string |
michael@0 | 454 | // may have filled them in. |
michael@0 | 455 | if (dictionary_validity.have(ustr__ZSebx())) { |
michael@0 | 456 | frame->context.ebx = dictionary.get(ustr__ZSebx()); |
michael@0 | 457 | frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX; |
michael@0 | 458 | } |
michael@0 | 459 | if (dictionary_validity.have(ustr__ZSesi())) { |
michael@0 | 460 | frame->context.esi = dictionary.get(ustr__ZSesi()); |
michael@0 | 461 | frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI; |
michael@0 | 462 | } |
michael@0 | 463 | if (dictionary_validity.have(ustr__ZSedi())) { |
michael@0 | 464 | frame->context.edi = dictionary.get(ustr__ZSedi()); |
michael@0 | 465 | frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI; |
michael@0 | 466 | } |
michael@0 | 467 | |
michael@0 | 468 | return frame; |
michael@0 | 469 | } |
michael@0 | 470 | |
michael@0 | 471 | StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( |
michael@0 | 472 | const vector<StackFrame*> &frames, |
michael@0 | 473 | CFIFrameInfo* cfi_frame_info) { |
michael@0 | 474 | StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); |
michael@0 | 475 | last_frame->cfi_frame_info = cfi_frame_info; |
michael@0 | 476 | |
michael@0 | 477 | scoped_ptr<StackFrameX86> frame(new StackFrameX86()); |
michael@0 | 478 | if (!cfi_walker_ |
michael@0 | 479 | .FindCallerRegisters(*memory_, *cfi_frame_info, |
michael@0 | 480 | last_frame->context, last_frame->context_validity, |
michael@0 | 481 | &frame->context, &frame->context_validity)) |
michael@0 | 482 | return NULL; |
michael@0 | 483 | |
michael@0 | 484 | // Make sure we recovered all the essentials. |
michael@0 | 485 | static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP |
michael@0 | 486 | | StackFrameX86::CONTEXT_VALID_ESP |
michael@0 | 487 | | StackFrameX86::CONTEXT_VALID_EBP); |
michael@0 | 488 | if ((frame->context_validity & essentials) != essentials) |
michael@0 | 489 | return NULL; |
michael@0 | 490 | |
michael@0 | 491 | frame->trust = StackFrame::FRAME_TRUST_CFI; |
michael@0 | 492 | |
michael@0 | 493 | return frame.release(); |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( |
michael@0 | 497 | const vector<StackFrame*> &frames, |
michael@0 | 498 | bool stack_scan_allowed) { |
michael@0 | 499 | StackFrame::FrameTrust trust; |
michael@0 | 500 | StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); |
michael@0 | 501 | uint32_t last_esp = last_frame->context.esp; |
michael@0 | 502 | uint32_t last_ebp = last_frame->context.ebp; |
michael@0 | 503 | |
michael@0 | 504 | // Assume that the standard %ebp-using x86 calling convention is in |
michael@0 | 505 | // use. |
michael@0 | 506 | // |
michael@0 | 507 | // The typical x86 calling convention, when frame pointers are present, |
michael@0 | 508 | // is for the calling procedure to use CALL, which pushes the return |
michael@0 | 509 | // address onto the stack and sets the instruction pointer (%eip) to |
michael@0 | 510 | // the entry point of the called routine. The called routine then |
michael@0 | 511 | // PUSHes the calling routine's frame pointer (%ebp) onto the stack |
michael@0 | 512 | // before copying the stack pointer (%esp) to the frame pointer (%ebp). |
michael@0 | 513 | // Therefore, the calling procedure's frame pointer is always available |
michael@0 | 514 | // by dereferencing the called procedure's frame pointer, and the return |
michael@0 | 515 | // address is always available at the memory location immediately above |
michael@0 | 516 | // the address pointed to by the called procedure's frame pointer. The |
michael@0 | 517 | // calling procedure's stack pointer (%esp) is 8 higher than the value |
michael@0 | 518 | // of the called procedure's frame pointer at the time the calling |
michael@0 | 519 | // procedure made the CALL: 4 bytes for the return address pushed by the |
michael@0 | 520 | // CALL itself, and 4 bytes for the callee's PUSH of the caller's frame |
michael@0 | 521 | // pointer. |
michael@0 | 522 | // |
michael@0 | 523 | // %eip_new = *(%ebp_old + 4) |
michael@0 | 524 | // %esp_new = %ebp_old + 8 |
michael@0 | 525 | // %ebp_new = *(%ebp_old) |
michael@0 | 526 | |
michael@0 | 527 | uint32_t caller_eip, caller_esp, caller_ebp; |
michael@0 | 528 | |
michael@0 | 529 | if (memory_->GetMemoryAtAddress(last_ebp + 4, &caller_eip) && |
michael@0 | 530 | memory_->GetMemoryAtAddress(last_ebp, &caller_ebp)) { |
michael@0 | 531 | caller_esp = last_ebp + 8; |
michael@0 | 532 | trust = StackFrame::FRAME_TRUST_FP; |
michael@0 | 533 | } else { |
michael@0 | 534 | // We couldn't read the memory %ebp refers to. It may be that %ebp |
michael@0 | 535 | // is pointing to non-stack memory. We'll scan the stack for a |
michael@0 | 536 | // return address. This can happen if last_frame is executing code |
michael@0 | 537 | // for a module for which we don't have symbols, and that module |
michael@0 | 538 | // is compiled without a frame pointer. |
michael@0 | 539 | if (!stack_scan_allowed |
michael@0 | 540 | || !ScanForReturnAddress(last_esp, &caller_esp, &caller_eip)) { |
michael@0 | 541 | // if we can't find an instruction pointer even with stack scanning, |
michael@0 | 542 | // give up. |
michael@0 | 543 | return NULL; |
michael@0 | 544 | } |
michael@0 | 545 | |
michael@0 | 546 | // ScanForReturnAddress found a reasonable return address. Advance |
michael@0 | 547 | // %esp to the location above the one where the return address was |
michael@0 | 548 | // found. Assume that %ebp is unchanged. |
michael@0 | 549 | caller_esp += 4; |
michael@0 | 550 | caller_ebp = last_ebp; |
michael@0 | 551 | |
michael@0 | 552 | trust = StackFrame::FRAME_TRUST_SCAN; |
michael@0 | 553 | } |
michael@0 | 554 | |
michael@0 | 555 | // Create a new stack frame (ownership will be transferred to the caller) |
michael@0 | 556 | // and fill it in. |
michael@0 | 557 | StackFrameX86* frame = new StackFrameX86(); |
michael@0 | 558 | |
michael@0 | 559 | frame->trust = trust; |
michael@0 | 560 | frame->context = last_frame->context; |
michael@0 | 561 | frame->context.eip = caller_eip; |
michael@0 | 562 | frame->context.esp = caller_esp; |
michael@0 | 563 | frame->context.ebp = caller_ebp; |
michael@0 | 564 | frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | |
michael@0 | 565 | StackFrameX86::CONTEXT_VALID_ESP | |
michael@0 | 566 | StackFrameX86::CONTEXT_VALID_EBP; |
michael@0 | 567 | |
michael@0 | 568 | return frame; |
michael@0 | 569 | } |
michael@0 | 570 | |
michael@0 | 571 | StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, |
michael@0 | 572 | bool stack_scan_allowed) { |
michael@0 | 573 | if (!memory_ || !stack) { |
michael@0 | 574 | BPLOG(ERROR) << "Can't get caller frame without memory or stack"; |
michael@0 | 575 | return NULL; |
michael@0 | 576 | } |
michael@0 | 577 | |
michael@0 | 578 | const vector<StackFrame*> &frames = *stack->frames(); |
michael@0 | 579 | StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); |
michael@0 | 580 | scoped_ptr<StackFrameX86> new_frame; |
michael@0 | 581 | |
michael@0 | 582 | // If the resolver has Windows stack walking information, use that. |
michael@0 | 583 | WindowsFrameInfo* windows_frame_info |
michael@0 | 584 | = frame_symbolizer_->FindWindowsFrameInfo(last_frame); |
michael@0 | 585 | if (windows_frame_info) |
michael@0 | 586 | new_frame.reset(GetCallerByWindowsFrameInfo(frames, windows_frame_info, |
michael@0 | 587 | stack_scan_allowed)); |
michael@0 | 588 | |
michael@0 | 589 | // If the resolver has DWARF CFI information, use that. |
michael@0 | 590 | if (!new_frame.get()) { |
michael@0 | 591 | CFIFrameInfo* cfi_frame_info = |
michael@0 | 592 | frame_symbolizer_->FindCFIFrameInfo(last_frame); |
michael@0 | 593 | if (cfi_frame_info) |
michael@0 | 594 | new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info)); |
michael@0 | 595 | } |
michael@0 | 596 | |
michael@0 | 597 | // Otherwise, hope that the program was using a traditional frame structure. |
michael@0 | 598 | if (!new_frame.get()) |
michael@0 | 599 | new_frame.reset(GetCallerByEBPAtBase(frames, stack_scan_allowed)); |
michael@0 | 600 | |
michael@0 | 601 | // If nothing worked, tell the caller. |
michael@0 | 602 | if (!new_frame.get()) |
michael@0 | 603 | return NULL; |
michael@0 | 604 | |
michael@0 | 605 | // Treat an instruction address of 0 as end-of-stack. |
michael@0 | 606 | if (new_frame->context.eip == 0) |
michael@0 | 607 | return NULL; |
michael@0 | 608 | |
michael@0 | 609 | // If the new stack pointer is at a lower address than the old, then |
michael@0 | 610 | // that's clearly incorrect. Treat this as end-of-stack to enforce |
michael@0 | 611 | // progress and avoid infinite loops. |
michael@0 | 612 | if (new_frame->context.esp <= last_frame->context.esp) |
michael@0 | 613 | return NULL; |
michael@0 | 614 | |
michael@0 | 615 | // new_frame->context.eip is the return address, which is the instruction |
michael@0 | 616 | // after the CALL that caused us to arrive at the callee. Set |
michael@0 | 617 | // new_frame->instruction to one less than that, so it points within the |
michael@0 | 618 | // CALL instruction. See StackFrame::instruction for details, and |
michael@0 | 619 | // StackFrameAMD64::ReturnAddress. |
michael@0 | 620 | new_frame->instruction = new_frame->context.eip - 1; |
michael@0 | 621 | |
michael@0 | 622 | return new_frame.release(); |
michael@0 | 623 | } |
michael@0 | 624 | |
michael@0 | 625 | } // namespace google_breakpad |