blob: 8dc1714b8b34e759709488d432259448b928d493 [file] [log] [blame]
// Copyright 2021 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 <algorithm>
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/source_file_provider_impl.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/debug_adapter/context.h"
namespace zxdb {
dap::StackTraceResponse PopulateStackTraceResponse(DebugAdapterContext* ctx, Thread* thread,
const dap::StackTraceRequest& req) {
dap::StackTraceResponse response;
auto& stack = thread->GetStack();
int64_t total_frames = static_cast<int64_t>(stack.size());
int64_t start_frame = req.startFrame.value(0);
// If levels is 0, DAP specifies to return all frames.
int64_t frames_to_return = total_frames;
if (req.levels && req.levels.value() > 0) {
frames_to_return = req.levels.value();
}
// Clamp the end frame to the actual end of the stack.
int64_t end_frame = std::min(start_frame + frames_to_return, total_frames);
auto elided_frames = ctx->GetElidedFrames(stack);
auto file_provider = SourceFileProviderImpl(thread->GetProcess()->GetTarget()->settings());
for (auto i = start_frame; i < end_frame; i++) {
dap::StackFrame frame;
auto location = stack[i]->GetLocation();
frame.source = dap::Source{};
// Try to get the source path.
auto data_or =
file_provider.GetFileData(location.file_line().file(), location.file_line().comp_dir());
if (!data_or.has_error()) {
frame.source->path = data_or.value().full_path;
}
frame.line = location.file_line().line();
frame.column = location.column();
frame.name = location.symbol().Get()->GetFullName();
frame.id = ctx->IdForFrame(thread->GetKoid(), i);
if (elided_frames[i]) {
frame.presentationHint = "subtle";
frame.source->origin = elided_frames[i].description;
}
response.stackFrames.push_back(frame);
}
response.totalFrames = total_frames;
return response;
}
void OnRequestStackTrace(
DebugAdapterContext* ctx, const dap::StackTraceRequest& req,
std::function<void(dap::ResponseOrError<dap::StackTraceResponse>)> callback) {
Thread* thread = ctx->GetThread(static_cast<uint64_t>(req.threadId));
if (thread) {
if (thread->GetStack().has_all_frames()) {
callback(PopulateStackTraceResponse(ctx, thread, req));
} else {
thread->GetStack().SyncFrames(
{}, [ctx, weak_thread = thread->GetWeakPtr(), request = dap::StackTraceRequest(req),
callback](const Err& err) {
if (!err.has_error() && weak_thread) {
callback(PopulateStackTraceResponse(ctx, weak_thread.get(), request));
} else {
callback(dap::Error("Thread exited, no frames."));
}
});
}
} else {
callback(dap::Error("Thread not found."));
}
}
} // namespace zxdb