| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/debug/zxdb/client/thread_controller.h" |
| |
| #include <stdarg.h> |
| |
| #include "src/developer/debug/zxdb/client/frame.h" |
| #include "src/developer/debug/zxdb/client/thread.h" |
| #include "src/developer/debug/zxdb/symbols/function.h" |
| |
| namespace zxdb { |
| |
| ThreadController::ThreadController() = default; |
| |
| ThreadController::~ThreadController() = default; |
| |
| #if defined(DEBUG_THREAD_CONTROLLERS) |
| void ThreadController::Log(const char* format, ...) const { |
| va_list ap; |
| va_start(ap, format); |
| |
| printf("%s controller: ", GetName()); |
| vprintf(format, ap); |
| |
| // Manually add \r so output will be reasonable even if the terminal is in |
| // raw mode. |
| printf("\r\n"); |
| |
| va_end(ap); |
| } |
| |
| // static |
| void ThreadController::LogRaw(const char* format, ...) { |
| va_list ap; |
| va_start(ap, format); |
| vprintf(format, ap); |
| printf("\r\n"); |
| va_end(ap); |
| } |
| |
| // static |
| std::string ThreadController::FrameFunctionNameForLog(const Frame* frame) { |
| const char kNone[] = "<none>"; |
| |
| const Location& loc = frame->GetLocation(); |
| if (!loc.symbol()) |
| return kNone; |
| |
| const Function* func = loc.symbol().Get()->AsFunction(); |
| if (!func) |
| return kNone; |
| |
| return func->GetFullName(); |
| } |
| #endif |
| |
| void ThreadController::SetInlineFrameIfAmbiguous(InlineFrameIs comparison, |
| FrameFingerprint fingerprint) { |
| Stack& stack = thread()->GetStack(); |
| |
| // Reset any hidden inline frames so we can iterate through all of them |
| // (and we'll leave this reset to 0 if the requested one isn't found). |
| size_t old_hide_count = stack.hide_ambiguous_inline_frame_count(); |
| stack.SetHideAmbiguousInlineFrameCount(0); |
| |
| for (size_t i = 0; i < stack.size(); i++) { |
| const Frame* frame = stack[i]; |
| auto found = stack.GetFrameFingerprint(i); |
| if (!found) |
| break; // Got to bottom of computable fingerprints, give up. |
| |
| // To be ambiguous, all frames to here need to be at the same address and |
| // all inline frames need to be at the beginning of one of their ranges. |
| // (the physical frame also needs matching but its range doesn't count). |
| bool is_inline = frame->IsInline(); |
| |
| if (*found == fingerprint) { |
| // Found it. |
| if (comparison == InlineFrameIs::kEqual) { |
| // Make this one the top of the stack. |
| stack.SetHideAmbiguousInlineFrameCount(i); |
| return; |
| } else { // comparison == InlineFrameIs::kOneBefore. |
| // Make the one below this frame topmost. That requires the current |
| // frame be inline since it will be hidden. |
| if (is_inline) { |
| stack.SetHideAmbiguousInlineFrameCount(i + 1); |
| return; |
| } |
| } |
| break; |
| } |
| |
| if (!is_inline) |
| break; // Don't check below the first physical frame. |
| |
| // The fingerprint can be set on a frame as long as all frames above it |
| // were ambiguous, but the frame being set to is usually not ambiguous |
| // (it's often the physical frame that calls an inline function, for |
| // example). |
| if (!frame->IsAmbiguousInlineLocation()) |
| break; |
| } |
| |
| if (old_hide_count) |
| stack.SetHideAmbiguousInlineFrameCount(old_hide_count); |
| } |
| |
| void ThreadController::NotifyControllerDone() { |
| thread_->NotifyControllerDone(this); |
| // Warning: |this| is likely deleted. |
| } |
| |
| } // namespace zxdb |