mirror of https://github.com/mgba-emu/mgba.git
GBA: Verify ELF entrypoint against ROM header (#2714)
This commit is contained in:
parent
b8c7196dd9
commit
694b80d289
1
CHANGES
1
CHANGES
|
@ -12,6 +12,7 @@ Other fixes:
|
||||||
- VFS: Fix minizip write returning 0 on success instead of size
|
- VFS: Fix minizip write returning 0 on success instead of size
|
||||||
Misc:
|
Misc:
|
||||||
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
|
||||||
|
- GBA: Improve detection of valid ELF ROMs
|
||||||
- macOS: Add category to plist (closes mgba.io/i/2691)
|
- macOS: Add category to plist (closes mgba.io/i/2691)
|
||||||
- macOS: Fix modern build with libepoxy (fixes mgba.io/i/2700)
|
- macOS: Fix modern build with libepoxy (fixes mgba.io/i/2700)
|
||||||
- Qt: Keep track of current pslette preset name (fixes mgba.io/i/2680)
|
- Qt: Keep track of current pslette preset name (fixes mgba.io/i/2680)
|
||||||
|
|
|
@ -154,6 +154,12 @@ void GBAHalt(struct GBA* gba);
|
||||||
void GBAStop(struct GBA* gba);
|
void GBAStop(struct GBA* gba);
|
||||||
void GBADebug(struct GBA* gba, uint16_t value);
|
void GBADebug(struct GBA* gba, uint16_t value);
|
||||||
|
|
||||||
|
#ifdef USE_ELF
|
||||||
|
struct ELF;
|
||||||
|
|
||||||
|
bool GBAVerifyELFEntry(struct ELF* elf, uint32_t target);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_DEBUGGERS
|
#ifdef USE_DEBUGGERS
|
||||||
struct mDebugger;
|
struct mDebugger;
|
||||||
void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger);
|
void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger);
|
||||||
|
|
|
@ -512,7 +512,7 @@ static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
|
||||||
#ifdef USE_ELF
|
#ifdef USE_ELF
|
||||||
struct ELF* elf = ELFOpen(vf);
|
struct ELF* elf = ELFOpen(vf);
|
||||||
if (elf) {
|
if (elf) {
|
||||||
if (ELFEntry(elf) == BASE_CART0) {
|
if (GBAVerifyELFEntry(elf, BASE_CART0)) {
|
||||||
GBALoadNull(core->board);
|
GBALoadNull(core->board);
|
||||||
}
|
}
|
||||||
bool success = mCoreLoadELF(core, elf);
|
bool success = mCoreLoadELF(core, elf);
|
||||||
|
|
|
@ -595,6 +595,63 @@ void GBADebug(struct GBA* gba, uint16_t flags) {
|
||||||
gba->debugFlags = GBADebugFlagsClearSend(gba->debugFlags);
|
gba->debugFlags = GBADebugFlagsClearSend(gba->debugFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ELF
|
||||||
|
bool GBAVerifyELFEntry(struct ELF* elf, uint32_t target) {
|
||||||
|
if (ELFEntry(elf) == target) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ELFProgramHeaders ph;
|
||||||
|
ELFProgramHeadersInit(&ph, 0);
|
||||||
|
ELFGetProgramHeaders(elf, &ph);
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < ELFProgramHeadersSize(&ph); ++i) {
|
||||||
|
Elf32_Phdr* phdr = ELFProgramHeadersGetPointer(&ph, i);
|
||||||
|
if (!phdr->p_filesz) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t phdrS = phdr->p_paddr;
|
||||||
|
size_t phdrE = phdrS + phdr->p_filesz;
|
||||||
|
|
||||||
|
// Does the segment contain our target address?
|
||||||
|
if (target < phdrS || target + 4 > phdrE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File offset to what should be the rom entry instruction
|
||||||
|
size_t off = phdr->p_offset + target - phdrS;
|
||||||
|
|
||||||
|
size_t eSize;
|
||||||
|
const char* bytes = ELFBytes(elf, &eSize);
|
||||||
|
|
||||||
|
// Bounds and alignment check
|
||||||
|
if (off >= eSize || off & 3) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t opcode;
|
||||||
|
LOAD_32(opcode, off, bytes);
|
||||||
|
struct ARMInstructionInfo info;
|
||||||
|
ARMDecodeARM(opcode, &info);
|
||||||
|
|
||||||
|
if (info.branchType != ARM_BRANCH && info.branchType != ARM_BRANCH_LINKED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bTarget = target + info.op1.immediate + 8;
|
||||||
|
|
||||||
|
if (ELFEntry(elf) == bTarget) {
|
||||||
|
ELFProgramHeadersDeinit(&ph);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFProgramHeadersDeinit(&ph);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool GBAIsROM(struct VFile* vf) {
|
bool GBAIsROM(struct VFile* vf) {
|
||||||
if (!vf) {
|
if (!vf) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -606,7 +663,7 @@ bool GBAIsROM(struct VFile* vf) {
|
||||||
uint32_t entry = ELFEntry(elf);
|
uint32_t entry = ELFEntry(elf);
|
||||||
bool isGBA = true;
|
bool isGBA = true;
|
||||||
isGBA = isGBA && ELFMachine(elf) == EM_ARM;
|
isGBA = isGBA && ELFMachine(elf) == EM_ARM;
|
||||||
isGBA = isGBA && (entry == BASE_CART0 || entry == BASE_WORKING_RAM + 0xC0);
|
isGBA = isGBA && (GBAVerifyELFEntry(elf, BASE_CART0) || GBAVerifyELFEntry(elf, BASE_WORKING_RAM + 0xC0));
|
||||||
ELFClose(elf);
|
ELFClose(elf);
|
||||||
return isGBA;
|
return isGBA;
|
||||||
}
|
}
|
||||||
|
@ -662,7 +719,7 @@ bool GBAIsMB(struct VFile* vf) {
|
||||||
#ifdef USE_ELF
|
#ifdef USE_ELF
|
||||||
struct ELF* elf = ELFOpen(vf);
|
struct ELF* elf = ELFOpen(vf);
|
||||||
if (elf) {
|
if (elf) {
|
||||||
bool isMB = ELFEntry(elf) == BASE_WORKING_RAM + 0xC0;
|
bool isMB = GBAVerifyELFEntry(elf, BASE_WORKING_RAM + 0xC0);
|
||||||
ELFClose(elf);
|
ELFClose(elf);
|
||||||
return isMB;
|
return isMB;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue