Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/include/alternate.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ void* getAlternate(void* addr);
void addAlternate(void* addr, void* alt);
void addCheckAlternate(void* addr, void* alt);
void cleanAlternate(void);
void suppressAlternate(void* addr);
void unsuppressAlternate(void* addr);
#ifdef HAVE_ALTJUMP
uintptr_t getAlternateJump(void* addr, int is32bits);
#endif
Expand Down
6 changes: 5 additions & 1 deletion src/mallochook.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,8 +881,12 @@ static void* ogg_page_body_copy = NULL;

static int my_ogg_sync_pageout_32(void* oy, void* og)
{
// Call the original emulated ogg_sync_pageout
// Suppress the alternate for the duration of the call to avoid
// infinite recursion: RunFunctionFmt -> EmuRun -> getAlternate
// would redirect back to this hook without suppression.
suppressAlternate((void*)real_ogg_sync_pageout_32);
int ret = (int)RunFunctionFmt(real_ogg_sync_pageout_32, "pp", oy, og);
unsuppressAlternate((void*)real_ogg_sync_pageout_32);

if(ret > 0 && og) {
// ogg_sync_pageout succeeded — og now has pointers into oy->data
Expand Down
23 changes: 22 additions & 1 deletion src/tools/alternate.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ typedef struct {
KHASH_MAP_INIT_INT64(alternate, my_alternate_t)
static kh_alternate_t *my_alternates = NULL;

// Per-address suppression: when set, getAlternate/hasAlternate/getAlternateJump
// will return "no alternate" for this specific address. Used by hooks that need
// to call through to the original emulated function via RunFunctionFmt without
// triggering infinite recursion (EmuRun applies getAlternate every iteration).
static uintptr_t alternate_suppress = 0;

int hasAlternate(void* addr) {
if(!my_alternates)
return 0;
if((uintptr_t)addr == alternate_suppress)
return 0;
khint_t k = kh_get(alternate, my_alternates, (uintptr_t)addr);
if(k==kh_end(my_alternates))
return 0;
Expand All @@ -32,6 +40,8 @@ int hasAlternate(void* addr) {
void* getAlternate(void* addr) {
if(!my_alternates)
return addr;
if((uintptr_t)addr == alternate_suppress)
return addr;
khint_t k = kh_get(alternate, my_alternates, (uintptr_t)addr);
if(k!=kh_end(my_alternates))
return kh_value(my_alternates, k).addr;
Expand All @@ -53,6 +63,15 @@ void addAlternate(void* addr, void* alt) {
#endif
}

void suppressAlternate(void* addr) {
alternate_suppress = (uintptr_t)addr;
}

void unsuppressAlternate(void* addr) {
(void)addr;
alternate_suppress = 0;
}

void addCheckAlternate(void* addr, void* alt) {
if(!hasAlternate(addr))
addAlternate(addr, alt);
Expand All @@ -70,6 +89,8 @@ void cleanAlternate() {
uintptr_t getAlternateJump(void* addr, int is32bits) {
if(!my_alternates)
return 0;
if((uintptr_t)addr == alternate_suppress)
return 0;
khint_t k = kh_get(alternate, my_alternates, (uintptr_t)addr);
if(k!=kh_end(my_alternates)) {
uintptr_t ret = kh_value(my_alternates, k).jump;
Expand All @@ -78,4 +99,4 @@ uintptr_t getAlternateJump(void* addr, int is32bits) {
}
return 0;
}
#endif
#endif
Loading