sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

patch_libmalloc.py (1762B)


      1 #!/usr/bin/env python
      2 #
      3 # Patches the malloc() function in libmalloc.so to allocate more than the
      4 # specified number of bytes. This is needed to work around issues with the
      5 # compiler occasionally crashing.
      6 #
      7 # This script replaces the "move a1, a0" (00 80 28 25) instruction with
      8 # "addiu a1, a0, n" (24 85 nn nn), which causes the malloc function to add n to
      9 # the size parameter that was passed in.
     10 
     11 import hashlib
     12 import os.path
     13 import sys
     14 
     15 # file to patch
     16 filename = 'tools/ido5.3_compiler/lib/libmalloc.so'
     17 # Expected (unpatched) hash of file
     18 filehash = 'adde672b5d79b52ca3cce9a47c7cb648'
     19 # location in file to patch
     20 address = 0xAB4
     21 
     22 # Get parameter
     23 if len(sys.argv) != 2:
     24     print('Usage: ' + sys.argv[0] + ' n\n    where n is the number of extra bytes to allocate in malloc()')
     25     exit(1)
     26 n = int(sys.argv[1])
     27 
     28 # Original instruction "move a1, a0"
     29 oldinsn = bytearray([0x00, 0x80, 0x28, 0x25])
     30 
     31 # New instruction "addiu a1, a0, n"
     32 newinsn = bytearray([0x24, 0x85, (n >> 8) & 0xFF, (n & 0xFF)])
     33 
     34 # Patch the file
     35 try:
     36     with open(filename, 'rb+') as f:
     37         # Read file contents
     38         contents = bytearray(f.read())
     39 
     40         # Unpatch the file by restoring original instruction
     41         contents[address:address+4] = oldinsn
     42 
     43         # Verify the (unpatched) hash of the file
     44         md5 = hashlib.md5()
     45         md5.update(contents)
     46         if md5.hexdigest() != filehash:
     47             print('Error: ' + filename + ' does not appear to be the correct version.')
     48             exit(1)
     49 
     50         # Patch the file
     51         if n != 0:
     52             contents[address:address+4] = newinsn
     53 
     54         # Write file
     55         f.seek(0, os.SEEK_SET)
     56         f.write(contents)
     57 except IOError as e:
     58     print('Error: Could not open library file for writing: ' + str(e))