devkitPro / wut

Let's try to make a Wii U Toolchain / SDK for creating rpx/rpl.
zlib License
244 stars 52 forks source link

newlib: Failure to create mutex when fopen() is called #55

Closed CreeperMario closed 7 years ago

CreeperMario commented 7 years ago

Hi. So I finally found a bug caused by newlib, which I discovered while working on porting @shinyquagsire23's Pazaak game to CMake WUT.

So basically, any attempts to call fopen() will result in a freeze. Following the stack dump retrieved from dumping my console's crash logs (pulled using Mocha CFW and FTPiiU Everywhere, from /storage_slc/logs), the issue is definitely caused by attempting to create a mutex.

Core1: Instruction at 0x01037DE4 (from SRR0) invalid access of 0x0000001C (value from DAR)
INFO: nn::ipc avoided busy close on /dev/acp_main (moduleId = 301, tag = 0) from pid = 21
00;01;25;942: 
--Proc15-Core1--------- OSContext 0x100457E0 --------------------

00;01;25;942: tag1  = 0x4F53436F (expecting 0x4F53436F)
00;01;25;942: tag2  = 0x6E747874 (expecting 0x6E747874)
00;01;25;942: TBR   = 0x00000001_38117006
00;01;25;942: CR    = 0x82000284
00;01;25;942: CTR   = 0x01037ED0
00;01;25;942: LR    = 0x01037DDC coreinit.rpl|OSInitMutexEx+0x68
00;01;25;942: SRR0  = 0x01037DE4 coreinit.rpl|OSInitMutexEx+0x68
00;01;25;942: SRR1  = 0x00005072

00;01;25;942: state = 0x0006

00;01;25;942: r0   = 0x01037f04 (      17006340)  r16  = 0x00000000 (             0)
00;01;25;942: r1   = 0x10737d80 (     276004224)  r17  = 0x00000000 (             0)
00;01;25;942: r2   = 0x1050b000 (     273723392)  r18  = 0x00000000 (             0)
00;01;25;942: r3   = 0x100457e0 (     268720096)  r19  = 0x00000000 (             0)
00;01;25;942: r4   = 0x107dd728 (     276682536)  r20  = 0x00000000 (             0)
00;01;25;942: r5   = 0x10504fa4 (     273698724)  r21  = 0x00000000 (             0)
00;01;25;942: r6   = 0x00000000 (             0)  r22  = 0x00000000 (             0)
00;01;25;942: r7   = 0x00000000 (             0)  r23  = 0x00000000 (             0)
00;01;25;942: r8   = 0x10506681 (     273704577)  r24  = 0x00000000 (             0)
00;01;25;942: r9   = 0x00000001 (             1)  r25  = 0x00000000 (             0)
00;01;25;942: r10  = 0x01037ef8 (      17006328)  r26  = 0x00000000 (             0)
00;01;25;942: r11  = 0x81037ef8 (   -2130477320)  r27  = 0x00000000 (             0)
00;01;25;942: r12  = 0x10055e80 (     268787328)  r28  = 0x00000000 (             0)
00;01;25;942: r13  = 0x1050b000 (     273723392)  r29  = 0x100457e0 (     268720096)
00;01;25;942: r14  = 0x00000000 (             0)  r30  = 0x00000000 (             0)
00;01;25;942: r15  = 0x00000000 (             0)  r31  = 0x00000001 (             1)
00;01;25;942: 
--Stack Trace--------------------------
00;01;25;943: 
Address:      Back Chain    LR Save
00;01;25;943: 0x10737d80:   0x10737d98    0x00000000
00;01;25;943: 0x10737d98:   0x10737da8    0x01037f04 coreinit.rpl|OSLockMutex+0x34
00;01;25;943: 0x10737da8:   0x10737dd0    0x0c018c98 pazaak-wiiu|__libwut_lock_acquire+0x4c
00;01;25;943: 0x10737dd0:   0x10737de8    0x0c07a220 pazaak-wiiu|__sfp+0x20
00;01;25;944: 0x10737de8:   0x10737e10    0x0c07a404 pazaak-wiiu|_fopen_r+0x44
00;01;25;944: 0x10737e10:   0x10737e38    0x0c009eb0 pazaak-wiiu|read_file_to_bytes+0x28
00;01;25;944: 0x10737e38:   0x10737e70    0x0c00ba9c pazaak-wiiu|main+0x48
00;01;25;944: 0x10737e70:   0x00000001    0x0c016bf4 pazaak-wiiu|free_img_texture+0x70
00:01:26:134: COS encountered unrecoverable error...

Pending Resource Request for COS processes...
        Title Id       Process Id -> RM Path             
exited...
[+-*APPLICATION EXITED 0*-+]
[+-*OUTPUT EOF*-+]

At the top of the stack (or bottom?) is the function __libwut_lock_acquire, which as you know is from newlib.c in libcrt.

static int __libwut_lock_acquire(int *lock)
{
   OSMutex *mutex = NULL;
   if (!lock || *lock == 0) {
      return -1;
   }

   OSLockMutex(mutex);
   return 0;
}

I'm not too experienced with threading and stuff like that, but I really don't think a mutex would exist at 0x0 (NULL). Is this mutex variable supposed to be initialized to something? Or are we supposed to use lock or sMallocMutex instead?

I tried stubbing __libwut_lock_acquire (and __libwut_lock_release) to simply return 0 and not do anything else, and this allows fopen and all related routines to work flawlessly, however not doing anything with this mutex is probably not the best thing to do in multithreded environments.

CreeperMario commented 7 years ago

This seems to work as well, but I'm still not sure if this is the proper fix.

static int __libwut_lock_acquire(int *lock)
{
   OSMutex *mutex = NULL;
   if (!lock || *lock == 0) {
      return -1;
   }

+  mutex = (OSMutex*)*lock;
   OSLockMutex(mutex);
   return 0;
}

static int __libwut_lock_release(int *lock)
{
   OSMutex *mutex = NULL;
   if (!lock || *lock == 0) {
      return -1;
   }

+  mutex = (OSMutex*)*lock;
   OSUnlockMutex(mutex);
   return 0;
}
exjam commented 7 years ago

Sorry for the slow reply, your fix is correct: https://github.com/decaf-emu/wut/commit/96b24236f15fe23e17a40d2680e7625eef569d38