blob: 4563a4b214627dd259c5cac7cc660c6f6ec587b3 [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 ExceptionUse::ExceptionDecoded(ExceptionDecoder* decoder) { decoder->Destroy(); }
void ExceptionUse::DecodingError(const DecoderError& error, ExceptionDecoder* decoder) {
FX_LOGS(ERROR) << error.message();
decoder->Destroy();
}
void ExceptionDecoder::Decode() {
zxdb::Thread* thread = get_thread();
if (thread == nullptr) {
Destroy();
return;
}
if (thread->GetStack().has_all_frames()) {
Display();
} else {
thread->GetStack().SyncFrames([this](const zxdb::Err& /*err*/) { Display(); });
}
}
void ExceptionDecoder::Display() {
zxdb::Thread* thread = get_thread();
if (thread == nullptr) {
Destroy();
return;
}
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;
}
}
}
use_->ExceptionDecoded(this);
}
void ExceptionDecoder::Destroy() {
InterceptionWorkflow* workflow = workflow_;
uint64_t process_id = process_id_;
uint64_t timestamp = timestamp_;
dispatcher_->DeleteDecoder(this);
workflow->ProcessDetached(process_id, timestamp);
}
void ExceptionDisplay::ExceptionDecoded(ExceptionDecoder* decoder) {
Thread* thread = dispatcher_->SearchThread(decoder->thread_id());
if (thread == nullptr) {
Process* process = dispatcher_->SearchProcess(decoder->process_id());
if (process == nullptr) {
zxdb::Thread* zxdb_thread = decoder->get_thread();
if (zxdb_thread == nullptr) {
decoder->Destroy();
return;
}
process = dispatcher_->CreateProcess(decoder->process_name(), decoder->process_id(),
zxdb_thread->GetProcess()->GetWeakPtr());
}
thread = dispatcher_->CreateThread(decoder->thread_id(), process);
}
auto event = std::make_shared<ExceptionEvent>(decoder->timestamp(), thread);
CopyStackFrame(decoder->caller_locations(), &event->stack_frame());
dispatcher_->AddExceptionEvent(std::move(event));
// Now our job is done, we can destroy the object.
decoder->Destroy();
}
void ExceptionDisplay::DecodingError(const DecoderError& error, ExceptionDecoder* decoder) {
std::string message = error.message();
size_t pos = 0;
for (;;) {
size_t end = message.find('\n', pos);
const fidl_codec::Colors& colors = dispatcher_->colors();
os_ << decoder->process_name() << ' ' << colors.red << decoder->process_id() << colors.reset
<< ':' << colors.red << decoder->thread_id() << colors.reset << ": " << colors.red
<< error.message().substr(pos, end) << colors.reset << '\n';
if (end == std::string::npos) {
break;
}
pos = end + 1;
}
os_ << '\n';
decoder->Destroy();
}
} // namespace fidlcat