xref: /aosp_15_r20/external/google-breakpad/docs/stack_walking.md (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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