Index: syzygy/agent/common/stack_walker_x86.cc |
diff --git a/syzygy/agent/common/stack_walker_x86.cc b/syzygy/agent/common/stack_walker_x86.cc |
deleted file mode 100644 |
index 2a63172ac70f359e72a512e79f3f793398b09541..0000000000000000000000000000000000000000 |
--- a/syzygy/agent/common/stack_walker_x86.cc |
+++ /dev/null |
@@ -1,186 +0,0 @@ |
-// Copyright 2015 Google Inc. All Rights Reserved. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
- |
-#include "syzygy/agent/common/stack_walker_x86.h" |
- |
-#include <windows.h> |
-#include <winnt.h> |
- |
-#include "base/logging.h" |
-#include "syzygy/agent/common/stack_capture.h" |
-#include "syzygy/common/align.h" |
- |
-namespace agent { |
-namespace common { |
- |
-namespace { |
- |
-static size_t kPointerSize = sizeof(void*); |
- |
-__declspec(naked) void* GetEbp() { |
- __asm { |
- mov eax, ebp |
- ret |
- } |
-} |
- |
-__declspec(naked) void* GetEsp() { |
- __asm { |
- mov eax, esp |
- ret |
- } |
-} |
- |
-// A small struct that can be laid out on top of a standard stack frame in |
-// order to grab the EBP and return address fields. Strictly speaking this |
-// is actually a snippet along the edge of two frames: |next_frame| belonging |
-// to the callee, and |return_address| belonging to the caller. |
-struct StackFrame { |
- StackFrame* next_frame; |
- void* return_address; |
-}; |
- |
-// Helper function to determine if the given stack frame is in bounds with |
-// respect to the top of the stack. |
-__forceinline bool IsFrameInBounds(const void* stack_top, const void* frame) { |
- // We've already confirmed that stack_bottom < stack_top, so stack_top can be |
- // safely decremented without underflowing. On the other hand, we can't |
- // increment |frame| without potentially overflowing. Yup, learned that one |
- // the hard way. |
- DCHECK_LE(reinterpret_cast<const void*>(4), stack_top); |
- return frame <= reinterpret_cast<const StackFrame*>(stack_top) - 1; |
-} |
- |
-// Returns true if the stack frame has a valid return address that can be |
-// read from. |
-__forceinline bool FrameHasValidReturnAddress(const void* stack_bottom, |
- const void* stack_top, |
- const StackFrame* frame) { |
- if (!IsFrameInBounds(stack_top, frame)) |
- return false; |
- |
- // The current frame must be pointer aligned. |
- if (!::common::IsAligned(frame, kPointerSize)) |
- return false; |
- |
- // The return address must not be null, and it can't be in the stack. |
- if (frame->return_address == nullptr) |
- return false; |
- if (frame->return_address >= stack_bottom && |
- frame->return_address < stack_top) { |
- return false; |
- } |
- |
- return true; |
-} |
- |
-__forceinline bool CanAdvanceFrame(const StackFrame* frame) { |
- // The next frame pointer must be at least a full frame beyond the current |
- // frame. Checking that the next frame lies within the stack is done by |
- // 'FrameHasValidReturnAddress' before it gets read. |
- if (frame + 1 > frame->next_frame) |
- return false; |
- return true; |
-} |
- |
-} // namespace |
- |
-size_t __declspec(noinline) WalkStack(size_t bottom_frames_to_skip, |
- size_t max_frame_count, |
- void** frames, |
- StackId* absolute_stack_id) { |
- // Get the stack extents. |
- // The first thing in the TEB is actually the TIB. |
- // http://www.nirsoft.net/kernel_struct/vista/TEB.html |
- NT_TIB* tib = reinterpret_cast<NT_TIB*>(NtCurrentTeb()); |
- void* stack_bottom = tib->StackLimit; // Lower address. |
- void* stack_top = tib->StackBase; // Higher address. |
- |
- // Ensure that the stack extents make sense, and bail early if they |
- // don't. Only proceed if there's at least room for a single pointer on |
- // the stack. |
- if (!::common::IsAligned(stack_top, kPointerSize) || |
- stack_bottom >= stack_top || |
- reinterpret_cast<StackFrame*>(stack_bottom) + 1 >= stack_top) { |
- return 0; |
- } |
- |
- // Ensure that the stack makes sense. If not, it's been hijacked and |
- // something is seriously wrong. |
- void *current_esp = GetEsp(); |
- void* current_ebp = GetEbp(); |
- if (stack_bottom > current_esp || current_esp > current_ebp || |
- !IsFrameInBounds(stack_top, current_ebp)) { |
- return 0; |
- } |
- |
- return WalkStackImpl(current_ebp, stack_bottom, stack_top, |
- bottom_frames_to_skip, max_frame_count, frames, |
- absolute_stack_id); |
-} |
- |
-size_t WalkStackImpl(const void* current_ebp, |
- const void* stack_bottom, |
- const void* stack_top, |
- size_t bottom_frames_to_skip, |
- size_t max_frame_count, |
- void** frames, |
- StackId* absolute_stack_id) { |
- DCHECK(::common::IsAligned(current_ebp, kPointerSize)); |
- DCHECK(::common::IsAligned(stack_top, kPointerSize)); |
- DCHECK_LT(stack_bottom, stack_top); |
- DCHECK_LE(reinterpret_cast<const StackFrame*>(stack_bottom) + 1, stack_top); |
- DCHECK_LE(current_ebp, stack_top); |
- DCHECK_NE(static_cast<void**>(nullptr), frames); |
- DCHECK_NE(static_cast<StackId*>(nullptr), absolute_stack_id); |
- |
- *absolute_stack_id = StackCapture::StartStackId(); |
- |
- const StackFrame* current_frame = |
- reinterpret_cast<const StackFrame*>(current_ebp); |
- |
- // Skip over any requested frames. |
- while (bottom_frames_to_skip) { |
- if (!FrameHasValidReturnAddress(stack_bottom, stack_top, current_frame)) |
- return 0; |
- if (!CanAdvanceFrame(current_frame)) |
- return 0; |
- --bottom_frames_to_skip; |
- current_frame = current_frame->next_frame; |
- } |
- |
- // Grab as many frames as possible. |
- size_t num_frames = 0; |
- while (num_frames < max_frame_count) { |
- if (!FrameHasValidReturnAddress(stack_bottom, stack_top, current_frame)) |
- break; |
- frames[num_frames] = current_frame->return_address; |
- ++num_frames; |
- *absolute_stack_id = StackCapture::UpdateStackId( |
- *absolute_stack_id, current_frame->return_address); |
- |
- if (!CanAdvanceFrame(current_frame)) |
- break; |
- |
- current_frame = current_frame->next_frame; |
- } |
- |
- *absolute_stack_id = |
- StackCapture::FinalizeStackId(*absolute_stack_id, num_frames); |
- |
- return num_frames; |
-} |
- |
-} // namespace common |
-} // namespace agent |