Compare commits

...

5 Commits

Author SHA1 Message Date
Fruityloops
18707701d4
Merge 157eb0ec6c into 3197b1e25b 2025-08-09 22:22:10 +09:30
comex
3197b1e25b nanovg: disable some compiler warnings
Disable all warnings seen on devkitA64 GCC 15.1.0:

- Several false-positive `-Wmisleading-indentation` warnings (the
  indentation is not actually misleading)

- One `-Wuse-after-free` warning, which looks alarming and represents
  very dubious design, but is ultimately harmless (a freed pointer is
  passed to a function that doesn't use it).

- Some `-Wunused-function` warnings in `simd/neon.h`
2025-08-08 14:16:03 -07:00
comex
822cbbbc8b daybreak: fix strncpy compiler warning
GCC warned that the output string would not be nul-terminated if the
input string was too long.  Fix this by subtracting 1 from the size
argument, as is done for other `strncpy` calls in the file.  (It would
probably be better to avoid `strncpy` entirely, but this is just a
simple fix.)
2025-08-08 14:16:03 -07:00
comex
4237f52ee2 haze: fix duplicate-macro warnings
haze was including both `<switch.h>` and `vapours/types.hpp` which both
define `R_SUCCEEDED` and `R_FAILED`, producing compiler warnings.

The intent is that `vapours/types.hpp` only gets included when targeting
not-Switch and/or not-EL0.  But the check didn't account for
Troposphère.  Fix that.
2025-08-08 14:16:03 -07:00
fruityloops1
157eb0ec6c creport: Add better 32-bit support 2025-03-09 23:18:12 +01:00
7 changed files with 99 additions and 56 deletions

View File

@ -44,8 +44,9 @@
#include <bit>
#include <span>
/* Stratosphere wants additional libstdc++ headers, others do not. */
#ifdef ATMOSPHERE_IS_STRATOSPHERE
/* Stratosphere/Troposphere want additional libstdc++ headers and libnx,
* others do not. */
#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_TROPOSPHERE)
#include <memory>
#include <mutex>
@ -71,7 +72,7 @@
/* Non-EL0 code can't include libnx. */
#include "types.hpp"
#endif /* ATMOSPHERE_IS_STRATOSPHERE */
#endif /* defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_TROPOSPHERE) */
/* Atmosphere meta. */
#include <vapours/ams_version.h>

View File

@ -105,7 +105,7 @@ namespace ams::creport {
if (this->OpenProcess(process_id)) {
/* Parse info from the crashed process. */
this->ProcessExceptions();
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_crashed_thread, this->Is64Bit());
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_crashed_thread);
m_thread_list->ReadFromProcess(m_debug_handle, m_thread_tls_map, this->Is64Bit());
/* Associate module list to threads. */
@ -120,7 +120,7 @@ namespace ams::creport {
/* Nintendo's creport finds extra modules by looking at all threads if application, */
/* but there's no reason for us not to always go looking. */
for (size_t i = 0; i < m_thread_list->GetThreadCount(); i++) {
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_thread_list->GetThreadInfo(i), this->Is64Bit());
m_module_list->FindModulesFromThreadInfo(m_debug_handle, m_thread_list->GetThreadInfo(i));
}
/* Cache the module base address to send to fatal. */
@ -188,6 +188,7 @@ namespace ams::creport {
void CrashReport::HandleDebugEventInfoCreateProcess(const svc::DebugEventInfo &d) {
m_process_info = d.info.create_process;
m_module_list->SetIs64Bit(Is64Bit());
/* On 5.0.0+, we want to parse out a dying message from application crashes. */
if (hos::GetVersion() < hos::Version_5_0_0 || !IsApplication()) {

View File

@ -58,26 +58,26 @@ namespace ams::creport {
}
}
void ModuleList::FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread, bool is_64_bit) {
void ModuleList::FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread) {
/* Set the debug handle, for access in other member functions. */
m_debug_handle = debug_handle;
/* Try to add the thread's PC. */
this->TryAddModule(thread.GetPC(), is_64_bit);
this->TryAddModule(thread.GetPC());
/* Try to add the thread's LR. */
this->TryAddModule(thread.GetLR(), is_64_bit);
this->TryAddModule(thread.GetLR());
/* Try to add all the addresses in the thread's stacktrace. */
for (size_t i = 0; i < thread.GetStackTraceSize(); i++) {
this->TryAddModule(thread.GetStackTrace(i), is_64_bit);
this->TryAddModule(thread.GetStackTrace(i));
}
}
void ModuleList::TryAddModule(uintptr_t guess, bool is_64_bit) {
void ModuleList::TryAddModule(uintptr_t guess) {
/* Try to locate module from guess. */
uintptr_t base_address = 0;
if (!this->TryFindModule(std::addressof(base_address), guess, is_64_bit)) {
if (!this->TryFindModule(std::addressof(base_address), guess)) {
return;
}
@ -114,9 +114,7 @@ namespace ams::creport {
util::SNPrintf(module.name, sizeof(module.name), "[%02x%02x%02x%02x]", module.module_id[0], module.module_id[1], module.module_id[2], module.module_id[3]);
} else {
/* The module has a name, and so might have a symbol table. Try to add it, if it does. */
if (is_64_bit) {
DetectModuleSymbolTable(module);
}
DetectModuleSymbolTable(module);
}
}
@ -134,9 +132,7 @@ namespace ams::creport {
}
}
bool ModuleList::TryFindModule(uintptr_t *out_address, uintptr_t guess, bool is_64_bit) {
AMS_UNUSED(is_64_bit);
bool ModuleList::TryFindModule(uintptr_t *out_address, uintptr_t guess) {
/* Query the memory region our guess falls in. */
svc::MemoryInfo mi;
svc::PageInfo pi;
@ -265,7 +261,6 @@ namespace ams::creport {
}
/* Declare temporaries. */
u64 temp_64;
u32 temp_32;
/* Get module state. */
@ -316,43 +311,54 @@ namespace ams::creport {
dyn_address = module.start_address + mod_offset + temp_32;
}
/* Locate tables inside .dyn. */
for (size_t ofs = 0; /* ... */; ofs += 0x10) {
/* Read the DynamicTag. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_64)), m_debug_handle, dyn_address + ofs, sizeof(u64)))) {
return;
}
if (temp_64 == 0) {
/* We're done parsing .dyn. */
break;
} else if (temp_64 == 4) {
/* We found DT_HASH */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_64)), m_debug_handle, dyn_address + ofs + sizeof(u64), sizeof(u64)))) {
{
struct Elf64_Dyn {
u64 d_tag;
u64 d_val;
} dyn;
struct Elf32_Dyn {
u32 d_tag;
u32 d_val;
} dyn_32;
size_t dyn_size = m_is_64_bit ? sizeof(Elf64_Dyn) : sizeof(Elf32_Dyn);
uintptr_t dyn_read_address = m_is_64_bit ? reinterpret_cast<uintptr_t>(std::addressof(dyn)) : reinterpret_cast<uintptr_t>(std::addressof(dyn_32));
/* Locate tables inside .dyn. */
for (size_t ofs = 0; /* ... */; ofs += dyn_size) {
/* Read the dynamic entry. */
if (R_FAILED(svc::ReadDebugProcessMemory(dyn_read_address, m_debug_handle, dyn_address + ofs, dyn_size))) {
return;
}
/* Read nchain, to get the number of symbols. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_32)), m_debug_handle, module.start_address + temp_64 + sizeof(u32), sizeof(u32)))) {
return;
/* Copy entry if necessary. */
if (!m_is_64_bit) {
dyn.d_tag = dyn_32.d_tag;
dyn.d_val = dyn_32.d_val;
}
if (dyn.d_tag == 0) {
/* We're done parsing .dyn. */
break;
} else if (dyn.d_tag == 4) {
/* We found DT_HASH */
/* Read nchain, to get the number of symbols. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_32)), m_debug_handle, module.start_address + dyn.d_val + sizeof(u32), sizeof(u32)))) {
return;
}
num_sym = temp_32;
} else if (dyn.d_tag == 5) {
/* We found DT_STRTAB */
str_tab = module.start_address + dyn.d_val;
} else if (dyn.d_tag == 6) {
/* We found DT_SYMTAB */
num_sym = temp_32;
} else if (temp_64 == 5) {
/* We found DT_STRTAB */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_64)), m_debug_handle, dyn_address + ofs + sizeof(u64), sizeof(u64)))) {
return;
sym_tab = module.start_address + dyn.d_val;
}
str_tab = module.start_address + temp_64;
} else if (temp_64 == 6) {
/* We found DT_SYMTAB */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(temp_64)), m_debug_handle, dyn_address + ofs + sizeof(u64), sizeof(u64)))) {
return;
}
sym_tab = module.start_address + temp_64;
}
}
@ -379,7 +385,7 @@ namespace ams::creport {
/* Try to locate an appropriate symbol. */
for (size_t j = 0; j < module.num_sym; ++j) {
/* Read symbol from the module's symbol table. */
struct {
struct Elf64_Sym {
u32 st_name;
u8 st_info;
u8 st_other;
@ -387,7 +393,33 @@ namespace ams::creport {
u64 st_value;
u64 st_size;
} sym;
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(sym)), m_debug_handle, module.sym_tab + j * sizeof(sym), sizeof(sym)))) {
/* Elf32_Sym is different from Elf64_Sym. */
if (!m_is_64_bit)
{
struct Elf32_Sym {
u32 st_name;
u32 st_value;
u32 st_size;
u8 st_info;
u8 st_other;
u16 st_shndx;
} sym_32;
/* Read 32-bit symbol. */
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(sym_32)), m_debug_handle, module.sym_tab + j * sizeof(sym_32), sizeof(sym_32)))) {
break;
}
sym.st_name = sym_32.st_name;
sym.st_info = sym_32.st_info;
sym.st_other = sym_32.st_other;
sym.st_shndx = sym_32.st_shndx;
sym.st_value = sym_32.st_value;
sym.st_size = sym_32.st_size;
}
/* Read 64-bit symbol. */
else if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(sym)), m_debug_handle, module.sym_tab + j * sizeof(sym), sizeof(sym)))) {
break;
}

