Extend SVC table with names

This extend a descriptor table for the SVCs with names for every SVC alongside their function pointer. The names are then used for logging and eventually tracing.
This commit is contained in:
PixelyIon 2021-03-20 14:55:48 +05:30 committed by ◱ Mark
parent 6eea38cca9
commit df3427a8c0
3 changed files with 163 additions and 140 deletions

View File

@ -229,136 +229,157 @@ namespace skyline::kernel::svc {
void SignalToAddress(const DeviceState &state); void SignalToAddress(const DeviceState &state);
/** /**
* @brief The SVC Table maps all SVCs to their corresponding functions * @brief A per-SVC descriptor with it's name and a function pointer
* @note The descriptor is nullable, the validity of the descriptor can be checked with the boolean operator
*/ */
static std::array<void (*)(const DeviceState &), 0x80> SvcTable{ struct SvcDescriptor {
nullptr, // 0x00 (Does not exist) void (*function)(const DeviceState &); //!< A function pointer to a HLE implementation of the SVC
SetHeapSize, // 0x01 const char* name; //!< A pointer to a static string of the SVC name, the underlying data should not be mutated
nullptr, // 0x02
SetMemoryAttribute, // 0x03 operator bool() {
MapMemory, // 0x04 return function;
UnmapMemory, // 0x05 }
QueryMemory, // 0x06 };
ExitProcess, // 0x07
CreateThread, // 0x08 #define SVC_NONE SvcDescriptor{} //!< A macro with a placeholder value for the SVC not being implemented or not existing
StartThread, // 0x09 #define SVC_STRINGIFY(name) #name
ExitThread, // 0x0A #define SVC_ENTRY(function) SvcDescriptor{function, SVC_STRINGIFY(Svc ## function)} //!< A macro which automatically stringifies the function name as the name to prevent pointless duplication
SleepThread, // 0x0B
GetThreadPriority, // 0x0C /**
SetThreadPriority, // 0x0D * @brief The SVC table maps all SVCs to their corresponding functions
GetThreadCoreMask, // 0x0E */
SetThreadCoreMask, // 0x0F static constexpr std::array<SvcDescriptor, 0x80> SvcTable{
GetCurrentProcessorNumber, // 0x10 SVC_NONE, // 0x00 (Does not exist)
nullptr, // 0x11 SVC_ENTRY(SetHeapSize), // 0x01
ClearEvent, // 0x12 SVC_NONE, // 0x02
MapSharedMemory, // 0x13 SVC_ENTRY(SetMemoryAttribute), // 0x03
nullptr, // 0x14 SVC_ENTRY(MapMemory), // 0x04
CreateTransferMemory, // 0x15 SVC_ENTRY(UnmapMemory), // 0x05
CloseHandle, // 0x16 SVC_ENTRY(QueryMemory), // 0x06
ResetSignal, // 0x17 SVC_ENTRY(ExitProcess), // 0x07
WaitSynchronization, // 0x18 SVC_ENTRY(CreateThread), // 0x08
CancelSynchronization, // 0x19 SVC_ENTRY(StartThread), // 0x09
ArbitrateLock, // 0x1A SVC_ENTRY(ExitThread), // 0x0A
ArbitrateUnlock, // 0x1B SVC_ENTRY(SleepThread), // 0x0B
WaitProcessWideKeyAtomic, // 0x1C SVC_ENTRY(GetThreadPriority), // 0x0C
SignalProcessWideKey, // 0x1D SVC_ENTRY(SetThreadPriority), // 0x0D
GetSystemTick, // 0x1E SVC_ENTRY(GetThreadCoreMask), // 0x0E
ConnectToNamedPort, // 0x1F SVC_ENTRY(SetThreadCoreMask), // 0x0F
nullptr, // 0x20 SVC_ENTRY(GetCurrentProcessorNumber), // 0x10
SendSyncRequest, // 0x21 SVC_NONE, // 0x11
nullptr, // 0x22 SVC_ENTRY(ClearEvent), // 0x12
nullptr, // 0x23 SVC_ENTRY(MapSharedMemory), // 0x13
nullptr, // 0x24 SVC_NONE, // 0x14
GetThreadId, // 0x25 SVC_ENTRY(CreateTransferMemory), // 0x15
Break, // 0x26 SVC_ENTRY(CloseHandle), // 0x16
OutputDebugString, // 0x27 SVC_ENTRY(ResetSignal), // 0x17
nullptr, // 0x28 SVC_ENTRY(WaitSynchronization), // 0x18
GetInfo, // 0x29 SVC_ENTRY(CancelSynchronization), // 0x19
nullptr, // 0x2A SVC_ENTRY(ArbitrateLock), // 0x1A
nullptr, // 0x2B SVC_ENTRY(ArbitrateUnlock), // 0x1B
MapPhysicalMemory, // 0x2C SVC_ENTRY(WaitProcessWideKeyAtomic), // 0x1C
UnmapPhysicalMemory, // 0x2D SVC_ENTRY(SignalProcessWideKey), // 0x1D
nullptr, // 0x2E SVC_ENTRY(GetSystemTick), // 0x1E
nullptr, // 0x2F SVC_ENTRY(ConnectToNamedPort), // 0x1F
nullptr, // 0x30 SVC_NONE, // 0x20
nullptr, // 0x31 SVC_ENTRY(SendSyncRequest), // 0x21
nullptr, // 0x32 SVC_NONE, // 0x22
nullptr, // 0x33 SVC_NONE, // 0x23
WaitForAddress, // 0x34 SVC_NONE, // 0x24
SignalToAddress, // 0x35 SVC_ENTRY(GetThreadId), // 0x25
nullptr, // 0x36 SVC_ENTRY(Break), // 0x26
nullptr, // 0x37 SVC_ENTRY(OutputDebugString), // 0x27
nullptr, // 0x38 SVC_NONE, // 0x28
nullptr, // 0x39 SVC_ENTRY(GetInfo), // 0x29
nullptr, // 0x3A SVC_NONE, // 0x2A
nullptr, // 0x3B SVC_NONE, // 0x2B
nullptr, // 0x3C SVC_ENTRY(MapPhysicalMemory), // 0x2C
nullptr, // 0x3D SVC_ENTRY(UnmapPhysicalMemory), // 0x2D
nullptr, // 0x3E SVC_NONE, // 0x2E
nullptr, // 0x3F SVC_NONE, // 0x2F
nullptr, // 0x40 SVC_NONE, // 0x30
nullptr, // 0x41 SVC_NONE, // 0x31
nullptr, // 0x42 SVC_NONE, // 0x32
nullptr, // 0x43 SVC_NONE, // 0x33
nullptr, // 0x44 SVC_ENTRY(WaitForAddress), // 0x34
nullptr, // 0x45 SVC_ENTRY(SignalToAddress), // 0x35
nullptr, // 0x46 SVC_NONE, // 0x36
nullptr, // 0x47 SVC_NONE, // 0x37
nullptr, // 0x48 SVC_NONE, // 0x38
nullptr, // 0x49 SVC_NONE, // 0x39
nullptr, // 0x4A SVC_NONE, // 0x3A
nullptr, // 0x4B SVC_NONE, // 0x3B
nullptr, // 0x4C SVC_NONE, // 0x3C
nullptr, // 0x4D SVC_NONE, // 0x3D
nullptr, // 0x4E SVC_NONE, // 0x3E
nullptr, // 0x4F SVC_NONE, // 0x3F
nullptr, // 0x50 SVC_NONE, // 0x40
nullptr, // 0x51 SVC_NONE, // 0x41
nullptr, // 0x52 SVC_NONE, // 0x42
nullptr, // 0x53 SVC_NONE, // 0x43
nullptr, // 0x54 SVC_NONE, // 0x44
nullptr, // 0x55 SVC_NONE, // 0x45
nullptr, // 0x56 SVC_NONE, // 0x46
nullptr, // 0x57 SVC_NONE, // 0x47
nullptr, // 0x58 SVC_NONE, // 0x48
nullptr, // 0x59 SVC_NONE, // 0x49
nullptr, // 0x5A SVC_NONE, // 0x4A
nullptr, // 0x5B SVC_NONE, // 0x4B
nullptr, // 0x5C SVC_NONE, // 0x4C
nullptr, // 0x5D SVC_NONE, // 0x4D
nullptr, // 0x5E SVC_NONE, // 0x4E
nullptr, // 0x5F SVC_NONE, // 0x4F
nullptr, // 0x60 SVC_NONE, // 0x50
nullptr, // 0x61 SVC_NONE, // 0x51
nullptr, // 0x62 SVC_NONE, // 0x52
nullptr, // 0x63 SVC_NONE, // 0x53
nullptr, // 0x64 SVC_NONE, // 0x54
nullptr, // 0x65 SVC_NONE, // 0x55
nullptr, // 0x66 SVC_NONE, // 0x56
nullptr, // 0x67 SVC_NONE, // 0x57
nullptr, // 0x68 SVC_NONE, // 0x58
nullptr, // 0x69 SVC_NONE, // 0x59
nullptr, // 0x6A SVC_NONE, // 0x5A
nullptr, // 0x6B SVC_NONE, // 0x5B
nullptr, // 0x6C SVC_NONE, // 0x5C
nullptr, // 0x6D SVC_NONE, // 0x5D
nullptr, // 0x6E SVC_NONE, // 0x5E
nullptr, // 0x6F SVC_NONE, // 0x5F
nullptr, // 0x70 SVC_NONE, // 0x60
nullptr, // 0x71 SVC_NONE, // 0x61
nullptr, // 0x72 SVC_NONE, // 0x62
nullptr, // 0x73 SVC_NONE, // 0x63
nullptr, // 0x74 SVC_NONE, // 0x64
nullptr, // 0x75 SVC_NONE, // 0x65
nullptr, // 0x76 SVC_NONE, // 0x66
nullptr, // 0x77 SVC_NONE, // 0x67
nullptr, // 0x78 SVC_NONE, // 0x68
nullptr, // 0x79 SVC_NONE, // 0x69
nullptr, // 0x7A SVC_NONE, // 0x6A
nullptr, // 0x7B SVC_NONE, // 0x6B
nullptr, // 0x7C SVC_NONE, // 0x6C
nullptr, // 0x7D SVC_NONE, // 0x6D
nullptr, // 0x7E SVC_NONE, // 0x6E
nullptr // 0x7F SVC_NONE, // 0x6F
}; SVC_NONE, // 0x70
SVC_NONE, // 0x71
SVC_NONE, // 0x72
SVC_NONE, // 0x73
SVC_NONE, // 0x74
SVC_NONE, // 0x75
SVC_NONE, // 0x76
SVC_NONE, // 0x77
SVC_NONE, // 0x78
SVC_NONE, // 0x79
SVC_NONE, // 0x7A
SVC_NONE, // 0x7B
SVC_NONE, // 0x7C
SVC_NONE, // 0x7D
SVC_NONE, // 0x7E
SVC_NONE // 0x7F
};
#undef SVC_NONE
#undef SVC_STRINGIFY
#undef SVC_ENTRY
} }

