Compare commits

...

4 Commits

Author SHA1 Message Date
Techflash
2cb0b61b3e
Merge b2a57f4391 into 04f71e5e6d 2025-12-15 09:46:55 +01:00
Jordan Woyak
04f71e5e6d
Merge pull request #14211 from cscd98/enumerate-radios
mingw: fix usage of std::invocable with EnumerateRadios
2025-12-12 17:21:51 -06:00
Craig Carnell
eded73fe8b mingw: fix use of std::invocable with EnumerateRadios 2025-12-12 09:33:10 +00:00
techflashYT
b2a57f4391 Core/Boot: Fix ELF load address semantics
Tested with a binary that has VMA != (LMA | 0x80000000), unlike most
libogc binaries.  This is indeed a valid setup for ELFs, and one that is
generally expected to work properly.

Test code: https://github.com/Wii-Linux/NPLL/tree/reloc

In either case, you still need to set the PC in the debugger to get it
to boot properly, though that is a different issue that I will be fixing
in a future patch.
Without this patch, the code to be runtime-relocated ends up already
loaded at the desired final address, and then when the code tries to
relocate from what it thinks is the source address (where the code
should be, where the LMA is) to the destination address (the VMA, where
Dolphin mistakenly already put the code), it ends up overwriting the
code that it is about to execute with garbage, and then promptly
crashing.
After this patch is applied, the behavior now matches the GameCube with
Swiss (assuming a [recent patch](bb4a57186c)
is applied), and the Wii with the Homebrew Channel.
2025-11-13 06:20:21 -07:00
2 changed files with 11 additions and 5 deletions

View File

@ -143,17 +143,23 @@ bool ElfReader::LoadIntoMemory(Core::System& system, bool only_in_mem1) const
{ {
Elf32_Phdr* p = segments + i; Elf32_Phdr* p = segments + i;
INFO_LOG_FMT(BOOT, "Type: {} Vaddr: {:08x} Filesz: {} Memsz: {}", p->p_type, p->p_vaddr, INFO_LOG_FMT(BOOT, "Type: {} Vaddr: {:08x} Paddr: {:08x} Filesz: {} Memsz: {}", p->p_type,
p->p_filesz, p->p_memsz); p->p_vaddr, p->p_paddr, p->p_filesz, p->p_memsz);
if (p->p_type == PT_LOAD) if (p->p_type == PT_LOAD)
{ {
u32 writeAddr = p->p_vaddr; // Check LMA (paddr) first - some are nonsense, so fall back to VMA (vaddr) if invalid
u32 writeAddr = p->p_paddr;
if (writeAddr)
writeAddr |= 0x80000000; // map to virtual address
else
writeAddr = p->p_vaddr; // LMA is empty, fall back to VMA
const u8* src = GetSegmentPtr(i); const u8* src = GetSegmentPtr(i);
u32 srcSize = p->p_filesz; u32 srcSize = p->p_filesz;
u32 dstSize = p->p_memsz; u32 dstSize = p->p_memsz;
if (only_in_mem1 && p->p_vaddr >= memory.GetRamSizeReal()) if (only_in_mem1 && writeAddr >= memory.GetRamSizeReal())
continue; continue;
memory.CopyToEmu(writeAddr, src, srcSize); memory.CopyToEmu(writeAddr, src, srcSize);

View File

@ -158,7 +158,7 @@ static std::optional<std::string> GetParentDeviceDescription(const WCHAR* hid_if
return std::nullopt; return std::nullopt;
} }
void EnumerateRadios(std::invocable<EnumerationControl(HANDLE)> auto&& enumeration_callback) void EnumerateRadios(std::invocable<HANDLE> auto&& enumeration_callback)
{ {
constexpr BLUETOOTH_FIND_RADIO_PARAMS radio_params{ constexpr BLUETOOTH_FIND_RADIO_PARAMS radio_params{
.dwSize = sizeof(radio_params), .dwSize = sizeof(radio_params),