summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Hilman <zachhilman@gmail.com>2019-06-29 23:18:07 +0200
committerZach Hilman <zachhilman@gmail.com>2019-09-22 18:34:55 +0200
commitef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e (patch)
tree86afb16448acf822ab4a1e2fe0c71c7a6866e41d
parentcore: Add LM::Manager to system (diff)
downloadyuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar.gz
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar.bz2
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar.lz
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar.xz
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.tar.zst
yuzu-ef9a7fa1f5e593bf6cd49aab2ee371b7ca84512e.zip
-rw-r--r--src/core/hle/service/lm/manager.cpp129
-rw-r--r--src/core/hle/service/lm/manager.h104
2 files changed, 233 insertions, 0 deletions
diff --git a/src/core/hle/service/lm/manager.cpp b/src/core/hle/service/lm/manager.cpp
new file mode 100644
index 000000000..fd8edaf46
--- /dev/null
+++ b/src/core/hle/service/lm/manager.cpp
@@ -0,0 +1,129 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "common/string_util.h"
+#include "core/hle/service/lm/manager.h"
+#include "core/reporter.h"
+
+namespace Service::LM {
+
+std::ostream& operator<<(std::ostream& os, DestinationFlag dest) {
+ std::vector<std::string> array;
+ const auto check_single_flag = [dest, &array](DestinationFlag check, std::string name) {
+ if ((static_cast<u32>(check) & static_cast<u32>(dest)) > 0) {
+ array.emplace_back(std::move(name));
+ }
+ };
+
+ check_single_flag(DestinationFlag::Default, "Default");
+ check_single_flag(DestinationFlag::UART, "UART");
+ check_single_flag(DestinationFlag::UARTSleeping, "UART (Sleeping)");
+
+ os << "[";
+ for (const auto& entry : array) {
+ os << entry << ", ";
+ }
+ return os << "]";
+}
+
+std::ostream& operator<<(std::ostream& os, MessageHeader::Severity severity) {
+ switch (severity) {
+ case MessageHeader::Severity::Trace:
+ return os << "Trace";
+ case MessageHeader::Severity::Info:
+ return os << "Info";
+ case MessageHeader::Severity::Warning:
+ return os << "Warning";
+ case MessageHeader::Severity::Error:
+ return os << "Error";
+ case MessageHeader::Severity::Critical:
+ return os << "Critical";
+ default:
+ return os << fmt::format("{:08X}", static_cast<u32>(severity));
+ }
+}
+
+std::ostream& operator<<(std::ostream& os, Field field) {
+ switch (field) {
+ case Field::Skip:
+ return os << "Skip";
+ case Field::Message:
+ return os << "Message";
+ case Field::Line:
+ return os << "Line";
+ case Field::Filename:
+ return os << "Filename";
+ case Field::Function:
+ return os << "Function";
+ case Field::Module:
+ return os << "Module";
+ case Field::Thread:
+ return os << "Thread";
+ default:
+ return os << fmt::format("{:08X}", static_cast<u32>(field));
+ }
+}
+
+std::string FormatField(Field type, const std::vector<u8>& data) {
+ switch (type) {
+ case Field::Skip:
+ return "";
+ case Field::Line:
+ if (data.size() >= sizeof(u32)) {
+ u32 line;
+ std::memcpy(&line, data.data(), sizeof(u32));
+ return fmt::format("{:08X}", line);
+ }
+ return "[ERROR DECODING LINE NUMBER]";
+ case Field::Message:
+ case Field::Filename:
+ case Field::Function:
+ case Field::Module:
+ case Field::Thread:
+ return Common::StringFromFixedZeroTerminatedBuffer(
+ reinterpret_cast<const char*>(data.data()), data.size());
+ default:
+ UNIMPLEMENTED();
+ }
+}
+
+Manager::Manager(Core::Reporter& reporter) : reporter(reporter) {}
+
+Manager::~Manager() = default;
+
+void Manager::SetEnabled(bool enabled) {
+ this->enabled = enabled;
+}
+
+void Manager::SetDestination(DestinationFlag destination) {
+ this->destination = destination;
+}
+
+void Manager::Log(LogMessage message) {
+ if (message.header.IsHeadLog()) {
+ InitializeLog();
+ }
+
+ current_log.emplace_back(std::move(message));
+
+ if (current_log.back().header.IsTailLog()) {
+ FinalizeLog();
+ }
+}
+
+void Manager::InitializeLog() {
+ current_log.clear();
+
+ LOG_INFO(Service_LM, "Initialized new log session!");
+}
+
+void Manager::FinalizeLog() {
+ reporter.SaveLogReport(static_cast<u32>(destination), std::move(current_log));
+
+ LOG_INFO(Service_LM, "Finalized current log session!");
+}
+
+} // namespace Service::LM
diff --git a/src/core/hle/service/lm/manager.h b/src/core/hle/service/lm/manager.h
new file mode 100644
index 000000000..af0a27257
--- /dev/null
+++ b/src/core/hle/service/lm/manager.h
@@ -0,0 +1,104 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <map>
+#include <ostream>
+#include <vector>
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+
+namespace Core {
+class Reporter;
+}
+
+namespace Service::LM {
+
+enum class DestinationFlag : u32 {
+ Default = 1,
+ UART = 2,
+ UARTSleeping = 4,
+
+ All = 0xFFFF,
+};
+
+struct MessageHeader {
+ enum Flags : u32_le {
+ IsHead = 1,
+ IsTail = 2,
+ };
+ enum Severity : u32_le {
+ Trace,
+ Info,
+ Warning,
+ Error,
+ Critical,
+ };
+
+ u64_le pid;
+ u64_le thread_context;
+ union {
+ BitField<0, 16, Flags> flags;
+ BitField<16, 8, Severity> severity;
+ BitField<24, 8, u32> verbosity;
+ };
+ u32_le payload_size;
+
+ bool IsHeadLog() const {
+ return flags & IsHead;
+ }
+ bool IsTailLog() const {
+ return flags & IsTail;
+ }
+};
+static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size");
+
+enum class Field : u8 {
+ Skip = 1,
+ Message = 2,
+ Line = 3,
+ Filename = 4,
+ Function = 5,
+ Module = 6,
+ Thread = 7,
+};
+
+std::ostream& operator<<(std::ostream& os, DestinationFlag dest);
+std::ostream& operator<<(std::ostream& os, MessageHeader::Severity severity);
+std::ostream& operator<<(std::ostream& os, Field field);
+
+using FieldMap = std::map<Field, std::vector<u8>>;
+
+struct LogMessage {
+ MessageHeader header;
+ FieldMap fields;
+};
+
+std::string FormatField(Field type, const std::vector<u8>& data);
+
+class Manager {
+public:
+ Manager(Core::Reporter& reporter);
+ ~Manager();
+
+ void SetEnabled(bool enabled);
+ void SetDestination(DestinationFlag destination);
+
+ void Log(LogMessage message);
+
+private:
+ void InitializeLog();
+ void FinalizeLog();
+
+ bool enabled = true;
+ DestinationFlag destination = DestinationFlag::All;
+
+ std::vector<LogMessage> current_log;
+
+ Core::Reporter& reporter;
+};
+
+} // namespace Service::LM