diff --git a/include/core/nxdt_log.h b/include/core/nxdt_log.h index 7854184..562b298 100644 --- a/include/core/nxdt_log.h +++ b/include/core/nxdt_log.h @@ -38,7 +38,7 @@ extern "C" { /// 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. /// 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) @@ -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_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_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__) +#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. */ -#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 +#if LOG_LEVEL <= LOG_LEVEL_INFO #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_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_BUF_INFO(dst, dst_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_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__) @@ -75,9 +85,9 @@ extern "C" { #define LOG_MSG_WARNING(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) -#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_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__) @@ -85,7 +95,7 @@ extern "C" { #define LOG_MSG_ERROR(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) -#endif /* LOG_LEVEL >= LOG_LEVEL_ERROR */ +#endif /* LOG_LEVEL <= LOG_LEVEL_ERROR */ /// Writes the provided string to the logfile. /// 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. -#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_BUF_GENERIC(dst, dst_size, level, fmt, ...) do {} while(0) #define LOG_DATA_GENERIC(data, data_size, level, fmt, ...) do {} while(0) diff --git a/libs/borealis b/libs/borealis index e46cb5a..df32a7c 160000 --- a/libs/borealis +++ b/libs/borealis @@ -1 +1 @@ -Subproject commit e46cb5a5eecf1caca5fee42502bd13ff54b0ae1f +Subproject commit df32a7cc42f06e0de259a8f0807e3d1690ef31f3 diff --git a/source/core/bktr.c b/source/core/bktr.c index 99f7846..c7dafdf 100644 --- a/source/core/bktr.c +++ b/source/core/bktr.c @@ -63,16 +63,20 @@ typedef struct { /* Global variables. */ +#if LOG_LEVEL <= LOG_LEVEL_ERROR static const char *g_bktrStorageTypeNames[] = { [BucketTreeStorageType_Indirect] = "Indirect", [BucketTreeStorageType_AesCtrEx] = "AesCtrEx", [BucketTreeStorageType_Compressed] = "Compressed", [BucketTreeStorageType_Sparse] = "Sparse" }; +#endif /* Function prototypes. */ +#if LOG_LEVEL <= LOG_LEVEL_ERROR static const char *bktrGetStorageTypeName(u8 storage_type); +#endif static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse); static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 read_size, u64 offset); @@ -161,8 +165,8 @@ bool bktrInitializeContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_c 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, \ - nca_ctx->content_id_str); + 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); return success; } @@ -311,7 +315,7 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse /* Find storage entry. */ 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; } @@ -332,7 +336,7 @@ bool bktrReadStorage(BucketTreeContext *ctx, void *out, u64 read_size, u64 offse 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: return success; @@ -353,7 +357,7 @@ bool bktrIsBlockWithinIndirectStorageRange(BucketTreeContext *ctx, u64 offset, u /* Find storage entry. */ 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; } @@ -490,10 +494,12 @@ end: return success; } +#if LOG_LEVEL <= LOG_LEVEL_ERROR static const char *bktrGetStorageTypeName(u8 storage_type) { return (storage_type < BucketTreeStorageType_Count ? g_bktrStorageTypeNames[storage_type] : NULL); } +#endif static bool bktrInitializeIndirectStorageContext(BucketTreeContext *out, NcaFsSectionContext *nca_fs_ctx, bool is_sparse) { diff --git a/source/core/mem.c b/source/core/mem.c index 6e7fc61..71f27e5 100644 --- a/source/core/mem.c +++ b/source/core/mem.c @@ -23,14 +23,18 @@ #include "nxdt_utils.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. */ static Mutex g_memMutex = 0; +static u64 g_fsTextSegmentAddr = 0; +#if LOG_LEVEL < LOG_LEVEL_NONE static char *g_memLogBuf = NULL; static size_t g_memLogBufSize = 0; +#endif /* Function prototypes. */ @@ -41,7 +45,7 @@ bool memRetrieveProgramMemorySegment(MemoryLocation *location) { if (!location || !location->program_id || !location->mask || location->mask >= BIT(3)) { - LOG_MSG("Invalid parameters!"); + LOG_MSG_ERROR("Invalid parameters!"); return false; } @@ -54,7 +58,7 @@ bool memRetrieveFullProgramMemory(MemoryLocation *location) { if (!location || !location->program_id) { - LOG_MSG("Invalid parameters!"); + LOG_MSG_ERROR("Invalid parameters!"); return false; } @@ -91,49 +95,72 @@ static bool memRetrieveProgramMemory(MemoryLocation *location, bool is_segment) /* Clear output MemoryLocation element. */ 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. */ - /* 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. */ logControlMutex(true); +#endif /* Retrieve debug handle by 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; } if (is_segment && location->program_id == FS_SYSMODULE_TID) { - /* If dealing with FS, locate the "real" .text segment, since Atmosphère emuMMC has two. */ - do { - rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr); - if (R_FAILED(rc)) - { - MEMLOG("svcQueryDebugProcessMemory failed for program %016lX! (0x%08X).", location->program_id, rc); - success = false; - goto end; - } + /* 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 { + rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr); + if (R_FAILED(rc)) + { + MEMLOG_ERROR("svcQueryDebugProcessMemory failed for program %016lX! (0x%X).", location->program_id, rc); + success = false; + goto end; + } - 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 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 - addr = (mem_info.addr + mem_info.size); - } while(addr != 0); + 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; - addr = last_text_addr; + addr = (mem_info.addr + mem_info.size); + } while(addr != 0); + + g_fsTextSegmentAddr = last_text_addr; + MEMLOG_DEBUG("FS .text segment address: 0x%lX.", g_fsTextSegmentAddr); + } + + addr = g_fsTextSegmentAddr; } do { rc = svcQueryDebugProcessMemory(&mem_info, &page_info, debug_handle, addr); 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; 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); /* 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); 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; 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); 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; break; } @@ -171,17 +198,20 @@ end: /* Close debug handle. */ if (debug_handle != INVALID_HANDLE) svcCloseHandle(debug_handle); +#if LOG_LEVEL < LOG_LEVEL_NONE /* Unlock logfile mutex. */ logControlMutex(false); +#endif 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; } 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. */ logWriteStringToLogFile(g_memLogBuf); @@ -193,6 +223,7 @@ end: } g_memLogBufSize = 0; +#endif return success; } @@ -201,7 +232,7 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id) { if (!out || !program_id) { - MEMLOG("Invalid parameters!"); + MEMLOG_ERROR("Invalid parameters!"); 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 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); 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; } + MEMLOG_DEBUG("Process ID (%016lX): 0x%lX.", program_id, pid); + /* Retrieve debug handle right away. */ rc = svcDebugActiveProcess(&debug_handle, pid); 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; } } else { @@ -234,14 +267,16 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id) pids = calloc(300, sizeof(u64)); if (!pids) { - MEMLOG("Failed to allocate memory for PID list!"); + MEMLOG_ERROR("Failed to allocate memory for PID list!"); return false; } + MEMLOG_DEBUG("svcDebugActiveProcess returned %u process IDs.", num_processes); + rc = svcGetProcessList((s32*)&num_processes, pids, 300); if (R_FAILED(rc)) { - MEMLOG("svcGetProcessList failed! (0x%08X).", rc); + MEMLOG_ERROR("svcGetProcessList failed! (0x%08X).", rc); free(pids); return false; } @@ -249,14 +284,26 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id) /* Perform a lookup using the retrieved process list. */ 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]); - 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. */ - /* 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); - 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. */ svcCloseHandle(debug_handle); @@ -267,11 +314,13 @@ static bool memRetrieveDebugHandleFromProgramById(Handle *out, u64 program_id) 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; } } + MEMLOG_DEBUG("Debug handle (%016lX): 0x%X.", program_id, debug_handle); + /* Set output debug handle. */ *out = debug_handle; diff --git a/source/core/nca.c b/source/core/nca.c index dc6fcf3..c60da1b 100644 --- a/source/core/nca.c +++ b/source/core/nca.c @@ -1005,7 +1005,10 @@ end: static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) { +#if LOG_LEVEL <= LOG_LEVEL_WARNING NcaContext *nca_ctx = (NcaContext*)ctx->nca_ctx; +#endif + bool success = false, valid = true; u64 accum = 0; @@ -1021,8 +1024,8 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) 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) { - LOG_DATA(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); + 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); break; } @@ -1033,8 +1036,8 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) 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)) { - LOG_MSG("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); + 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); valid = false; break; } @@ -1053,8 +1056,8 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) 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) { - LOG_DATA(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); + 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); break; } @@ -1065,8 +1068,8 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) 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)) { - LOG_MSG("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); + 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); valid = false; break; } @@ -1079,7 +1082,7 @@ static bool ncaFsSectionValidateHashDataBoundaries(NcaFsSectionContext *ctx) break; 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; } diff --git a/source/core/nxdt_log.c b/source/core/nxdt_log.c index 915e3fa..4874cd6 100644 --- a/source/core/nxdt_log.c +++ b/source/core/nxdt_log.c @@ -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, ...) { - 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; @@ -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, ...) { - 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; 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) { /* 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; diff --git a/source/core/nxdt_utils.c b/source/core/nxdt_utils.c index 13a78f5..17d479e 100644 --- a/source/core/nxdt_utils.c +++ b/source/core/nxdt_utils.c @@ -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 (__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. */ u32 hos_version = hosversionGet(); - LOG_MSG(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)); - LOG_MSG("Horizon OS version: %u.%u.%u.", HOSVER_MAJOR(hos_version), HOSVER_MINOR(hos_version), HOSVER_MICRO(hos_version)); + LOG_MSG_INFO(APP_TITLE " v" APP_VERSION " starting (" GIT_REV "). Built on " BUILD_TIMESTAMP "."); + if (g_nxLinkSocketFd >= 0) LOG_MSG_INFO("nxlink enabled! Host IP address: %s.", inet_ntoa(__nxlink_host)); + 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. */ _utilsGetCustomFirmwareType(); - if (g_customFirmwareType != UtilsCustomFirmwareType_Unknown) LOG_MSG("Detected %s CFW.", (g_customFirmwareType == UtilsCustomFirmwareType_Atmosphere ? "Atmosphère" : \ - (g_customFirmwareType == UtilsCustomFirmwareType_SXOS ? "SX OS" : "ReiNX"))); + if (g_customFirmwareType != UtilsCustomFirmwareType_Unknown) LOG_MSG_INFO("Detected %s CFW.", (g_customFirmwareType == UtilsCustomFirmwareType_Atmosphere ? "Atmosphère" : \ + (g_customFirmwareType == UtilsCustomFirmwareType_SXOS ? "SX OS" : "ReiNX"))); /* Check if we're not running under a development unit. */ 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. */ 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). */ /* 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) { - 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. */ /* 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); 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; }*/ } @@ -245,15 +247,18 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv) if (!ret) { + char *msg = NULL; 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. */ 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); +#endif /* Print error message. */ utilsPrintConsoleError(msg); @@ -326,8 +331,10 @@ void utilsCloseResources(void) rename(NRO_TMP_PATH, NRO_PATH); }*/ +#if LOG_LEVEL <= LOG_LEVEL_ERROR /* Close logfile. */ logCloseLogFile(); +#endif /* Unlock applet exit. */ appletUnlockExit(); diff --git a/source/core/tik.c b/source/core/tik.c index bd8c4a7..f0dfc2f 100644 --- a/source/core/tik.c +++ b/source/core/tik.c @@ -72,10 +72,12 @@ NXDT_ASSERT(TikEsCtrKeyPattern9x, 0x28); /* Global variables. */ +#if LOG_LEVEL <= LOG_LEVEL_ERROR static const char *g_tikTitleKeyTypeStrings[] = { [TikTitleKeyType_Common] = "common", [TikTitleKeyType_Personalized] = "personalized" }; +#endif static MemoryLocation g_esMemoryLocation = { .program_id = ES_SYSMODULE_TID, @@ -454,7 +456,10 @@ static bool tikRetrieveRightsIdsByTitleKeyType(FsRightsId **out, u32 *out_count, Result rc = 0; u32 count = 0, ids_written = 0; FsRightsId *rights_ids = NULL; + +#if LOG_LEVEL <= LOG_LEVEL_ERROR u8 str_idx = (personalized ? TikTitleKeyType_Personalized : TikTitleKeyType_Common); +#endif *out = NULL; *out_count = 0; diff --git a/source/core/usb.c b/source/core/usb.c index 896817d..cfbc48f 100644 --- a/source/core/usb.c +++ b/source/core/usb.c @@ -669,7 +669,11 @@ NX_INLINE void usbPrepareCommandHeader(u32 cmd, u32 cmd_block_size) static bool usbSendCommand(void) { 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; u32 status = UsbStatusType_Success; diff --git a/source/exception_handler.cpp b/source/exception_handler.cpp index 4a45663..0238d5c 100644 --- a/source/exception_handler.cpp +++ b/source/exception_handler.cpp @@ -48,7 +48,7 @@ namespace nxdt::utils { { if (!out) { - LOG_MSG("Invalid parameters!"); + LOG_MSG_ERROR("Invalid parameters!"); return; } @@ -58,14 +58,15 @@ namespace nxdt::utils { /* Find the memory region in which this function is stored. */ /* The start of it will be the base address the homebrew was mapped to. */ rc = svcQueryMemory(out, &p, static_cast(reinterpret_cast(&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) { 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; } @@ -89,6 +90,7 @@ namespace nxdt::utils { return (*out_stack_trace_size > 0); } +#endif /* LOG_LEVEL == LOG_LEVEL_DEBUG */ static void NORETURN AbortProgramExecution(std::string str) { @@ -118,7 +120,7 @@ extern "C" { void diagAbortWithResult(Result res) { /* 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. */ 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) { 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; /* Get homebrew memory info. */ nxdt::utils::GetHomebrewMemoryInfo(&info); - /* Log exception type. */ - LOG_MSG("*** Exception Triggered ***"); - switch(ctx->error_desc) { case ThreadExceptionDesc_InstructionAbort: @@ -171,6 +164,16 @@ extern "C" { 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); /* Log CPU registers. */ @@ -217,6 +220,7 @@ extern "C" { /* Free exception info string. */ if (exception_str) free(exception_str); +#endif /* LOG_LEVEL == LOG_LEVEL_DEBUG */ /* Abort program execution. */ crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : \