1*9712c20fSFrederick Mayle# Introduction 2*9712c20fSFrederick Mayle 3*9712c20fSFrederick MayleThis page aims to provide a detailed description of how Breakpad produces stack 4*9712c20fSFrederick Mayletraces from the information contained within a minidump file. 5*9712c20fSFrederick Mayle 6*9712c20fSFrederick Mayle# Details 7*9712c20fSFrederick Mayle 8*9712c20fSFrederick Mayle## Starting the Process 9*9712c20fSFrederick Mayle 10*9712c20fSFrederick MayleTypically the stack walking process is initiated by instantiating the 11*9712c20fSFrederick Mayle[MinidumpProcessor](../src/processor/minidump_processor.cc) 12*9712c20fSFrederick Mayleclass and calling the [MinidumpProcessor::Process](../src/processor/minidump_processor.cc#61) 13*9712c20fSFrederick Maylemethod, providing it a minidump file to process. To produce a useful stack 14*9712c20fSFrederick Mayletrace, the MinidumpProcessor requires two other objects which are passed in its 15*9712c20fSFrederick Mayleconstructor: a [SymbolSupplier](../src/google_breakpad/processor/symbol_supplier.h) 16*9712c20fSFrederick Mayleand a [SourceLineResolverInterface](../src/google_breakpad/processor/source_line_resolver_interface.h). 17*9712c20fSFrederick MayleThe SymbolSupplier object is responsible for locating and providing SymbolFiles 18*9712c20fSFrederick Maylethat match modules from the minidump. The SourceLineResolverInterface is 19*9712c20fSFrederick Mayleresponsible for loading the symbol files and using the information contained 20*9712c20fSFrederick Maylewithin to provide function and source information for stack frames, as well as 21*9712c20fSFrederick Mayleinformation on how to unwind from a stack frame to its caller. More detail will 22*9712c20fSFrederick Maylebe provided on these interactions later. 23*9712c20fSFrederick Mayle 24*9712c20fSFrederick MayleA number of data streams are extracted from the minidump to begin stack walking: 25*9712c20fSFrederick Maylethe list of threads from the process 26*9712c20fSFrederick Mayle([MinidumpThreadList](../src/google_breakpad/processor/minidump.h#335)), 27*9712c20fSFrederick Maylethe list of modules loaded in the process 28*9712c20fSFrederick Mayle([MinidumpModuleList](../src/google_breakpad/processor/minidump.h#501)), 29*9712c20fSFrederick Mayleand information about the exception that caused the process to crash 30*9712c20fSFrederick Mayle([MinidumpException](../src/google_breakpad/processor/minidump.h#615)). 31*9712c20fSFrederick Mayle 32*9712c20fSFrederick Mayle## Enumerating Threads 33*9712c20fSFrederick Mayle 34*9712c20fSFrederick MayleFor each thread in the thread list 35*9712c20fSFrederick Mayle([MinidumpThread](../src/google_breakpad/processor/minidump.h#299)), 36*9712c20fSFrederick Maylethe thread memory containing the stack for the thread 37*9712c20fSFrederick Mayle([MinidumpMemoryRegion](../src/google_breakpad/processor/minidump.h#236)) 38*9712c20fSFrederick Mayleand the CPU context representing the CPU state of the thread at the time the 39*9712c20fSFrederick Mayledump was written ([MinidumpContext](../src/google_breakpad/processor/minidump.h#171)) 40*9712c20fSFrederick Mayleare extracted from the minidump. If the thread being processed is the thread 41*9712c20fSFrederick Maylethat produced the exception then a CPU context is obtained from the 42*9712c20fSFrederick MayleMinidumpException object instead, which represents the CPU state of the thread 43*9712c20fSFrederick Mayleat the point of the exception. A stack walker is then instantiated by calling 44*9712c20fSFrederick Maylethe [Stackwalker::StackwalkerForCPU](../src/google_breakpad/processor/stackwalker.h#77) 45*9712c20fSFrederick Maylemethod and passing it the CPU context, the thread memory, the module list, as 46*9712c20fSFrederick Maylewell as the SymbolSupplier and SourceLineResolverInterface. This method selects 47*9712c20fSFrederick Maylethe specific !Stackwalker subclass based on the CPU architecture of the provided 48*9712c20fSFrederick MayleCPU context and returns an instance of that subclass. 49*9712c20fSFrederick Mayle 50*9712c20fSFrederick Mayle## Walking a thread's stack 51*9712c20fSFrederick Mayle 52*9712c20fSFrederick MayleOnce a !Stackwalker instance has been obtained, the processor calls the 53*9712c20fSFrederick Mayle[Stackwalker::Walk](../src/google_breakpad/processor/source_line_resolver_interface.h) 54*9712c20fSFrederick Maylemethod to obtain a list of frames representing the stack of this thread. The 55*9712c20fSFrederick Mayle!Stackwalker starts by calling the GetContextFrame method which returns a 56*9712c20fSFrederick MayleStackFrame representing the top of the stack, with CPU state provided by the 57*9712c20fSFrederick Mayleinitial CPU context. From there, the stack walker repeats the following steps 58*9712c20fSFrederick Maylefor each frame in turn: 59*9712c20fSFrederick Mayle 60*9712c20fSFrederick Mayle### Finding the Module 61*9712c20fSFrederick Mayle 62*9712c20fSFrederick MayleThe address of the instruction pointer of the current frame is used to determine 63*9712c20fSFrederick Maylewhich module contains the current frame by calling the module list's 64*9712c20fSFrederick Mayle[GetModuleForAddress](../src/google_breakpad/processor/code_modules.h#56) method. 65*9712c20fSFrederick Mayle 66*9712c20fSFrederick Mayle### Locating Symbols 67*9712c20fSFrederick Mayle 68*9712c20fSFrederick MayleIf a module is located, the SymbolSupplier is asked to locate symbols 69*9712c20fSFrederick Maylecorresponding to the module by calling its 70*9712c20fSFrederick Mayle[GetCStringSymbolData](../src/google_breakpad/processor/symbol_supplier.h#87) 71*9712c20fSFrederick Maylemethod. Typically this is implemented by using the module's debug filename (the 72*9712c20fSFrederick MaylePDB filename for Windows dumps) and debug identifier (a GUID plus one extra 73*9712c20fSFrederick Mayledigit) as a lookup key. The [SimpleSymbolSupplier](../src/processor/simple_symbol_supplier.cc) 74*9712c20fSFrederick Mayleclass simply uses these as parts of a file path to locate a flat file on disk. 75*9712c20fSFrederick Mayle 76*9712c20fSFrederick Mayle### Loading Symbols 77*9712c20fSFrederick Mayle 78*9712c20fSFrederick MayleIf a symbol file is located, the SourceLineResolverInterface is then asked to 79*9712c20fSFrederick Mayleload the symbol file by calling its 80*9712c20fSFrederick Mayle[LoadModuleUsingMemoryBuffer](../src/google_breakpad/processor/source_line_resolver_interface.h#71) 81*9712c20fSFrederick Maylemethod. The [BasicSourceLineResolver](../src/processor/basic_source_line_resolver.cc) 82*9712c20fSFrederick Mayleimplementation parses the text-format [symbol file](symbol_files.md) into 83*9712c20fSFrederick Maylein-memory data structures to make lookups by address of function names, source 84*9712c20fSFrederick Mayleline information, and unwind information easy. 85*9712c20fSFrederick Mayle 86*9712c20fSFrederick Mayle### Getting source line information 87*9712c20fSFrederick Mayle 88*9712c20fSFrederick MayleIf a symbol file has been successfully loaded, the SourceLineResolverInterface's 89*9712c20fSFrederick Mayle[FillSourceLineInfo](../src/google_breakpad/processor/source_line_resolver_interface.h#89) 90*9712c20fSFrederick Maylemethod is called to provide a function name and source line information for the 91*9712c20fSFrederick Maylecurrent frame. This is done by subtracting the base address of the module 92*9712c20fSFrederick Maylecontaining the current frame from the instruction pointer of the current frame 93*9712c20fSFrederick Mayleto obtain a relative virtual address (RVA), which is a code offset relative to 94*9712c20fSFrederick Maylethe start of the module. This RVA is then used as a lookup into a table of 95*9712c20fSFrederick Maylefunctions ([FUNC lines](SymbolFiles#FUNC_records.md) from the symbol file), each 96*9712c20fSFrederick Mayleof which has an associated address range (function start address, function 97*9712c20fSFrederick Maylesize). If a function is found whose address range contains the RVA, then its 98*9712c20fSFrederick Maylename is used. The RVA is then used as a lookup into a table of source lines 99*9712c20fSFrederick Mayle([line records](SymbolFiles#Line_records.md) from the symbol file), each of 100*9712c20fSFrederick Maylewhich also has an associated address range. If a match is found it will provide 101*9712c20fSFrederick Maylethe file name and source line associated with the current frame. If no match was 102*9712c20fSFrederick Maylefound in the function table, another table of publicly exported symbols may be 103*9712c20fSFrederick Mayleconsulted ([PUBLIC lines](SymbolFiles#PUBLIC_records.md) from the symbol file). 104*9712c20fSFrederick MaylePublic symbols contain only a start address, so the lookup simply looks for the 105*9712c20fSFrederick Maylenearest symbol that is less than the provided RVA. 106*9712c20fSFrederick Mayle 107*9712c20fSFrederick Mayle### Finding the caller frame 108*9712c20fSFrederick Mayle 109*9712c20fSFrederick MayleTo find the next frame in the stack, the !Stackwalker calls its 110*9712c20fSFrederick Mayle[GetCallerFrame](../src/google_breakpad/processor/stackwalker.h#186) 111*9712c20fSFrederick Maylemethod, passing in the current frame. Each !Stackwalker subclass implements 112*9712c20fSFrederick MayleGetCallerFrame differently, but there are common patterns. 113*9712c20fSFrederick Mayle 114*9712c20fSFrederick MayleTypically the first step is to query the SourceLineResolverInterface for the 115*9712c20fSFrederick Maylepresence of detailed unwind information. This is done using its 116*9712c20fSFrederick Mayle[FindWindowsFrameInfo](../src/google_breakpad/processor/source_line_resolver_interface.h#96) 117*9712c20fSFrederick Mayleand [FindCFIFrameInfo](../src/google_breakpad/processor/source_line_resolver_interface.h#102) 118*9712c20fSFrederick Maylemethods. These methods look for Windows unwind info extracted from a PDB file 119*9712c20fSFrederick Mayle([STACK WIN](SymbolFiles#STACK_WIN_records.md) lines from the symbol file), or 120*9712c20fSFrederick MayleDWARF CFI extracted from a binary ([STACK CFI](SymbolFiles#STACK_CFI_records.md) 121*9712c20fSFrederick Maylelines from the symbol file) respectively. The information covers address ranges, 122*9712c20fSFrederick Mayleso the RVA of the current frame is used for lookup as with function and source 123*9712c20fSFrederick Mayleline information. 124*9712c20fSFrederick Mayle 125*9712c20fSFrederick MayleIf unwind info is found it provides a set of rules to recover the register state 126*9712c20fSFrederick Mayleof the caller frame given the current register state as well as the thread's 127*9712c20fSFrederick Maylestack memory. The rules are evaluated to produce the caller frame. 128*9712c20fSFrederick Mayle 129*9712c20fSFrederick MayleIf unwind info is not found then the !Stackwalker may resort to other methods. 130*9712c20fSFrederick MayleTypically on architectures which specify a frame pointer unwinding by 131*9712c20fSFrederick Mayledereferencing the frame pointer is tried next. If that is successful it is used 132*9712c20fSFrederick Mayleto produce the caller frame. 133*9712c20fSFrederick Mayle 134*9712c20fSFrederick MayleIf no caller frame was found by any other method most !Stackwalker 135*9712c20fSFrederick Mayleimplementations resort to stack scanning by looking at each word on the stack 136*9712c20fSFrederick Mayledown to a fixed depth (implemented in the 137*9712c20fSFrederick Mayle[Stackwalker::ScanForReturnAddress](../src/google_breakpad/processor/stackwalker.h#131) 138*9712c20fSFrederick Maylemethod) and using a heuristic to attempt to find a reasonable return address 139*9712c20fSFrederick Mayle(implemented in the 140*9712c20fSFrederick Mayle[Stackwalker::InstructionAddressSeemsValid](../src/google_breakpad/processor/stackwalker.h#111) method). 141*9712c20fSFrederick Mayle 142*9712c20fSFrederick MayleIf no caller frame is found or the caller frame seems invalid, stack walking 143*9712c20fSFrederick Maylestops. If a caller frame was found then these steps repeat using the new frame 144*9712c20fSFrederick Mayleas the current frame. 145