View File

@ -14,18 +14,16 @@
#include "nce.h" #include "nce.h"
namespace skyline::nce { namespace skyline::nce {
void NCE::SvcHandler(u16 svc, ThreadContext *ctx) { void NCE::SvcHandler(u16 svcId, ThreadContext *ctx) {
TRACE_EVENT_END("guest"); TRACE_EVENT_END("guest");
const auto &state{*ctx->state}; const auto &state{*ctx->state};
auto svc{kernel::svc::SvcTable[svcId]};
try { try {
auto function{kernel::svc::SvcTable[svc]}; if (svc) [[likely]] {
if (function) [[likely]] { (svc.function)(state);
TRACE_EVENT("kernel", "SVC");
state.logger->Debug("SVC called 0x{:X}", svc);
(*function)(state);
} else [[unlikely]] { } else [[unlikely]] {
throw exception("Unimplemented SVC 0x{:X}", svc); throw exception("Unimplemented SVC 0x{:X}", svcId);
} }
while (kernel::Scheduler::YieldPending) [[unlikely]] { while (kernel::Scheduler::YieldPending) [[unlikely]] {
@ -35,7 +33,7 @@ namespace skyline::nce {
} }
} catch (const signal::SignalException &e) { } catch (const signal::SignalException &e) {
if (e.signal != SIGINT) { if (e.signal != SIGINT) {
state.logger->Error("{} (SVC: 0x{:X})\nStack Trace:{}", e.what(), svc, state.loader->GetStackTrace(e.frames)); state.logger->ErrorNoPrefix("{} (SVC: 0x{:X})\nStack Trace:{}", e.what(), svc.name, state.loader->GetStackTrace(e.frames));
if (state.thread->id) { if (state.thread->id) {
signal::BlockSignal({SIGINT}); signal::BlockSignal({SIGINT});
state.process->Kill(false); state.process->Kill(false);
@ -44,7 +42,11 @@ namespace skyline::nce {
abi::__cxa_end_catch(); // We call this prior to the longjmp to cause the exception object to be destroyed abi::__cxa_end_catch(); // We call this prior to the longjmp to cause the exception object to be destroyed
std::longjmp(state.thread->originalCtx, true); std::longjmp(state.thread->originalCtx, true);
} catch (const std::exception &e) { } catch (const std::exception &e) {
state.logger->Error("{} (SVC: 0x{:X})\nStack Trace:{}", e.what(), svc, state.loader->GetStackTrace()); if (svc)
state.logger->ErrorNoPrefix("{} (SVC: {})\nStack Trace:{}", e.what(), svc.name, state.loader->GetStackTrace());
else
state.logger->ErrorNoPrefix("{} (SVC: 0x{:X})\nStack Trace:{}", e.what(), svcId, state.loader->GetStackTrace());
if (state.thread->id) { if (state.thread->id) {
signal::BlockSignal({SIGINT}); signal::BlockSignal({SIGINT});
state.process->Kill(false); state.process->Kill(false);

View File

@ -14,7 +14,7 @@ namespace skyline::nce {
private: private:
const DeviceState &state; const DeviceState &state;
static void SvcHandler(u16 svc, ThreadContext *ctx); static void SvcHandler(u16 svcId, ThreadContext *ctx);
public: public:
static void SignalHandler(int signal, siginfo *info, ucontext *ctx, void **tls); static void SignalHandler(int signal, siginfo *info, ucontext *ctx, void **tls);