committed by
GitHub
8 changed files with 288 additions and 345 deletions
-
2src/core/CMakeLists.txt
-
12src/core/core.cpp
-
7src/core/core.h
-
319src/core/hle/service/lm/lm.cpp
-
134src/core/hle/service/lm/manager.cpp
-
106src/core/hle/service/lm/manager.h
-
50src/core/reporter.cpp
-
3src/core/reporter.h
@ -1,134 +0,0 @@ |
|||||
// 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("{}", 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_MSG("Unimplemented field type={}", type); |
|
||||
return ""; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
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::Flush() { |
|
||||
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
|
|
||||
@ -1,106 +0,0 @@ |
|||||
// 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: |
|
||||
explicit Manager(Core::Reporter& reporter); |
|
||||
~Manager(); |
|
||||
|
|
||||
void SetEnabled(bool enabled); |
|
||||
void SetDestination(DestinationFlag destination); |
|
||||
|
|
||||
void Log(LogMessage message); |
|
||||
|
|
||||
void Flush(); |
|
||||
|
|
||||
private: |
|
||||
void InitializeLog(); |
|
||||
void FinalizeLog(); |
|
||||
|
|
||||
bool enabled = true; |
|
||||
DestinationFlag destination = DestinationFlag::All; |
|
||||
|
|
||||
std::vector<LogMessage> current_log; |
|
||||
|
|
||||
Core::Reporter& reporter; |
|
||||
}; |
|
||||
|
|
||||
} // namespace Service::LM |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue