1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Defines an X86 stack walker for standard frames that contain a saved EBP
16 : // value at the top, generated by the common preamble:
17 : //
18 : // push ebp // Save the previous EBP. ESP now points at the saved EBP.
19 : // mov ebp, esp // EBP now points at the saved EBP.
20 : //
21 : // The algorithms expects the stack to be laid out as follows:
22 : //
23 : // +-------------+ <-- top of stack
24 : // | ...data.... |
25 : // | ret address |
26 : // +-------------+
27 : // | saved ebp |
28 : // | ...data.... | <-- frame 0 (root)
29 : // | ret address |
30 : // +-------------+
31 : // | saved ebp |
32 : // | ...data.... | <-- frame 1
33 : // | ret address |
34 : // +-------------+
35 : // . . .
36 : // . . .
37 : // +-------------+
38 : // | saved ebp |
39 : // | ...data.... | <-- frame n (leaf)
40 : // | ret address |
41 : // +-------------+ <-- bottom of stack
42 : //
43 : // If the stack is truly laid out as above then there are a few invariants that
44 : // must hold:
45 : //
46 : // - The return address of the previous frame is at EBP + 4. This must be a
47 : // sensible return address (non-null, and not in the stack itself).
48 : // - Frames are laid out linearly on the stack, so successive EBP values must
49 : // be monotonically increasing.
50 : // - Push aligns the stack to the machine word size, so all EBP values must be
51 : // 4-byte aligned.
52 : // - There must be the content of the saved EBP and a return pointer between
53 : // any two successive EBP values, so they must be at least 8 bytes apart.
54 : // - The frames must be entirely contained within the stack itself, so strictly
55 : // between the known bottom and top of the stack.
56 : //
57 : // The algorithm walks the stack as far as it can while the above invariants
58 : // hold true, saving the value of the return pointer for each valid frame
59 : // encountered. Note that it can quickly derail if frame pointer optimization
60 : // is enabled, or at any frame that uses a non-standard layout.
61 :
62 : #ifndef SYZYGY_AGENT_COMMON_STACK_WALKER_X86_H_
63 : #define SYZYGY_AGENT_COMMON_STACK_WALKER_X86_H_
64 :
65 : #include "base/basictypes.h"
66 : #include "syzygy/common/asan_parameters.h"
67 :
68 m : namespace agent {
69 m : namespace common {
70 :
71 m : using StackId = ::common::AsanStackId;
72 :
73 : // Heuristically walks the current stack. Does not consider its own stack
74 : // frame. Frames are expected to have a standard layout with the top of the
75 : // frame being a saved frame pointer, and the bottom of a frame being a return
76 : // address.
77 : // @param bottom_frames_to_skip The number of frames to skip from the bottom
78 : // of the stack.
79 : // @param max_frame_count The maximum number of frames that can be written to
80 : // @p frames.
81 : // @param frames The array to be populated with the computed frames.
82 : // @param absolute_stack_id Pointer to the stack ID that will be calculated as
83 : // we are walking the stack.
84 : // @returns the number of frames successfully walked and stored in @p frames.
85 m : size_t WalkStack(size_t bottom_frames_to_skip,
86 m : size_t max_frame_count,
87 m : void** frames,
88 m : StackId* absolute_stack_id);
89 :
90 : // Implementation of WalkStack, with explicitly provided @p current_ebp,
91 : // @p stack_bottom and @p stack_top. Exposed for much easier unittesting.
92 : // @param current_ebp The current stack frame base to start walking from.
93 : // This must be a valid stack location from which to start walking.
94 : // @param stack_bottom The bottom of the stack to walk. (Lower address.)
95 : // @param stack_top The top of the stack to walk. (Higher address.)
96 : // @param bottom_frames_to_skip The number of frames to skip from the bottom
97 : // of the stack.
98 : // @param max_frame_count The maximum number of frames that can be written to
99 : // @p frames.
100 : // @param frames The array to be populated with the computed frames.
101 : // @param absolute_stack_id Pointer to the stack ID that will be calculated as
102 : // we are walking the stack.
103 : // @returns the number of frames successfully walked and stored in @p frames.
104 m : size_t WalkStackImpl(const void* current_ebp,
105 m : const void* stack_bottom,
106 m : const void* stack_top,
107 m : size_t bottom_frames_to_skip,
108 m : size_t max_frame_count,
109 m : void** frames,
110 m : StackId* absolute_stack_id);
111 :
112 m : } // namespace common
113 m : } // namespace agent
114 :
115 : #endif // SYZYGY_AGENT_COMMON_STACK_WALKER_X86_H_
|