mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 09:24:16 +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/pl/IPlatformServiceManager.cpp
|
||||||
${source_DIR}/skyline/services/aocsrv/IAddOnContentManager.cpp
|
${source_DIR}/skyline/services/aocsrv/IAddOnContentManager.cpp
|
||||||
${source_DIR}/skyline/services/pctl/IParentalControlServiceFactory.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/partition_filesystem.cpp
|
||||||
${source_DIR}/skyline/vfs/rom_filesystem.cpp
|
${source_DIR}/skyline/vfs/rom_filesystem.cpp
|
||||||
${source_DIR}/skyline/vfs/os_backing.cpp
|
${source_DIR}/skyline/vfs/os_backing.cpp
|
||||||
|
@ -65,6 +65,8 @@ namespace skyline::service {
|
|||||||
pl_IPlatformServiceManager,
|
pl_IPlatformServiceManager,
|
||||||
aocsrv_IAddOnContentManager,
|
aocsrv_IAddOnContentManager,
|
||||||
pctl_IParentalControlServiceFactory,
|
pctl_IParentalControlServiceFactory,
|
||||||
|
lm_ILogService,
|
||||||
|
lm_ILogger
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +96,8 @@ namespace skyline::service {
|
|||||||
{"pctl", Service::pctl_IParentalControlServiceFactory},
|
{"pctl", Service::pctl_IParentalControlServiceFactory},
|
||||||
{"pctl:a", Service::pctl_IParentalControlServiceFactory},
|
{"pctl:a", Service::pctl_IParentalControlServiceFactory},
|
||||||
{"pctl:s", Service::pctl_IParentalControlServiceFactory},
|
{"pctl:s", Service::pctl_IParentalControlServiceFactory},
|
||||||
{"pctl:r", Service::pctl_IParentalControlServiceFactory}
|
{"pctl:r", Service::pctl_IParentalControlServiceFactory},
|
||||||
|
{"lm", Service::lm_ILogService}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServiceManager;
|
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 "pl/IPlatformServiceManager.h"
|
||||||
#include "aocsrv/IAddOnContentManager.h"
|
#include "aocsrv/IAddOnContentManager.h"
|
||||||
#include "pctl/IParentalControlServiceFactory.h"
|
#include "pctl/IParentalControlServiceFactory.h"
|
||||||
|
#include "lm/ILogService.h"
|
||||||
#include "serviceman.h"
|
#include "serviceman.h"
|
||||||
|
|
||||||
namespace skyline::service {
|
namespace skyline::service {
|
||||||
@ -82,6 +83,9 @@ namespace skyline::service {
|
|||||||
case Service::pctl_IParentalControlServiceFactory:
|
case Service::pctl_IParentalControlServiceFactory:
|
||||||
serviceObj = std::make_shared<pctl::IParentalControlServiceFactory>(state, *this);
|
serviceObj = std::make_shared<pctl::IParentalControlServiceFactory>(state, *this);
|
||||||
break;
|
break;
|
||||||
|
case Service::lm_ILogService:
|
||||||
|
serviceObj = std::make_shared<lm::ILogService>(state, *this);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw exception("CreateService called on missing object, type: {}", serviceType);
|
throw exception("CreateService called on missing object, type: {}", serviceType);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user