mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Absolute bare minimum to get this to build.
Codebase still needs to be updated to properly use log levels, but at least it's building on all of them.
This commit is contained in:
parent
5f59d0f444
commit
9cb2a0440e
10 changed files with 189 additions and 93 deletions
|
@ -38,7 +38,7 @@ extern "C" {
|
||||||
/// Defines the log level used throughout the application.
|
/// Defines the log level used throughout the application.
|
||||||
/// Log messages with a log value lower than this one won't be compiled into the binary.
|
/// Log messages with a log value lower than this one won't be compiled into the binary.
|
||||||
/// If a value lower than LOG_LEVEL_DEBUG or equal to/greater than LOG_LEVEL_NONE is used, logfile output will be entirely disabled.
|
/// If a value lower than LOG_LEVEL_DEBUG or equal to/greater than LOG_LEVEL_NONE is used, logfile output will be entirely disabled.
|
||||||
#define LOG_LEVEL LOG_LEVEL_DEBUG /* TODO: change before release. */
|
#define LOG_LEVEL LOG_LEVEL_DEBUG /* TODO: change before release (warning?). */
|
||||||
|
|
||||||
#if (LOG_LEVEL >= LOG_LEVEL_DEBUG) && (LOG_LEVEL < LOG_LEVEL_NONE)
|
#if (LOG_LEVEL >= LOG_LEVEL_DEBUG) && (LOG_LEVEL < LOG_LEVEL_NONE)
|
||||||
|
|
||||||
|
@ -48,16 +48,26 @@ extern "C" {
|
||||||
#define LOG_MSG_BUF_GENERIC(dst, dst_size, level, fmt, ...) logWriteFormattedStringToBuffer(dst, dst_size, level, __FILENAME__, __LINE__, __func__, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF_GENERIC(dst, dst_size, level, fmt, ...) logWriteFormattedStringToBuffer(dst, dst_size, level, __FILENAME__, __LINE__, __func__, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_DATA_GENERIC(data, data_size, level, fmt, ...) logWriteBinaryDataToLogFile(data, data_size, level, __FILENAME__, __LINE__, __func__, fmt, ##__VA_ARGS__)
|
#define LOG_DATA_GENERIC(data, data_size, level, fmt, ...) logWriteBinaryDataToLogFile(data, data_size, level, __FILENAME__, __LINE__, __func__, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: delete these macros after migrating all log calls to the new verbosity-level-based system. */
|
||||||
|
#define LOG_MSG(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_MSG_BUF(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_DATA(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if LOG_LEVEL == LOG_LEVEL_DEBUG
|
||||||
#define LOG_MSG_DEBUG(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_DEBUG(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_MSG_BUF_DEBUG(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF_DEBUG(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_DATA_DEBUG(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
#define LOG_DATA_DEBUG(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOG_MSG_DEBUG(fmt, ...) do {} while(0)
|
||||||
|
#define LOG_MSG_BUF_DEBUG(dst, dst_size, fmt, ...) do {} while(0)
|
||||||
|
#define LOG_DATA_DEBUG(data, data_size, fmt, ...) do {} while(0)
|
||||||
|
#endif /* LOG_LEVEL == LOG_LEVEL_DEBUG */
|
||||||
|
|
||||||
/* TODO: delete these macros after migrating all log calls to the new verbosity-level-based system. */
|
#if LOG_LEVEL <= LOG_LEVEL_INFO
|
||||||
#define LOG_MSG(fmt, ...) LOG_MSG_DEBUG(fmt, ##__VA_ARGS__)
|
|
||||||
#define LOG_MSG_BUF(dst, dst_size, fmt, ...) LOG_MSG_BUF_DEBUG(dst, dst_size, fmt, ##__VA_ARGS__)
|
|
||||||
#define LOG_DATA(data, data_size, fmt, ...) LOG_DATA_DEBUG(data, data_size, fmt, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#if LOG_LEVEL >= LOG_LEVEL_INFO
|
|
||||||
#define LOG_MSG_INFO(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_INFO(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_MSG_BUF_INFO(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF_INFO(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_DATA_INFO(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
#define LOG_DATA_INFO(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
|
||||||
|
@ -65,9 +75,9 @@ extern "C" {
|
||||||
#define LOG_MSG_INFO(fmt, ...) do {} while(0)
|
#define LOG_MSG_INFO(fmt, ...) do {} while(0)
|
||||||
#define LOG_MSG_BUF_INFO(dst, dst_size, fmt, ...) do {} while(0)
|
#define LOG_MSG_BUF_INFO(dst, dst_size, fmt, ...) do {} while(0)
|
||||||
#define LOG_DATA_INFO(data, data_size, fmt, ...) do {} while(0)
|
#define LOG_DATA_INFO(data, data_size, fmt, ...) do {} while(0)
|
||||||
#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */
|
#endif /* LOG_LEVEL <= LOG_LEVEL_INFO */
|
||||||
|
|
||||||
#if LOG_LEVEL >= LOG_LEVEL_WARNING
|
#if LOG_LEVEL <= LOG_LEVEL_WARNING
|
||||||
#define LOG_MSG_WARNING(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_WARNING(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_MSG_BUF_WARNING(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF_WARNING(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_DATA_WARNING(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
#define LOG_DATA_WARNING(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
|
||||||
|
@ -75,9 +85,9 @@ extern "C" {
|
||||||
#define LOG_MSG_WARNING(fmt, ...) do {} while(0)
|
#define LOG_MSG_WARNING(fmt, ...) do {} while(0)
|
||||||
#define LOG_MSG_BUF_WARNING(dst, dst_size, fmt, ...) do {} while(0)
|
#define LOG_MSG_BUF_WARNING(dst, dst_size, fmt, ...) do {} while(0)
|
||||||
#define LOG_DATA_WARNING(data, data_size, fmt, ...) do {} while(0)
|
#define LOG_DATA_WARNING(data, data_size, fmt, ...) do {} while(0)
|
||||||
#endif /* LOG_LEVEL >= LOG_LEVEL_WARNING */
|
#endif /* LOG_LEVEL <= LOG_LEVEL_WARNING */
|
||||||
|
|
||||||
#if LOG_LEVEL >= LOG_LEVEL_ERROR
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
#define LOG_MSG_ERROR(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_ERROR(fmt, ...) LOG_MSG_GENERIC(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_MSG_BUF_ERROR(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
#define LOG_MSG_BUF_ERROR(dst, dst_size, fmt, ...) LOG_MSG_BUF_GENERIC(dst, dst_size, LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
||||||
#define LOG_DATA_ERROR(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
#define LOG_DATA_ERROR(data, data_size, fmt, ...) LOG_DATA_GENERIC(data, data_size, LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
||||||
|
@ -85,7 +95,7 @@ extern "C" {
|
||||||
#define LOG_MSG_ERROR(fmt, ...) do {} while(0)
|
#define LOG_MSG_ERROR(fmt, ...) do {} while(0)
|
||||||
#define LOG_MSG_BUF_ERROR(dst, dst_size, fmt, ...) do {} while(0)
|
#define LOG_MSG_BUF_ERROR(dst, dst_size, fmt, ...) do {} while(0)
|
||||||
#define LOG_DATA_ERROR(data, data_size, fmt, ...) do {} while(0)
|
#define LOG_DATA_ERROR(data, data_size, fmt, ...) do {} while(0)
|
||||||
#endif /* LOG_LEVEL >= LOG_LEVEL_ERROR */
|
#endif /* LOG_LEVEL <= LOG_LEVEL_ERROR */
|
||||||
|
|
||||||
/// Writes the provided string to the logfile.
|
/// Writes the provided string to the logfile.
|
||||||
/// If the logfile hasn't been created and/or opened, this function takes care of it.
|
/// If the logfile hasn't been created and/or opened, this function takes care of it.
|
||||||
|
@ -120,7 +130,15 @@ void logControlMutex(bool lock);
|
||||||
|
|
||||||
/// Helper macros.
|
/// Helper macros.
|
||||||
|
|
||||||
#define LOG_STR(src) do {} while(0)
|
|
||||||
|
|
||||||
|
/* TODO: delete these macros after migrating all log calls to the new verbosity-level-based system. */
|
||||||
|
#define LOG_MSG(fmt, ...) do {} while(0)
|
||||||
|
#define LOG_MSG_BUF(dst, dst_size, fmt, ...) do {} while(0)
|
||||||
|
#define LOG_DATA(data, data_size, fmt, ...) do {} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define LOG_MSG_GENERIC(level, fmt, ...) do {} while(0)
|
#define LOG_MSG_GENERIC(level, fmt, ...) do {} while(0)
|
||||||
#define LOG_MSG_BUF_GENERIC(dst, dst_size, level, fmt, ...) do {} while(0)
|
#define LOG_MSG_BUF_GENERIC(dst, dst_size, level, fmt, ...) do {} while(0)
|
||||||
#define LOG_DATA_GENERIC(data, data_size, level, fmt, ...) do {} while(0)
|
#define LOG_DATA_GENERIC(data, data_size, level, fmt, ...) do {} while(0)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e46cb5a5eecf1caca5fee42502bd13ff54b0ae1f
|
Subproject commit df32a7cc42f06e0de259a8f0807e3d1690ef31f3
|
|
@ -63,16 +63,20 @@ typedef struct {
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
static const char *g_bktrStorageTypeNames[] = {
|
static const char *g_bktrStorageTypeNames[] = {
|
||||||
[BucketTreeStorageType_Indirect] = "Indirect",
|
[BucketTreeStorageType_Indirect] = "Indirect",
|
||||||
[BucketTreeStorageType_AesCtrEx] = "AesCtrEx",
|
[BucketTreeStorageType_AesCtrEx] = "AesCtrEx",
|
||||||
[BucketTreeStorageType_Compressed] = "Compressed",
|
[BucketTreeStorageType_Compressed] = "Compressed",
|
||||||
[BucketTreeStorageType_Sparse] = "Sparse"
|
[BucketTreeStorageType_Sparse] = "Sparse"
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
static const char *bktrGetStorageTypeName(u8 storage_type);
|
static const char *bktrGetStorageTypeName(u8 storage_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse);
|
static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse);
|
||||||
static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 read_size, u64 offset);
|
static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 read_size, u64 offset);
|
||||||
|
@ -161,7 +165,7 @@ bool bktrInitializeContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) LOG_MSG("Failed to initialize Bucket Tree %s storage for FS section #%u in \"%s\".", bktrGetStorageTypeName(storage_type), nca_fs_ctx->section_idx, \
|
if (!success) LOG_MSG_ERROR("Failed to initialize Bucket Tree %s storage for FS section #%u in \"%s\".", bktrGetStorageTypeName(storage_type), nca_fs_ctx->section_idx, \
|
||||||
nca_ctx->content_id_str);
|
nca_ctx->content_id_str);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -311,7 +315,7 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse
|
||||||
/* Find storage entry. */
|
/* Find storage entry. */
|
||||||
if (!bktrFindStorageEntry(ctx, offset, &visitor))
|
if (!bktrFindStorageEntry(ctx, offset, &visitor))
|
||||||
{
|
{
|
||||||
LOG_MSG("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
LOG_MSG_ERROR("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +336,7 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) LOG_MSG("Failed to read 0x%lX-byte long block at offset 0x%lX from %s storage!", read_size, offset, bktrGetStorageTypeName(ctx->storage_type));
|
if (!success) LOG_MSG_ERROR("Failed to read 0x%lX-byte long block at offset 0x%lX from %s storage!", read_size, offset, bktrGetStorageTypeName(ctx->storage_type));
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return success;
|
return success;
|
||||||
|
@ -353,7 +357,7 @@ bool bktrIsBlockWithinIndirectStorageRange(BucketTreeContext *ctx, u64 offset, u
|
||||||
/* Find storage entry. */
|
/* Find storage entry. */
|
||||||
if (!bktrFindStorageEntry(ctx, offset, &visitor))
|
if (!bktrFindStorageEntry(ctx, offset, &visitor))
|
||||||
{
|
{
|
||||||
LOG_MSG("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
LOG_MSG_ERROR("Unable to find %s storage entry for offset 0x%lX!", bktrGetStorageTypeName(ctx->storage_type), offset);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,10 +494,12 @@ end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
static const char *bktrGetStorageTypeName(u8 storage_type)
|
static const char *bktrGetStorageTypeName(u8 storage_type)
|
||||||
{
|
{
|
||||||
return (storage_type < BucketTreeStorageType_Count ? g_bktrStorageTypeNames[storage_type] : NULL);
|
return (storage_type < BucketTreeStorageType_Count ? g_bktrStorageTypeNames[storage_type] : NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse)
|
static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,14 +23,18 @@
|
||||||
#include "nxdt_utils.h"
|
#include "nxdt_utils.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
||||||
#define MEMLOG(fmt, ...) LOG_MSG_BUF(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
|
#define MEMLOG_DEBUG(fmt, ...) LOG_MSG_BUF_DEBUG(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
|
||||||
|
#define MEMLOG_ERROR(fmt, ...) LOG_MSG_BUF_ERROR(&g_memLogBuf, &g_memLogBufSize, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
static Mutex g_memMutex = 0;
|
static Mutex g_memMutex = 0;
|
||||||
|
static u64 g_fsTextSegmentAddr = 0;
|
||||||
|
|
||||||
|
#if LOG_LEVEL < LOG_LEVEL_NONE
|
||||||
static char *g_memLogBuf = NULL;
|
static char *g_memLogBuf = NULL;
|
||||||
static size_t g_memLogBufSize = 0;
|
static size_t g_memLogBufSize = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
|
|
||||||
|
@ -41,7 +45,7 @@ bool memRetrieveProgramMemorySegment(MemoryLocation *location)
|
||||||
{
|
{
|
||||||
if (!location || !location->program_id || !location->mask || location->mask >= BIT(3))
|
if (!location || !location->program_id || !location->mask || location->mask >= BIT(3))
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +58,7 @@ bool memRetrieveFullProgramMemory(MemoryLocation *location)
|
||||||
{
|
{
|
||||||
if (!location || !location->program_id)
|
if (!location || !location->program_id)
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,49 +95,72 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
|
||||||
/* Clear output MemoryLocation element. */
|
/* Clear output MemoryLocation element. */
|
||||||
memFreeMemoryLocation(location);
|
memFreeMemoryLocation(location);
|
||||||
|
|
||||||
/* LOG_MSG() will be useless if the target program is the FS sysmodule. */
|
#if LOG_LEVEL < LOG_LEVEL_NONE
|
||||||
|
/* LOG_*() macros will be useless if the target program is the FS sysmodule. */
|
||||||
/* This is because any FS I/O operation *will* lock up the console while FS itself is being debugged. */
|
/* This is because any FS I/O operation *will* lock up the console while FS itself is being debugged. */
|
||||||
/* So we'll just temporarily log data to a char array using LOG_MSG_BUF(), then write it all out after calling svcCloseHandle(). */
|
/* So we'll just temporarily log data to a char array using LOG_MSG_BUF_*() macros, then write it all out after calling svcCloseHandle(). */
|
||||||
/* However, we must prevent other threads from logging data as well in order to avoid a lock up, so we'll temporarily lock the logfile mutex. */
|
/* However, we must prevent other threads from logging data as well in order to avoid a lock up, so we'll temporarily lock the logfile mutex. */
|
||||||
logControlMutex(true);
|
logControlMutex(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Retrieve debug handle by program ID. */
|
/* Retrieve debug handle by program ID. */
|
||||||
if (!memRetrieveDebugHandleFromProgramById(&debug_handle, location->program_id))
|
if (!memRetrieveDebugHandleFromProgramById(&debug_handle, location->program_id))
|
||||||
{
|
{
|
||||||
MEMLOG("Unable to retrieve debug handle for program %016lX!", location->program_id);
|
MEMLOG_ERROR("Unable to retrieve debug handle for program %016lX!", location->program_id);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_segment && location->program_id == FS_SYSMODULE_TID)
|
if (is_segment && location->program_id == FS_SYSMODULE_TID)
|
||||||
{
|
{
|
||||||
/* If dealing with FS, locate the "real" .text segment, since Atmosphère emuMMC has two. */
|
/* Only look for the FS .text segment address if we haven't previously retrieved it. */
|
||||||
|
if (!g_fsTextSegmentAddr)
|
||||||
|
{
|
||||||
|
/* Locate the "real" FS .text segment, since Atmosphère emuMMC has two. */
|
||||||
do {
|
do {
|
||||||
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
|
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("svcQueryDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc);
|
MEMLOG_ERROR("svcQueryDebugProcessMemory failed for program %016lX! (0x%X).", location->program_id, rc);
|
||||||
success = false;
|
success = false;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOG_LEVEL == LOG_LEVEL_DEBUG
|
||||||
|
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (#1) (program %016lX, page 0x%X, debug handle 0x%X, address 0x%lX):\r\n" \
|
||||||
|
"- addr: 0x%lX\r\n- size: 0x%lX\r\n- type: 0x%X\r\n- attr: 0x%X\r\n- perm: 0x%X\r\n- ipc_refcount: 0x%X\r\n- device_refcount: 0x%X", \
|
||||||
|
location->program_id, page_info, debug_handle, addr, \
|
||||||
|
mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, mem_info.ipc_refcount, mem_info.device_refcount);
|
||||||
|
#endif
|
||||||
|
|
||||||
mem_type = (u8)(mem_info.type & 0xFF);
|
mem_type = (u8)(mem_info.type & 0xFF);
|
||||||
if ((mem_info.perm & Perm_X) && (mem_type == MemType_CodeStatic || mem_type == MemType_CodeMutable)) last_text_addr = mem_info.addr;
|
if ((mem_info.perm & Perm_X) && (mem_type == MemType_CodeStatic || mem_type == MemType_CodeMutable)) last_text_addr = mem_info.addr;
|
||||||
|
|
||||||
addr = (mem_info.addr + mem_info.size);
|
addr = (mem_info.addr + mem_info.size);
|
||||||
} while(addr != 0);
|
} while(addr != 0);
|
||||||
|
|
||||||
addr = last_text_addr;
|
g_fsTextSegmentAddr = last_text_addr;
|
||||||
|
MEMLOG_DEBUG("FS .text segment address: 0x%lX.", g_fsTextSegmentAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = g_fsTextSegmentAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
|
rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("svcQueryDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc);
|
MEMLOG_ERROR("svcQueryDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc);
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOG_LEVEL == LOG_LEVEL_DEBUG
|
||||||
|
MEMLOG_DEBUG("svcQueryDebugProcessMemory info (#2) (program %016lX, page 0x%X, debug handle 0x%X, address 0x%lX):\r\n" \
|
||||||
|
"- addr: 0x%lX\r\n- size: 0x%lX\r\n- type: 0x%X\r\n- attr: 0x%X\r\n- perm: 0x%X\r\n- ipc_refcount: 0x%X\r\n- device_refcount: 0x%X", \
|
||||||
|
location->program_id, page_info, debug_handle, addr, \
|
||||||
|
mem_info.addr, mem_info.size, mem_info.type, mem_info.attr, mem_info.perm, mem_info.ipc_refcount, mem_info.device_refcount);
|
||||||
|
#endif
|
||||||
|
|
||||||
mem_type = (u8)(mem_info.type & 0xFF);
|
mem_type = (u8)(mem_info.type & 0xFF);
|
||||||
|
|
||||||
/* Code to allow for bitmasking segments. */
|
/* Code to allow for bitmasking segments. */
|
||||||
|
@ -145,7 +172,7 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
|
||||||
tmp = realloc(location->data, location->data_size + mem_info.size);
|
tmp = realloc(location->data, location->data_size + mem_info.size);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
{
|
{
|
||||||
MEMLOG("Failed to resize segment data buffer to 0x%lX bytes for program %016lX!", location->data_size + mem_info.size, location->program_id);
|
MEMLOG_ERROR("Failed to resize segment data buffer to 0x%lX bytes for program %016lX!", location->data_size + mem_info.size, location->program_id);
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +183,7 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment)
|
||||||
rc = svcReadDebugProcessMemory(location->data + location->data_size, debug_handle, mem_info.addr, mem_info.size);
|
rc = svcReadDebugProcessMemory(location->data + location->data_size, debug_handle, mem_info.addr, mem_info.size);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("svcReadDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc);
|
MEMLOG_ERROR("svcReadDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc);
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -171,17 +198,20 @@ end:
|
||||||
/* Close debug handle. */
|
/* Close debug handle. */
|
||||||
if (debug_handle != INVALID_HANDLE) svcCloseHandle(debug_handle);
|
if (debug_handle != INVALID_HANDLE) svcCloseHandle(debug_handle);
|
||||||
|
|
||||||
|
#if LOG_LEVEL < LOG_LEVEL_NONE
|
||||||
/* Unlock logfile mutex. */
|
/* Unlock logfile mutex. */
|
||||||
logControlMutex(false);
|
logControlMutex(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (success && (!location->data || !location->data_size))
|
if (success && (!location->data || !location->data_size))
|
||||||
{
|
{
|
||||||
MEMLOG("Unable to locate readable program memory pages for %016lX that match the required criteria!", location->program_id);
|
MEMLOG_ERROR("Unable to locate readable program memory pages for %016lX that match the required criteria!", location->program_id);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) memFreeMemoryLocation(location);
|
if (!success) memFreeMemoryLocation(location);
|
||||||
|
|
||||||
|
#if LOG_LEVEL < LOG_LEVEL_NONE
|
||||||
/* Write log buffer data. This will do nothing if the log buffer length is zero. */
|
/* Write log buffer data. This will do nothing if the log buffer length is zero. */
|
||||||
logWriteStringToLogFile(g_memLogBuf);
|
logWriteStringToLogFile(g_memLogBuf);
|
||||||
|
|
||||||
|
@ -193,6 +223,7 @@ end:
|
||||||
}
|
}
|
||||||
|
|
||||||
g_memLogBufSize = 0;
|
g_memLogBufSize = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +232,7 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
|
||||||
{
|
{
|
||||||
if (!out || !program_id)
|
if (!out || !program_id)
|
||||||
{
|
{
|
||||||
MEMLOG("Invalid parameters!");
|
MEMLOG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,19 +245,21 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
|
||||||
|
|
||||||
if (program_id > BOOT_SYSMODULE_TID && program_id != SPL_SYSMODULE_TID)
|
if (program_id > BOOT_SYSMODULE_TID && program_id != SPL_SYSMODULE_TID)
|
||||||
{
|
{
|
||||||
/* If not a kernel process, get PID from pm:dmnt. */
|
/* If not a kernel process, get process ID from pm:dmnt. */
|
||||||
rc = pmdmntGetProcessId(&pid, program_id);
|
rc = pmdmntGetProcessId(&pid, program_id);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("pmdmntGetProcessId failed for program %016lX! (0x%08X).", program_id, rc);
|
MEMLOG_ERROR("pmdmntGetProcessId failed for program %016lX! (0x%08X).", program_id, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEMLOG_DEBUG("Process ID (%016lX): 0x%lX.", program_id, pid);
|
||||||
|
|
||||||
/* Retrieve debug handle right away. */
|
/* Retrieve debug handle right away. */
|
||||||
rc = svcDebugActiveProcess(&debug_handle, pid);
|
rc = svcDebugActiveProcess(&debug_handle, pid);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("svcDebugActiveProcess failed for program %016lX! (0x%08X).", program_id, rc);
|
MEMLOG_ERROR("svcDebugActiveProcess failed for program %016lX! (0x%08X).", program_id, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -234,14 +267,16 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
|
||||||
pids = calloc(300, sizeof(u64));
|
pids = calloc(300, sizeof(u64));
|
||||||
if (!pids)
|
if (!pids)
|
||||||
{
|
{
|
||||||
MEMLOG("Failed to allocate memory for PID list!");
|
MEMLOG_ERROR("Failed to allocate memory for PID list!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEMLOG_DEBUG("svcDebugActiveProcess returned %u process IDs.", num_processes);
|
||||||
|
|
||||||
rc = svcGetProcessList((s32*)&num_processes, pids, 300);
|
rc = svcGetProcessList((s32*)&num_processes, pids, 300);
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
MEMLOG("svcGetProcessList failed! (0x%08X).", rc);
|
MEMLOG_ERROR("svcGetProcessList failed! (0x%08X).", rc);
|
||||||
free(pids);
|
free(pids);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -249,14 +284,26 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
|
||||||
/* Perform a lookup using the retrieved process list. */
|
/* Perform a lookup using the retrieved process list. */
|
||||||
for(i = 0; i < num_processes; i++)
|
for(i = 0; i < num_processes; i++)
|
||||||
{
|
{
|
||||||
/* Retrieve debug handle for the current PID. */
|
/* Retrieve debug handle for the current process ID. */
|
||||||
rc = svcDebugActiveProcess(&debug_handle, pids[i]);
|
rc = svcDebugActiveProcess(&debug_handle, pids[i]);
|
||||||
if (R_FAILED(rc)) continue;
|
if (R_FAILED(rc))
|
||||||
|
{
|
||||||
|
MEMLOG_DEBUG("svcDebugActiveProcess failed for process ID 0x%lX! (0x%X).", pids[i], rc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMLOG_DEBUG("Debug handle (process 0x%lX): 0x%X.", pids[i], debug_handle);
|
||||||
|
|
||||||
/* Get debug event using the debug handle. */
|
/* Get debug event using the debug handle. */
|
||||||
/* This will let us know the program ID from the current PID. */
|
/* This will let us know the program ID from the current process ID. */
|
||||||
rc = svcGetDebugEvent((u8*)&d, debug_handle);
|
rc = svcGetDebugEvent((u8*)&d, debug_handle);
|
||||||
if (R_SUCCEEDED(rc) && d[2] == program_id) break;
|
if (R_SUCCEEDED(rc))
|
||||||
|
{
|
||||||
|
/* Jackpot. */
|
||||||
|
if (d[2] == program_id) break;
|
||||||
|
} else {
|
||||||
|
MEMLOG_DEBUG("svcGetDebugEvent failed for debug handle 0x%X! (0x%X).", debug_handle, rc);
|
||||||
|
}
|
||||||
|
|
||||||
/* No match. Close debug handle and keep looking for our program. */
|
/* No match. Close debug handle and keep looking for our program. */
|
||||||
svcCloseHandle(debug_handle);
|
svcCloseHandle(debug_handle);
|
||||||
|
@ -267,11 +314,13 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id)
|
||||||
|
|
||||||
if (i == num_processes)
|
if (i == num_processes)
|
||||||
{
|
{
|
||||||
MEMLOG("Unable to find program %016lX in kernel process list! (0x%08X).", program_id, rc);
|
MEMLOG_ERROR("Unable to find program %016lX in kernel process list! (0x%08X).", program_id, rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEMLOG_DEBUG("Debug handle (%016lX): 0x%X.", program_id, debug_handle);
|
||||||
|
|
||||||
/* Set output debug handle. */
|
/* Set output debug handle. */
|
||||||
*out = debug_handle;
|
*out = debug_handle;
|
||||||
|
|
||||||
|
|
|
@ -1005,7 +1005,10 @@ end:
|
||||||
|
|
||||||
static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
{
|
{
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_WARNING
|
||||||
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool success = false, valid = true;
|
bool success = false, valid = true;
|
||||||
u64 accum = 0;
|
u64 accum = 0;
|
||||||
|
|
||||||
|
@ -1021,7 +1024,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
NcaHierarchicalSha256Data *hash_data = &(ctx->header.hash_data.hierarchical_sha256_data);
|
NcaHierarchicalSha256Data *hash_data = &(ctx->header.hash_data.hierarchical_sha256_data);
|
||||||
if (!hash_data->hash_block_size || !hash_data->hash_region_count || hash_data->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT)
|
if (!hash_data->hash_block_size || !hash_data->hash_region_count || hash_data->hash_region_count > NCA_HIERARCHICAL_SHA256_MAX_REGION_COUNT)
|
||||||
{
|
{
|
||||||
LOG_DATA(hash_data, sizeof(NcaHierarchicalSha256Data), "Invalid HierarchicalSha256 data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
LOG_DATA_WARNING(hash_data, sizeof(NcaHierarchicalSha256Data), "Invalid HierarchicalSha256 data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
||||||
ctx->section_idx, nca_ctx->content_id_str);
|
ctx->section_idx, nca_ctx->content_id_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1033,7 +1036,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
if (hash_region->offset < accum || !hash_region->size || \
|
if (hash_region->offset < accum || !hash_region->size || \
|
||||||
((i < (hash_data->hash_region_count - 1) || !ctx->has_sparse_layer) && (hash_region->offset + hash_region->size) > ctx->section_size))
|
((i < (hash_data->hash_region_count - 1) || !ctx->has_sparse_layer) && (hash_region->offset + hash_region->size) > ctx->section_size))
|
||||||
{
|
{
|
||||||
LOG_MSG("HierarchicalSha256 region #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
LOG_MSG_WARNING("HierarchicalSha256 region #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
||||||
i, ctx->section_idx, nca_ctx->content_id_str);
|
i, ctx->section_idx, nca_ctx->content_id_str);
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1053,7 +1056,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
if (__builtin_bswap32(hash_data->magic) != NCA_IVFC_MAGIC || hash_data->master_hash_size != SHA256_HASH_SIZE || \
|
if (__builtin_bswap32(hash_data->magic) != NCA_IVFC_MAGIC || hash_data->master_hash_size != SHA256_HASH_SIZE || \
|
||||||
hash_data->info_level_hash.max_level_count != NCA_IVFC_MAX_LEVEL_COUNT)
|
hash_data->info_level_hash.max_level_count != NCA_IVFC_MAX_LEVEL_COUNT)
|
||||||
{
|
{
|
||||||
LOG_DATA(hash_data, sizeof(NcaIntegrityMetaInfo), "Invalid HierarchicalIntegrity data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
LOG_DATA_WARNING(hash_data, sizeof(NcaIntegrityMetaInfo), "Invalid HierarchicalIntegrity data for FS section #%u in \"%s\". Skipping FS section. Hash data dump:", \
|
||||||
ctx->section_idx, nca_ctx->content_id_str);
|
ctx->section_idx, nca_ctx->content_id_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1068,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
if (lvl_info->offset < accum || !lvl_info->size || !lvl_info->block_order || ((i < (NCA_IVFC_LEVEL_COUNT - 1) || \
|
if (lvl_info->offset < accum || !lvl_info->size || !lvl_info->block_order || ((i < (NCA_IVFC_LEVEL_COUNT - 1) || \
|
||||||
(!ctx->has_sparse_layer && ctx->section_type != NcaFsSectionType_PatchRomFs)) && (lvl_info->offset + lvl_info->size) > ctx->section_size))
|
(!ctx->has_sparse_layer && ctx->section_type != NcaFsSectionType_PatchRomFs)) && (lvl_info->offset + lvl_info->size) > ctx->section_size))
|
||||||
{
|
{
|
||||||
LOG_MSG("HierarchicalIntegrity level #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
LOG_MSG_WARNING("HierarchicalIntegrity level #%u for FS section #%u in \"%s\" is out of NCA boundaries. Skipping FS section.", \
|
||||||
i, ctx->section_idx, nca_ctx->content_id_str);
|
i, ctx->section_idx, nca_ctx->content_id_str);
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1079,7 +1082,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_MSG("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", ctx->section_idx, nca_ctx->content_id_str, ctx->hash_type);
|
LOG_MSG_WARNING("Invalid hash type for FS section #%u in \"%s\" (0x%02X). Skipping FS section.", ctx->section_idx, nca_ctx->content_id_str, ctx->hash_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ __attribute__((format(printf, 5, 6))) void logWriteFormattedStringToLogFile(u8 l
|
||||||
|
|
||||||
__attribute__((format(printf, 7, 8))) void logWriteFormattedStringToBuffer(char **dst, size_t *dst_size, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, ...)
|
__attribute__((format(printf, 7, 8))) void logWriteFormattedStringToBuffer(char **dst, size_t *dst_size, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
if (!dst || !dst_size || (!*dst && *dst_size) || (*dst && !*dst_size) || level > LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
|
if (!dst || !dst_size || (!*dst && *dst_size) || (*dst && !*dst_size) || level < LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ end:
|
||||||
|
|
||||||
__attribute__((format(printf, 7, 8))) void logWriteBinaryDataToLogFile(const void *data, size_t data_size, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, ...)
|
__attribute__((format(printf, 7, 8))) void logWriteBinaryDataToLogFile(const void *data, size_t data_size, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
if (!data || !data_size || level > LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
|
if (!data || !data_size || level < LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt) return;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
size_t data_str_size = ((data_size * 2) + 3);
|
size_t data_str_size = ((data_size * 2) + 3);
|
||||||
|
@ -279,7 +279,7 @@ static void _logWriteStringToLogFile(const char *src)
|
||||||
static void _logWriteFormattedStringToLogFile(bool save, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, va_list args)
|
static void _logWriteFormattedStringToLogFile(bool save, u8 level, const char *file_name, int line, const char *func_name, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
/* Make sure we have allocated memory for the log buffer and opened the logfile. */
|
/* Make sure we have allocated memory for the log buffer and opened the logfile. */
|
||||||
if (level > LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt || !logAllocateLogBuffer() || !logOpenLogFile()) return;
|
if (level < LOG_LEVEL || !file_name || !*file_name || !func_name || !*func_name || !fmt || !*fmt || !logAllocateLogBuffer() || !logOpenLogFile()) return;
|
||||||
|
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
|
|
||||||
|
|
|
@ -139,24 +139,26 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
|
||||||
/* If so, initialize nxlink connection without redirecting stdout and/or stderr. */
|
/* If so, initialize nxlink connection without redirecting stdout and/or stderr. */
|
||||||
if (__nxlink_host.s_addr != 0 && __nxlink_host.s_addr != INADDR_NONE) g_nxLinkSocketFd = nxlinkConnectToHost(false, false);
|
if (__nxlink_host.s_addr != 0 && __nxlink_host.s_addr != INADDR_NONE) g_nxLinkSocketFd = nxlinkConnectToHost(false, false);
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_INFO
|
||||||
/* Log info messages. */
|
/* Log info messages. */
|
||||||
u32 hos_version = hosversionGet();
|
u32 hos_version = hosversionGet();
|
||||||
LOG_MSG(APP_TITLE " v" APP_VERSION " starting (" GIT_REV "). Built on " BUILD_TIMESTAMP ".");
|
LOG_MSG_INFO(APP_TITLE " v" APP_VERSION " starting (" GIT_REV "). Built on " BUILD_TIMESTAMP ".");
|
||||||
if (g_nxLinkSocketFd >= 0) LOG_MSG("nxlink enabled! Host IP address: %s.", inet_ntoa(__nxlink_host));
|
if (g_nxLinkSocketFd >= 0) LOG_MSG_INFO("nxlink enabled! Host IP address: %s.", inet_ntoa(__nxlink_host));
|
||||||
LOG_MSG("Horizon OS version: %u.%u.%u.", HOSVER_MAJOR(hos_version), HOSVER_MINOR(hos_version), HOSVER_MICRO(hos_version));
|
LOG_MSG_INFO("Horizon OS version: %u.%u.%u.", HOSVER_MAJOR(hos_version), HOSVER_MINOR(hos_version), HOSVER_MICRO(hos_version));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Retrieve custom firmware type. */
|
/* Retrieve custom firmware type. */
|
||||||
_utilsGetCustomFirmwareType();
|
_utilsGetCustomFirmwareType();
|
||||||
if (g_customFirmwareType != UtilsCustomFirmwareType_Unknown) LOG_MSG("Detected %s CFW.", (g_customFirmwareType == UtilsCustomFirmwareType_Atmosphere ? "Atmosphère" : \
|
if (g_customFirmwareType != UtilsCustomFirmwareType_Unknown) LOG_MSG_INFO("Detected %s CFW.", (g_customFirmwareType == UtilsCustomFirmwareType_Atmosphere ? "Atmosphère" : \
|
||||||
(g_customFirmwareType == UtilsCustomFirmwareType_SXOS ? "SX OS" : "ReiNX")));
|
(g_customFirmwareType == UtilsCustomFirmwareType_SXOS ? "SX OS" : "ReiNX")));
|
||||||
|
|
||||||
/* Check if we're not running under a development unit. */
|
/* Check if we're not running under a development unit. */
|
||||||
if (!_utilsIsDevelopmentUnit()) break;
|
if (!_utilsIsDevelopmentUnit()) break;
|
||||||
LOG_MSG("Running under %s unit.", g_isDevUnit ? "development" : "retail");
|
LOG_MSG_INFO("Running under %s unit.", g_isDevUnit ? "development" : "retail");
|
||||||
|
|
||||||
/* Get applet type. */
|
/* Get applet type. */
|
||||||
g_programAppletType = appletGetAppletType();
|
g_programAppletType = appletGetAppletType();
|
||||||
LOG_MSG("Running under %s mode.", _utilsAppletModeCheck() ? "applet" : "title override");
|
LOG_MSG_INFO("Running under %s mode.", _utilsAppletModeCheck() ? "applet" : "title override");
|
||||||
|
|
||||||
/* Create output directories (SD card only). */
|
/* Create output directories (SD card only). */
|
||||||
/* TODO: remove the APP_TITLE check whenever we're ready for a release. */
|
/* TODO: remove the APP_TITLE check whenever we're ready for a release. */
|
||||||
|
@ -164,7 +166,7 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
|
||||||
|
|
||||||
if (g_appLaunchPath)
|
if (g_appLaunchPath)
|
||||||
{
|
{
|
||||||
LOG_MSG("Launch path: \"%s\".", g_appLaunchPath);
|
LOG_MSG_INFO("Launch path: \"%s\".", g_appLaunchPath);
|
||||||
|
|
||||||
/* Move NRO if the launch path isn't the right one, then return. */
|
/* Move NRO if the launch path isn't the right one, then return. */
|
||||||
/* TODO: uncomment this block whenever we are ready for a release. */
|
/* TODO: uncomment this block whenever we are ready for a release. */
|
||||||
|
@ -173,7 +175,7 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
|
||||||
remove(NRO_PATH);
|
remove(NRO_PATH);
|
||||||
rename(g_appLaunchPath, NRO_PATH);
|
rename(g_appLaunchPath, NRO_PATH);
|
||||||
|
|
||||||
LOG_MSG("Moved NRO to \"%s\". Please reload the application.", NRO_PATH);
|
LOG_MSG_INFO("Moved NRO to \"%s\". Please reload the application.", NRO_PATH);
|
||||||
break;
|
break;
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
@ -245,15 +247,18 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
|
char *msg = NULL;
|
||||||
size_t msg_size = 0;
|
size_t msg_size = 0;
|
||||||
char log_msg[0x100] = {0}, *msg = NULL;
|
|
||||||
|
|
||||||
/* Get last log message. */
|
|
||||||
logGetLastMessage(log_msg, sizeof(log_msg));
|
|
||||||
|
|
||||||
/* Generate error message. */
|
/* Generate error message. */
|
||||||
utilsAppendFormattedStringToBuffer(&msg, &msg_size, "An error occurred while initializing resources.");
|
utilsAppendFormattedStringToBuffer(&msg, &msg_size, "An error occurred while initializing resources.");
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
|
/* Get last log message. */
|
||||||
|
char log_msg[0x100] = {0};
|
||||||
|
logGetLastMessage(log_msg, sizeof(log_msg));
|
||||||
if (*log_msg) utilsAppendFormattedStringToBuffer(&msg, &msg_size, "\n\n%s", log_msg);
|
if (*log_msg) utilsAppendFormattedStringToBuffer(&msg, &msg_size, "\n\n%s", log_msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Print error message. */
|
/* Print error message. */
|
||||||
utilsPrintConsoleError(msg);
|
utilsPrintConsoleError(msg);
|
||||||
|
@ -326,8 +331,10 @@ void utilsCloseResources(void)
|
||||||
rename(NRO_TMP_PATH, NRO_PATH);
|
rename(NRO_TMP_PATH, NRO_PATH);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
/* Close logfile. */
|
/* Close logfile. */
|
||||||
logCloseLogFile();
|
logCloseLogFile();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Unlock applet exit. */
|
/* Unlock applet exit. */
|
||||||
appletUnlockExit();
|
appletUnlockExit();
|
||||||
|
|
|
@ -72,10 +72,12 @@ NXDT_ASSERT(TikEsCtrKeyPattern9x, 0x28);
|
||||||
|
|
||||||
/* Global variables. */
|
/* Global variables. */
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
static const char *g_tikTitleKeyTypeStrings[] = {
|
static const char *g_tikTitleKeyTypeStrings[] = {
|
||||||
[TikTitleKeyType_Common] = "common",
|
[TikTitleKeyType_Common] = "common",
|
||||||
[TikTitleKeyType_Personalized] = "personalized"
|
[TikTitleKeyType_Personalized] = "personalized"
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static MemoryLocation g_esMemoryLocation = {
|
static MemoryLocation g_esMemoryLocation = {
|
||||||
.program_id = ES_SYSMODULE_TID,
|
.program_id = ES_SYSMODULE_TID,
|
||||||
|
@ -454,7 +456,10 @@ static bool tikRetrieveRightsIdsByTitleKeyType(FsRightsId **out, u32 *out_count,
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
u32 count = 0, ids_written = 0;
|
u32 count = 0, ids_written = 0;
|
||||||
FsRightsId *rights_ids = NULL;
|
FsRightsId *rights_ids = NULL;
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
u8 str_idx = (personalized ? TikTitleKeyType_Personalized : TikTitleKeyType_Common);
|
u8 str_idx = (personalized ? TikTitleKeyType_Personalized : TikTitleKeyType_Common);
|
||||||
|
#endif
|
||||||
|
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
|
|
|
@ -669,7 +669,11 @@ NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size)
|
||||||
static bool usbSendCommand(void)
|
static bool usbSendCommand(void)
|
||||||
{
|
{
|
||||||
UsbCommandHeader *cmd_header = (UsbCommandHeader*)g_usbTransferBuffer;
|
UsbCommandHeader *cmd_header = (UsbCommandHeader*)g_usbTransferBuffer;
|
||||||
u32 cmd = cmd_header->cmd, cmd_block_size = cmd_header->cmd_block_size;
|
u32 cmd_block_size = cmd_header->cmd_block_size;
|
||||||
|
|
||||||
|
#if LOG_LEVEL <= LOG_LEVEL_ERROR
|
||||||
|
u32 cmd = cmd_header->cmd;
|
||||||
|
#endif
|
||||||
|
|
||||||
UsbStatus *cmd_status = (UsbStatus*)g_usbTransferBuffer;
|
UsbStatus *cmd_status = (UsbStatus*)g_usbTransferBuffer;
|
||||||
u32 status = UsbStatusType_Success;
|
u32 status = UsbStatusType_Success;
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace nxdt::utils {
|
||||||
{
|
{
|
||||||
if (!out)
|
if (!out)
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,14 +58,15 @@ namespace nxdt::utils {
|
||||||
/* Find the memory region in which this function is stored. */
|
/* Find the memory region in which this function is stored. */
|
||||||
/* The start of it will be the base address the homebrew was mapped to. */
|
/* The start of it will be the base address the homebrew was mapped to. */
|
||||||
rc = svcQueryMemory(out, &p, static_cast<u64>(reinterpret_cast<uintptr_t>(&GetHomebrewMemoryInfo)));
|
rc = svcQueryMemory(out, &p, static_cast<u64>(reinterpret_cast<uintptr_t>(&GetHomebrewMemoryInfo)));
|
||||||
if (R_FAILED(rc)) LOG_MSG("svcQueryMemory failed! (0x%08X).", rc);
|
if (R_FAILED(rc)) LOG_MSG_ERROR("svcQueryMemory failed! (0x%08X).", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOG_LEVEL == LOG_LEVEL_DEBUG
|
||||||
static bool UnwindStack(u64 *out_stack_trace, u32 *out_stack_trace_size, size_t max_stack_trace_size, u64 cur_fp)
|
static bool UnwindStack(u64 *out_stack_trace, u32 *out_stack_trace_size, size_t max_stack_trace_size, u64 cur_fp)
|
||||||
{
|
{
|
||||||
if (!out_stack_trace || !out_stack_trace_size || !max_stack_trace_size || !cur_fp)
|
if (!out_stack_trace || !out_stack_trace_size || !max_stack_trace_size || !cur_fp)
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG_ERROR("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +90,7 @@ namespace nxdt::utils {
|
||||||
|
|
||||||
return (*out_stack_trace_size > 0);
|
return (*out_stack_trace_size > 0);
|
||||||
}
|
}
|
||||||
|
#endif /* LOG_LEVEL == LOG_LEVEL_DEBUG */
|
||||||
|
|
||||||
static void NORETURN AbortProgramExecution(std::string str)
|
static void NORETURN AbortProgramExecution(std::string str)
|
||||||
{
|
{
|
||||||
|
@ -118,7 +120,7 @@ extern "C" {
|
||||||
void diagAbortWithResult(Result res)
|
void diagAbortWithResult(Result res)
|
||||||
{
|
{
|
||||||
/* Log error. */
|
/* Log error. */
|
||||||
LOG_MSG("*** libnx aborted with error code: 0x%08X ***", res);
|
LOG_MSG_ERROR("*** libnx aborted with error code: 0x%08X ***", res);
|
||||||
|
|
||||||
/* Abort program execution. */
|
/* Abort program execution. */
|
||||||
std::string crash_str = (g_borealisInitialized ? i18n::getStr("generic/libnx_abort"_i18n, res) : fmt::format("Fatal error triggered in libnx!\nError code: 0x{:08X}.", res));
|
std::string crash_str = (g_borealisInitialized ? i18n::getStr("generic/libnx_abort"_i18n, res) : fmt::format("Fatal error triggered in libnx!\nError code: 0x{:08X}.", res));
|
||||||
|
@ -129,20 +131,11 @@ extern "C" {
|
||||||
void __libnx_exception_handler(ThreadExceptionDump *ctx)
|
void __libnx_exception_handler(ThreadExceptionDump *ctx)
|
||||||
{
|
{
|
||||||
MemoryInfo info = {0};
|
MemoryInfo info = {0};
|
||||||
u32 stack_trace_size = 0;
|
|
||||||
u64 stack_trace[STACK_TRACE_SIZE] = {0};
|
|
||||||
|
|
||||||
char *exception_str = NULL;
|
|
||||||
size_t exception_str_size = 0;
|
|
||||||
|
|
||||||
std::string error_desc_str, crash_str;
|
std::string error_desc_str, crash_str;
|
||||||
|
|
||||||
/* Get homebrew memory info. */
|
/* Get homebrew memory info. */
|
||||||
nxdt::utils::GetHomebrewMemoryInfo(&info);
|
nxdt::utils::GetHomebrewMemoryInfo(&info);
|
||||||
|
|
||||||
/* Log exception type. */
|
|
||||||
LOG_MSG("*** Exception Triggered ***");
|
|
||||||
|
|
||||||
switch(ctx->error_desc)
|
switch(ctx->error_desc)
|
||||||
{
|
{
|
||||||
case ThreadExceptionDesc_InstructionAbort:
|
case ThreadExceptionDesc_InstructionAbort:
|
||||||
|
@ -171,6 +164,16 @@ extern "C" {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOG_LEVEL == LOG_LEVEL_DEBUG
|
||||||
|
char *exception_str = NULL;
|
||||||
|
size_t exception_str_size = 0;
|
||||||
|
|
||||||
|
u32 stack_trace_size = 0;
|
||||||
|
u64 stack_trace[STACK_TRACE_SIZE] = {0};
|
||||||
|
|
||||||
|
/* Log exception type. */
|
||||||
|
LOG_MSG_DEBUG("*** Exception Triggered ***");
|
||||||
|
|
||||||
EH_ADD_FMT_STR("Type: %s (0x%X)\r\n", error_desc_str.c_str(), ctx->error_desc);
|
EH_ADD_FMT_STR("Type: %s (0x%X)\r\n", error_desc_str.c_str(), ctx->error_desc);
|
||||||
|
|
||||||
/* Log CPU registers. */
|
/* Log CPU registers. */
|
||||||
|
@ -217,6 +220,7 @@ extern "C" {
|
||||||
|
|
||||||
/* Free exception info string. */
|
/* Free exception info string. */
|
||||||
if (exception_str) free(exception_str);
|
if (exception_str) free(exception_str);
|
||||||
|
#endif /* LOG_LEVEL == LOG_LEVEL_DEBUG */
|
||||||
|
|
||||||
/* Abort program execution. */
|
/* Abort program execution. */
|
||||||
crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : \
|
crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : \
|
||||||
|
|
Loading…
Reference in a new issue