diff options
| author | 2018-02-13 09:44:53 +0300 | |
|---|---|---|
| committer | 2018-02-13 09:44:53 +0300 | |
| commit | 55de13efcce5a940d6b9999885b45d70f6719711 (patch) | |
| tree | b8f32584323b0c65182d780faafad4e2d2bb1e25 /src/core/hle/service/lm | |
| parent | Merge pull request #179 from gdkchan/audren_stubs (diff) | |
| download | yuzu-55de13efcce5a940d6b9999885b45d70f6719711.tar.gz yuzu-55de13efcce5a940d6b9999885b45d70f6719711.tar.xz yuzu-55de13efcce5a940d6b9999885b45d70f6719711.zip | |
Service/lm: add support to multiline logs
Diffstat (limited to 'src/core/hle/service/lm')
| -rw-r--r-- | src/core/hle/service/lm/lm.cpp | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index c480f6b97..b8e53d2c7 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <sstream> | ||
| 5 | #include <string> | 6 | #include <string> |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| @@ -28,19 +29,28 @@ private: | |||
| 28 | IsHead = 1, | 29 | IsHead = 1, |
| 29 | IsTail = 2, | 30 | IsTail = 2, |
| 30 | }; | 31 | }; |
| 32 | enum Severity : u32_le { | ||
| 33 | Trace, | ||
| 34 | Info, | ||
| 35 | Warning, | ||
| 36 | Error, | ||
| 37 | Critical, | ||
| 38 | }; | ||
| 31 | 39 | ||
| 32 | u64_le pid; | 40 | u64_le pid; |
| 33 | u64_le threadContext; | 41 | u64_le threadContext; |
| 34 | union { | 42 | union { |
| 35 | BitField<0, 16, Flags> flags; | 43 | BitField<0, 16, Flags> flags; |
| 36 | BitField<16, 8, u32_le> severity; | 44 | BitField<16, 8, Severity> severity; |
| 37 | BitField<24, 8, u32_le> verbosity; | 45 | BitField<24, 8, u32_le> verbosity; |
| 38 | }; | 46 | }; |
| 39 | u32_le payload_size; | 47 | u32_le payload_size; |
| 40 | 48 | ||
| 41 | /// Returns true if this is part of a single log message | 49 | bool IsHeadLog() const { |
| 42 | bool IsSingleMessage() const { | 50 | return flags & Flags::IsHead; |
| 43 | return (flags & Flags::IsHead) && (flags & Flags::IsTail); | 51 | } |
| 52 | bool IsTailLog() const { | ||
| 53 | return flags & Flags::IsTail; | ||
| 44 | } | 54 | } |
| 45 | }; | 55 | }; |
| 46 | static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size"); | 56 | static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size"); |
| @@ -57,7 +67,7 @@ private: | |||
| 57 | }; | 67 | }; |
| 58 | 68 | ||
| 59 | /** | 69 | /** |
| 60 | * LM::Initialize service function | 70 | * LM::Log service function |
| 61 | * Inputs: | 71 | * Inputs: |
| 62 | * 0: 0x00000000 | 72 | * 0: 0x00000000 |
| 63 | * Outputs: | 73 | * Outputs: |
| @@ -75,9 +85,9 @@ private: | |||
| 75 | Memory::ReadBlock(addr, &header, sizeof(MessageHeader)); | 85 | Memory::ReadBlock(addr, &header, sizeof(MessageHeader)); |
| 76 | addr += sizeof(MessageHeader); | 86 | addr += sizeof(MessageHeader); |
| 77 | 87 | ||
| 78 | if (!header.IsSingleMessage()) { | 88 | if (header.IsHeadLog()) { |
| 79 | LOG_WARNING(Service_LM, "Multi message logs are unimplemeneted"); | 89 | log_stream.str(""); |
| 80 | return; | 90 | log_stream.clear(); |
| 81 | } | 91 | } |
| 82 | 92 | ||
| 83 | // Parse out log metadata | 93 | // Parse out log metadata |
| @@ -85,7 +95,7 @@ private: | |||
| 85 | std::string message, filename, function; | 95 | std::string message, filename, function; |
| 86 | while (addr < end_addr) { | 96 | while (addr < end_addr) { |
| 87 | const Field field{static_cast<Field>(Memory::Read8(addr++))}; | 97 | const Field field{static_cast<Field>(Memory::Read8(addr++))}; |
| 88 | size_t length{Memory::Read8(addr++)}; | 98 | const size_t length{Memory::Read8(addr++)}; |
| 89 | 99 | ||
| 90 | if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { | 100 | if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { |
| 91 | ++addr; | 101 | ++addr; |
| @@ -110,28 +120,47 @@ private: | |||
| 110 | } | 120 | } |
| 111 | 121 | ||
| 112 | // Empty log - nothing to do here | 122 | // Empty log - nothing to do here |
| 113 | if (message.empty()) { | 123 | if (log_stream.str().empty() && message.empty()) { |
| 114 | return; | 124 | return; |
| 115 | } | 125 | } |
| 116 | 126 | ||
| 117 | // Format a nicely printable string out of the log metadata | 127 | // Format a nicely printable string out of the log metadata |
| 118 | std::string output; | 128 | if (!filename.empty()) { |
| 119 | if (filename.size()) { | 129 | log_stream << filename << ':'; |
| 120 | output += filename + ':'; | ||
| 121 | } | 130 | } |
| 122 | if (function.size()) { | 131 | if (!function.empty()) { |
| 123 | output += function + ':'; | 132 | log_stream << function << ':'; |
| 124 | } | 133 | } |
| 125 | if (line) { | 134 | if (line) { |
| 126 | output += std::to_string(line) + ':'; | 135 | log_stream << std::to_string(line) << ':'; |
| 127 | } | 136 | } |
| 128 | if (output.length() > 0 && output.back() == ':') { | 137 | if (log_stream.str().length() > 0 && log_stream.str().back() == ':') { |
| 129 | output += ' '; | 138 | log_stream << ' '; |
| 130 | } | 139 | } |
| 131 | output += message; | 140 | log_stream << message; |
| 132 | 141 | ||
| 133 | LOG_INFO(Debug_Emulated, "%s", output.c_str()); | 142 | if (header.IsTailLog()) { |
| 143 | switch (header.severity) { | ||
| 144 | case MessageHeader::Severity::Trace: | ||
| 145 | LOG_TRACE(Debug_Emulated, "%s", log_stream.str().c_str()); | ||
| 146 | break; | ||
| 147 | case MessageHeader::Severity::Info: | ||
| 148 | LOG_INFO(Debug_Emulated, "%s", log_stream.str().c_str()); | ||
| 149 | break; | ||
| 150 | case MessageHeader::Severity::Warning: | ||
| 151 | LOG_WARNING(Debug_Emulated, "%s", log_stream.str().c_str()); | ||
| 152 | break; | ||
| 153 | case MessageHeader::Severity::Error: | ||
| 154 | LOG_ERROR(Debug_Emulated, "%s", log_stream.str().c_str()); | ||
| 155 | break; | ||
| 156 | case MessageHeader::Severity::Critical: | ||
| 157 | LOG_CRITICAL(Debug_Emulated, "%s", log_stream.str().c_str()); | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | } | ||
| 134 | } | 161 | } |
| 162 | |||
| 163 | std::ostringstream log_stream; | ||
| 135 | }; | 164 | }; |
| 136 | 165 | ||
| 137 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 166 | void InstallInterfaces(SM::ServiceManager& service_manager) { |