Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2173)

Unified Diff: syzygy/agent/common/stack_walker_x86.cc

Issue 2194383007: Port some more code to x64 (Closed) Base URL: git@github.com:google/syzygy.git@master
Patch Set: Rename the stack_walker unittest and fix the x86-64 implementation of stack_walker Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « syzygy/agent/common/stack_walker_x86.h ('k') | syzygy/agent/common/stack_walker_x86_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « syzygy/agent/common/stack_walker_x86.h ('k') | syzygy/agent/common/stack_walker_x86_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698