mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-26 22:21:50 +01:00
Implement log services (lm)
lm is used by applications to print messages to the system log. Log messages are made up of a header and then several fields containing metadata or string messages.
This commit is contained in:
parent
8985fe705f
commit
3a343d3a48
@ -108,6 +108,8 @@ add_library(skyline SHARED
|
||||
${source_DIR}/skyline/services/pl/IPlatformServiceManager.cpp
|
||||
${source_DIR}/skyline/services/aocsrv/IAddOnContentManager.cpp
|
||||
${source_DIR}/skyline/services/pctl/IParentalControlServiceFactory.cpp
|
||||
${source_DIR}/skyline/services/lm/ILogService.cpp
|
||||
${source_DIR}/skyline/services/lm/ILogger.cpp
|
||||
${source_DIR}/skyline/vfs/partition_filesystem.cpp
|
||||
${source_DIR}/skyline/vfs/rom_filesystem.cpp
|
||||
${source_DIR}/skyline/vfs/os_backing.cpp
|
||||
|
@ -65,6 +65,8 @@ namespace skyline::service {
|
||||
pl_IPlatformServiceManager,
|
||||
aocsrv_IAddOnContentManager,
|
||||
pctl_IParentalControlServiceFactory,
|
||||
lm_ILogService,
|
||||
lm_ILogger
|
||||
};
|
||||
|
||||
/**
|
||||
@ -94,7 +96,8 @@ namespace skyline::service {
|
||||
{"pctl", Service::pctl_IParentalControlServiceFactory},
|
||||
{"pctl:a", Service::pctl_IParentalControlServiceFactory},
|
||||
{"pctl:s", Service::pctl_IParentalControlServiceFactory},
|
||||
{"pctl:r", Service::pctl_IParentalControlServiceFactory}
|
||||
{"pctl:r", Service::pctl_IParentalControlServiceFactory},
|
||||
{"lm", Service::lm_ILogService}
|
||||
};
|
||||
|
||||
class ServiceManager;
|
||||
|
15
app/src/main/cpp/skyline/services/lm/ILogService.cpp
Normal file
15
app/src/main/cpp/skyline/services/lm/ILogService.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "ILogger.h"
|
||||
#include "ILogService.h"
|
||||
|
||||
namespace skyline::service::lm {
|
||||
ILogService::ILogService(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::lm_ILogService, "lm:ILogService", {
|
||||
{0x0, SFUNC(ILogService::OpenLogger)}
|
||||
}) {}
|
||||
|
||||
void ILogService::OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
manager.RegisterService(std::make_shared<ILogger>(state, manager), session, response);
|
||||
}
|
||||
}
|
22
app/src/main/cpp/skyline/services/lm/ILogService.h
Normal file
22
app/src/main/cpp/skyline/services/lm/ILogService.h
Normal file
@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/base_service.h>
|
||||
#include <services/serviceman.h>
|
||||
|
||||
namespace skyline::service::lm {
|
||||
/**
|
||||
* @brief ILogService is used by applications to open an ILogger for printing log messages (https://switchbrew.org/wiki/Log_services#lm)
|
||||
*/
|
||||
class ILogService : public BaseService {
|
||||
public:
|
||||
ILogService(const DeviceState &state, ServiceManager &manager);
|
||||
|
||||
/**
|
||||
* @brief This opens an ILogger that can be used by applications to print log messages (https://switchbrew.org/wiki/Log_services#OpenLogger)
|
||||
*/
|
||||
void OpenLogger(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
};
|
||||
}
|
102
app/src/main/cpp/skyline/services/lm/ILogger.cpp
Normal file
102
app/src/main/cpp/skyline/services/lm/ILogger.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include <kernel/types/KProcess.h>
|
||||
#include "ILogger.h"
|
||||
|
||||
namespace skyline::service::lm {
|
||||
ILogger::ILogger(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::lm_ILogger, "lm:ILogger", {
|
||||
{0x0, SFUNC(ILogger::Log)},
|
||||
{0x1, SFUNC(ILogger::SetDestination)}
|
||||
}) {}
|
||||
|
||||
std::string ILogger::GetFieldName(LogFieldType type) {
|
||||
switch (type) {
|
||||
case LogFieldType::Message:
|
||||
return "Message";
|
||||
case LogFieldType::Line:
|
||||
return "Line";
|
||||
case LogFieldType::Filename:
|
||||
return "Filename";
|
||||
case LogFieldType::Function:
|
||||
return "Function";
|
||||
case LogFieldType::Module:
|
||||
return "Module";
|
||||
case LogFieldType::Thread:
|
||||
return "Thread";
|
||||
case LogFieldType::DropCount:
|
||||
return "DropCount";
|
||||
case LogFieldType::Time:
|
||||
return "Time";
|
||||
case LogFieldType::ProgramName:
|
||||
return "ProgramName";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void ILogger::Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
struct Data {
|
||||
u64 pid;
|
||||
u64 threadContext;
|
||||
u16 flags;
|
||||
LogLevel level;
|
||||
u8 verbosity;
|
||||
u32 payloadLength;
|
||||
} data = state.process->GetReference<Data>(request.inputBuf.at(0).address);
|
||||
|
||||
std::ostringstream logMessage;
|
||||
logMessage << "Guest log: ";
|
||||
|
||||
u64 offset = sizeof(Data);
|
||||
while (offset < request.inputBuf.at(0).size) {
|
||||
auto fieldType = state.process->GetObject<LogFieldType>(request.inputBuf.at(0).address + offset++);
|
||||
auto length = state.process->GetObject<u8>(request.inputBuf.at(0).address + offset++);
|
||||
auto address = request.inputBuf.at(0).address + offset;
|
||||
|
||||
switch (fieldType) {
|
||||
case LogFieldType::Start:
|
||||
offset += length;
|
||||
continue;
|
||||
case LogFieldType::Line:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u32>(address);
|
||||
offset += sizeof(u32);
|
||||
continue;
|
||||
case LogFieldType::DropCount:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u64>(address);
|
||||
offset += sizeof(u64);
|
||||
continue;
|
||||
case LogFieldType::Time:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetObject<u64>(address) << "s";
|
||||
offset += sizeof(u64);
|
||||
continue;
|
||||
case LogFieldType::Stop:
|
||||
break;
|
||||
default:
|
||||
logMessage << GetFieldName(fieldType) << ": " << state.process->GetString(address, length);
|
||||
offset += length;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (data.level) {
|
||||
case LogLevel::Trace:
|
||||
state.logger->Debug("{}", logMessage.str());
|
||||
break;
|
||||
case LogLevel::Info:
|
||||
state.logger->Info("{}", logMessage.str());
|
||||
break;
|
||||
case LogLevel::Warning:
|
||||
state.logger->Warn("{}", logMessage.str());
|
||||
break;
|
||||
case LogLevel::Error:
|
||||
case LogLevel::Critical:
|
||||
state.logger->Error("{}", logMessage.str());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ILogger::SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
||||
}
|
63
app/src/main/cpp/skyline/services/lm/ILogger.h
Normal file
63
app/src/main/cpp/skyline/services/lm/ILogger.h
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <services/base_service.h>
|
||||
#include <services/serviceman.h>
|
||||
|
||||
namespace skyline::service::lm {
|
||||
/**
|
||||
* @brief ILogger is used by applications to print messages to the system log (https://switchbrew.org/wiki/Log_services#ILogger)
|
||||
*/
|
||||
class ILogger : public BaseService {
|
||||
private:
|
||||
/**
|
||||
* @brief This enumerates the field types in a log message
|
||||
*/
|
||||
enum class LogFieldType : u8 {
|
||||
Start = 0, //!< This is the first log message in the stream
|
||||
Stop = 1, //!< This is the final log message in the stream
|
||||
Message = 2, //!< This log field contains a general message
|
||||
Line = 3, //!< This log field contains a line number
|
||||
Filename = 4, //!< This log field contains a filename
|
||||
Function = 5, //!< This log field contains a function name
|
||||
Module = 6, //!< This log field contains a module name
|
||||
Thread = 7, //!< This log field contains a thread name
|
||||
DropCount = 8, //!< This log field contains the number of dropped messages
|
||||
Time = 9, //!< This log field contains a timestamp
|
||||
ProgramName = 10, //!< This log field contains the program's name
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This enumerates the log levels for log messages
|
||||
*/
|
||||
enum class LogLevel : u8 {
|
||||
Trace, //!< This is a trace log
|
||||
Info, //!< This is an info log
|
||||
Warning, //!< This is a warning log
|
||||
Error, //!< This is an error log
|
||||
Critical //!< This is a critical log
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Obtains a string containing the name of the given field type
|
||||
* @param type The field type to return the name of
|
||||
* @return The name of the given field type
|
||||
*/
|
||||
std::string GetFieldName(LogFieldType type);
|
||||
|
||||
public:
|
||||
ILogger(const DeviceState &state, ServiceManager &manager);
|
||||
|
||||
/**
|
||||
* @brief This prints a message to the log (https://switchbrew.org/wiki/Log_services#Log)
|
||||
*/
|
||||
void Log(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief This sets the log destination (https://switchbrew.org/wiki/Log_services#SetDestination)
|
||||
*/
|
||||
void SetDestination(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
};
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
#include "pl/IPlatformServiceManager.h"
|
||||
#include "aocsrv/IAddOnContentManager.h"
|
||||
#include "pctl/IParentalControlServiceFactory.h"
|
||||
#include "lm/ILogService.h"
|
||||
#include "serviceman.h"
|
||||
|
||||
namespace skyline::service {
|
||||
@ -82,6 +83,9 @@ namespace skyline::service {
|
||||
case Service::pctl_IParentalControlServiceFactory:
|
||||
serviceObj = std::make_shared<pctl::IParentalControlServiceFactory>(state, *this);
|
||||
break;
|
||||
case Service::lm_ILogService:
|
||||
serviceObj = std::make_shared<lm::ILogService>(state, *this);
|
||||
break;
|
||||
default:
|
||||
throw exception("CreateService called on missing object, type: {}", serviceType);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user