mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	lm: Rename Initialize to Log and implement with manager/reporter
Allows saving and clearer output of data.
This commit is contained in:
		
							parent
							
								
									ef9a7fa1f5
								
							
						
					
					
						commit
						fa6531ab0f
					
				| @ -17,65 +17,16 @@ namespace Service::LM { | |||||||
| 
 | 
 | ||||||
| class ILogger final : public ServiceFramework<ILogger> { | class ILogger final : public ServiceFramework<ILogger> { | ||||||
| public: | public: | ||||||
|     ILogger() : ServiceFramework("ILogger") { |     ILogger(Manager& manager) : ServiceFramework("ILogger"), manager(manager) { | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0x00000000, &ILogger::Initialize, "Initialize"}, |             {0, &ILogger::Log, "Log"}, | ||||||
|             {0x00000001, &ILogger::SetDestination, "SetDestination"}, |             {1, &ILogger::SetDestination, "SetDestination"}, | ||||||
|         }; |         }; | ||||||
|         RegisterHandlers(functions); |         RegisterHandlers(functions); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     struct MessageHeader { |     void Log(Kernel::HLERequestContext& ctx) { | ||||||
|         enum Flags : u32_le { |  | ||||||
|             IsHead = 1, |  | ||||||
|             IsTail = 2, |  | ||||||
|         }; |  | ||||||
|         enum Severity : u32_le { |  | ||||||
|             Trace, |  | ||||||
|             Info, |  | ||||||
|             Warning, |  | ||||||
|             Error, |  | ||||||
|             Critical, |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         u64_le pid; |  | ||||||
|         u64_le threadContext; |  | ||||||
|         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 & Flags::IsHead; |  | ||||||
|         } |  | ||||||
|         bool IsTailLog() const { |  | ||||||
|             return flags & Flags::IsTail; |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size"); |  | ||||||
| 
 |  | ||||||
|     /// Log field type
 |  | ||||||
|     enum class Field : u8 { |  | ||||||
|         Skip = 1, |  | ||||||
|         Message = 2, |  | ||||||
|         Line = 3, |  | ||||||
|         Filename = 4, |  | ||||||
|         Function = 5, |  | ||||||
|         Module = 6, |  | ||||||
|         Thread = 7, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * ILogger::Initialize service function |  | ||||||
|      *  Inputs: |  | ||||||
|      *      0: 0x00000000 |  | ||||||
|      *  Outputs: |  | ||||||
|      *      0: ResultCode |  | ||||||
|      */ |  | ||||||
|     void Initialize(Kernel::HLERequestContext& ctx) { |  | ||||||
|         // This function only succeeds - Get that out of the way
 |         // This function only succeeds - Get that out of the way
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(RESULT_SUCCESS); |         rb.Push(RESULT_SUCCESS); | ||||||
| @ -87,111 +38,42 @@ private: | |||||||
|         Memory::ReadBlock(addr, &header, sizeof(MessageHeader)); |         Memory::ReadBlock(addr, &header, sizeof(MessageHeader)); | ||||||
|         addr += sizeof(MessageHeader); |         addr += sizeof(MessageHeader); | ||||||
| 
 | 
 | ||||||
|         if (header.IsHeadLog()) { |         FieldMap fields; | ||||||
|             log_stream.str(""); |  | ||||||
|             log_stream.clear(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Parse out log metadata
 |  | ||||||
|         u32 line{}; |  | ||||||
|         std::string module; |  | ||||||
|         std::string message; |  | ||||||
|         std::string filename; |  | ||||||
|         std::string function; |  | ||||||
|         std::string thread; |  | ||||||
|         while (addr < end_addr) { |         while (addr < end_addr) { | ||||||
|             const Field field{static_cast<Field>(Memory::Read8(addr++))}; |             const auto field = static_cast<Field>(Memory::Read8(addr++)); | ||||||
|             const std::size_t length{Memory::Read8(addr++)}; |             const auto length = Memory::Read8(addr++); | ||||||
| 
 | 
 | ||||||
|             if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { |             if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) { | ||||||
|                 ++addr; |                 ++addr; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             switch (field) { |             SCOPE_EXIT({ addr += length; }); | ||||||
|             case Field::Skip: | 
 | ||||||
|                 break; |             if (field == Field::Skip) { | ||||||
|             case Field::Message: |                 continue; | ||||||
|                 message = Memory::ReadCString(addr, length); |  | ||||||
|                 break; |  | ||||||
|             case Field::Line: |  | ||||||
|                 line = Memory::Read32(addr); |  | ||||||
|                 break; |  | ||||||
|             case Field::Filename: |  | ||||||
|                 filename = Memory::ReadCString(addr, length); |  | ||||||
|                 break; |  | ||||||
|             case Field::Function: |  | ||||||
|                 function = Memory::ReadCString(addr, length); |  | ||||||
|                 break; |  | ||||||
|             case Field::Module: |  | ||||||
|                 module = Memory::ReadCString(addr, length); |  | ||||||
|                 break; |  | ||||||
|             case Field::Thread: |  | ||||||
|                 thread = Memory::ReadCString(addr, length); |  | ||||||
|                 break; |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             addr += length; |             std::vector<u8> data(length); | ||||||
|  |             Memory::ReadBlock(addr, data.data(), length); | ||||||
|  |             fields.emplace(field, std::move(data)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Empty log - nothing to do here
 |         manager.Log({header, std::move(fields)}); | ||||||
|         if (log_stream.str().empty() && message.empty()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Format a nicely printable string out of the log metadata
 |  | ||||||
|         if (!filename.empty()) { |  | ||||||
|             log_stream << filename << ':'; |  | ||||||
|         } |  | ||||||
|         if (!module.empty()) { |  | ||||||
|             log_stream << module << ':'; |  | ||||||
|         } |  | ||||||
|         if (!function.empty()) { |  | ||||||
|             log_stream << function << ':'; |  | ||||||
|         } |  | ||||||
|         if (line) { |  | ||||||
|             log_stream << std::to_string(line) << ':'; |  | ||||||
|         } |  | ||||||
|         if (!thread.empty()) { |  | ||||||
|             log_stream << thread << ':'; |  | ||||||
|         } |  | ||||||
|         if (log_stream.str().length() > 0 && log_stream.str().back() == ':') { |  | ||||||
|             log_stream << ' '; |  | ||||||
|         } |  | ||||||
|         log_stream << message; |  | ||||||
| 
 |  | ||||||
|         if (header.IsTailLog()) { |  | ||||||
|             switch (header.severity) { |  | ||||||
|             case MessageHeader::Severity::Trace: |  | ||||||
|                 LOG_DEBUG(Debug_Emulated, "{}", log_stream.str()); |  | ||||||
|                 break; |  | ||||||
|             case MessageHeader::Severity::Info: |  | ||||||
|                 LOG_INFO(Debug_Emulated, "{}", log_stream.str()); |  | ||||||
|                 break; |  | ||||||
|             case MessageHeader::Severity::Warning: |  | ||||||
|                 LOG_WARNING(Debug_Emulated, "{}", log_stream.str()); |  | ||||||
|                 break; |  | ||||||
|             case MessageHeader::Severity::Error: |  | ||||||
|                 LOG_ERROR(Debug_Emulated, "{}", log_stream.str()); |  | ||||||
|                 break; |  | ||||||
|             case MessageHeader::Severity::Critical: |  | ||||||
|                 LOG_CRITICAL(Debug_Emulated, "{}", log_stream.str()); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // This service function is intended to be used as a way to
 |  | ||||||
|     // redirect logging output to different destinations, however,
 |  | ||||||
|     // given we always want to see the logging output, it's sufficient
 |  | ||||||
|     // to do nothing and return success here.
 |  | ||||||
|     void SetDestination(Kernel::HLERequestContext& ctx) { |     void SetDestination(Kernel::HLERequestContext& ctx) { | ||||||
|         LOG_DEBUG(Service_LM, "called"); |         IPC::RequestParser rp{ctx}; | ||||||
|  |         const auto destination = rp.PopEnum<DestinationFlag>(); | ||||||
|  | 
 | ||||||
|  |         LOG_DEBUG(Service_LM, "called, destination={:08X}", static_cast<u32>(destination)); | ||||||
|  | 
 | ||||||
|  |         manager.SetDestination(destination); | ||||||
| 
 | 
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(RESULT_SUCCESS); |         rb.Push(RESULT_SUCCESS); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::ostringstream log_stream; |     Manager& manager; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class LM final : public ServiceFramework<LM> { | class LM final : public ServiceFramework<LM> { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Zach Hilman
						Zach Hilman