View File

@ -37,13 +37,14 @@ namespace ams::creport {
};
private:
os::NativeHandle m_debug_handle;
bool m_is_64_bit;
size_t m_num_modules;
ModuleInfo m_modules[ModuleCountMax];
/* For pretty-printing. */
char m_address_str_buf[1_KB];
public:
ModuleList() : m_debug_handle(os::InvalidNativeHandle), m_num_modules(0) {
ModuleList() : m_debug_handle(os::InvalidNativeHandle), m_is_64_bit(true), m_num_modules(0) {
std::memset(m_modules, 0, sizeof(m_modules));
}
@ -55,12 +56,16 @@ namespace ams::creport {
return m_modules[i].start_address;
}
void FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread, bool is_64_bit);
void SetIs64Bit(bool is_64_bit) {
m_is_64_bit = is_64_bit;
}
void FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread);
const char *GetFormattedAddressString(uintptr_t address);
void SaveToFile(ScopedFile &file);
private:
bool TryFindModule(uintptr_t *out_address, uintptr_t guess, bool is_64_bit);
void TryAddModule(uintptr_t guess, bool is_64_bit);
bool TryFindModule(uintptr_t *out_address, uintptr_t guess);
void TryAddModule(uintptr_t guess);
void GetModuleName(char *out_name, uintptr_t text_start, uintptr_t ro_start);
void GetModuleId(u8 *out, uintptr_t ro_start);
void DetectModuleSymbolTable(ModuleInfo &module);

View File

@ -50,6 +50,8 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += -Wno-misleading-indentation -Wno-use-after-free -Wno-unused-function
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -std=gnu++17 -fno-exceptions -fno-rtti

View File

@ -1277,7 +1277,7 @@ namespace dbk {
if (InitializeMenu(screen_width, screen_height)) {
/* Set the update path. */
strncpy(g_update_path, update_path, sizeof(g_update_path));
strncpy(g_update_path, update_path, sizeof(g_update_path)-1);
/* Change the menu. */
ChangeMenu(std::make_shared<ValidateUpdateMenu>(g_current_menu));

View File

@ -15,7 +15,9 @@
*/
#pragma once
#define ATMOSPHERE_IS_TROPOSPHERE
#define ATMOSPHERE_OS_HORIZON
#define ATMOSPHERE_BOARD_NINTENDO_NX
#define ATMOSPHERE_ARCH_ARM64
#define ATMOSPHERE_ARCH_ARM_V8A