1
+ # Copyright PistonMiner, all rights reserved
2
+ # Revision 0.1
3
+
4
+ import sys
5
+ import os
6
+ import struct
7
+ import ctypes
8
+
9
+ # read the data in.
10
+ filename_in = sys .argv [1 ]
11
+ input = open (filename_in , "rb" )
12
+ file_data = ctypes .create_string_buffer (input .read ())
13
+ input .close ()
14
+
15
+ baseAddress = int (sys .argv [2 ], 16 ) #0x805ba9a0 #0x804FFF3C #
16
+
17
+ curOffset = 0x0
18
+ relID = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
19
+ curOffset = 0xC
20
+ section_count = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
21
+ curOffset = 0x10
22
+ section_info_offset = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
23
+ curOffset = 0x28
24
+ import_offset = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
25
+ curOffset = 0x2C
26
+ import_size = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
27
+
28
+ # set imports and relocations to invalid since we are doing them
29
+ struct .pack_into (">L" , file_data , 0x24 , 0 ) # reloc offset
30
+ struct .pack_into (">L" , file_data , 0x28 , 0 ) # import offset
31
+ struct .pack_into (">L" , file_data , 0x2C , 0 ) # import count
32
+
33
+ sections = [] # [list of [offset, size]]
34
+ imports = [] # [list of [id, offset]]
35
+
36
+ for i in xrange (section_count ):
37
+ curOffset = section_info_offset + 8 * i
38
+
39
+ offset = (struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]) & ~ 1 # remove bit 0 (exec bit)
40
+ size = struct .unpack (">L" , file_data [curOffset + 0x4 :curOffset + 0x8 ])[0 ]
41
+
42
+ sections .append ([offset , size ])
43
+
44
+ print str (section_count ) + " sections"
45
+
46
+ print sections
47
+
48
+ for i in xrange (import_size / 8 ):
49
+ curOffset = import_offset + 8 * i
50
+
51
+ id = struct .unpack (">L" , file_data [curOffset :curOffset + 0x4 ])[0 ]
52
+ offset = struct .unpack (">L" , file_data [curOffset + 0x4 :curOffset + 0x8 ])[0 ]
53
+
54
+ imports .append ([id , offset ])
55
+
56
+ print str (import_size / 8 ) + " import lists"
57
+
58
+ print imports
59
+
60
+
61
+ for import_entry in imports :
62
+ curOffset = import_entry [1 ] # offset
63
+ if 1 : #relID == import_entry[0] # self-relocations / or others apparently cause they only do it for fancy import entries.
64
+ curRelOffset = 0
65
+ curRelSection = 0
66
+ while 1 :
67
+ curRelOffset += struct .unpack (">H" , file_data [curOffset :curOffset + 0x2 ])[0 ] # add offset
68
+ operation = struct .unpack (">B" , file_data [curOffset + 0x2 :curOffset + 0x3 ])[0 ]
69
+ targetSection = struct .unpack (">B" , file_data [curOffset + 0x3 :curOffset + 0x4 ])[0 ]
70
+ addend = struct .unpack (">L" , file_data [curOffset + 0x4 :curOffset + 0x8 ])[0 ]
71
+ curOffset += 8
72
+
73
+ print "Processing import entry: " + format (curRelOffset , "x" ) + " / " + format (operation , "x" ) + " / " + format (targetSection , "x" ) + " / " + format (addend , "x" )
74
+
75
+ effectiveOffset = sections [curRelSection ][0 ] + curRelOffset
76
+ if relID == import_entry [0 ]:
77
+ targetAddress = sections [targetSection ][0 ] + addend + baseAddress
78
+ else :
79
+ targetAddress = addend
80
+
81
+ print format (effectiveOffset , "x" ) + " / " + format (targetAddress , "x" )
82
+
83
+ #if operation == 0 or operation == 201: # R_PPC_NONE || R_DOLPHIN_NOP
84
+ # dummy = 0
85
+ if operation == 202 : # R_DOLPHIN_SECTION
86
+ curRelSection = targetSection
87
+ curRelOffset = 0
88
+ elif operation == 1 : # R_PPC_ADDR32
89
+ struct .pack_into (">L" , file_data , effectiveOffset , targetAddress )
90
+ elif operation == 4 : # R_PPC_ADDR16_LO
91
+ struct .pack_into (">H" , file_data , effectiveOffset , targetAddress & 0xFFFF )
92
+ elif operation == 6 : # R_PPC_ADDR16_HA
93
+ if (targetAddress & 0x8000 ) == 0x8000 :
94
+ targetAddress += 0x00010000
95
+
96
+ struct .pack_into (">H" , file_data , effectiveOffset , (targetAddress >> 16 ) & 0xFFFF )
97
+ elif operation == 10 : # R_PPC_REL24
98
+ value = addend
99
+ value -= (effectiveOffset + baseAddress )
100
+ orig = struct .unpack (">L" , file_data [effectiveOffset :effectiveOffset + 0x4 ])[0 ]
101
+ orig &= 0xFC000003
102
+ orig |= value & 0x03FFFFFC
103
+ struct .pack_into (">L" , file_data , effectiveOffset , orig )
104
+ elif operation == 203 : # R_DOLPHIN_END
105
+ break
106
+ else :
107
+ print "Unknown relocation operation " + format (opcode , "x" )
108
+
109
+ output_data = str (bytearray (file_data ))
110
+
111
+ filename_out = filename_in + ".linked"
112
+ output = open (filename_out , "wb" )
113
+ output .write (output_data )
114
+ output .close ()
0 commit comments