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