blob: e6960b32b7984c142304a7dfa878ee1d8133551a [file] [log] [blame]
// Copyright 2019 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 "tools/fidlcat/lib/exception_decoder.h"
#include <lib/syslog/cpp/macros.h>
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "tools/fidlcat/lib/interception_workflow.h"
namespace fidlcat {
void ExceptionDecoder::Decode() {
zxdb::Thread* thread = get_thread();
if (thread == nullptr) {
Destroy();
return;
}
if (thread->GetStack().has_all_frames()) {
Decoded();
} else {
thread->GetStack().SyncFrames([this](const zxdb::Err& /*err*/) { Decoded(); });
}
}
void ExceptionDecoder::Decoded() {
zxdb::Thread* thread = get_thread();
if (thread == nullptr) {
Destroy();
return;
}
std::vector<zxdb::Location> caller_locations;
const zxdb::Stack& stack = thread->GetStack();
if (stack.size() > 0) {
for (size_t i = stack.size() - 1;; --i) {
const zxdb::Frame* caller = stack[i];
caller_locations.push_back(caller->GetLocation());
if (i == 0) {
break;
}
}
}
Thread* fidlcat_thread = dispatcher_->SearchThread(thread_id());
if (fidlcat_thread == nullptr) {
Process* process = dispatcher_->SearchProcess(process_id());
if (process == nullptr) {
process = dispatcher_->CreateProcess(process_name(), process_id(),
thread->GetProcess()->GetWeakPtr());
}
fidlcat_thread = dispatcher_->CreateThread(thread_id(), process);
}
auto event = std::make_shared<ExceptionEvent>(timestamp(), fidlcat_thread);
CopyStackFrame(caller_locations, &event->stack_frame());
dispatcher_->AddExceptionEvent(std::move(event));
Destroy();
}
void ExceptionDecoder::Destroy() {
InterceptionWorkflow* workflow = workflow_;
uint64_t process_id = process_id_;
uint64_t timestamp = timestamp_;
dispatcher_->DeleteDecoder(this);
workflow->ProcessDetached(process_id, timestamp);
}
} // namespace fidlcat