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