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