Subversion Repositories freemyipod

Rev

Rev 811 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 811 Rev 816
Line 22... Line 22...
22
#
22
#
23
 
23
 
24
 
24
 
25
import sys
25
import sys
26
import struct
26
import struct
27
from misc import ExtendedCStruct
27
from misc import ExtendedCStruct, string_from_image
-
 
28
from libemcoredata import scheduler_thread
28
from ctypes import *
29
from ctypes import *
29
 
30
 
30
 
31
 
31
def usage():
32
def usage():
32
  print("Usage: %s <image> [image_base] [tlsf_pool] [SL_INDEX_COUNT_LOG2] [FL_INDEX_MAX]" % (sys.argv[0]))
33
  print("Usage: %s <image> [image_base] [tlsf_pool] [SL_INDEX_COUNT_LOG2] [FL_INDEX_MAX]" % (sys.argv[0]))
Line 130... Line 131...
130
  if blocks.count(prev_addr) > 0:
131
  if blocks.count(prev_addr) > 0:
131
    print("Block loop detected at %08X" % (prev_addr))
132
    print("Block loop detected at %08X" % (prev_addr))
132
    break
133
    break
133
  blocks.append(prev_addr)
134
  blocks.append(prev_addr)
134
  if prev_free:
135
  if prev_free:
-
 
136
    try:
-
 
137
      nfa = block.get_next_free().get_address()
-
 
138
      if nfa >= prev_addr and nfa < prev_addr + block.get_size() + 4:
-
 
139
        print("%08X: Next free block (%08X) lies within the block itself" % (prev_addr, nfa))
-
 
140
    except: print("%08X: Invalid next free block pointer: %08X" % (prev_addr, block.next_free))
-
 
141
    try:
-
 
142
      pfa = block.get_prev_free().get_address()
-
 
143
      if pfa >= prev_addr and pfa < prev_addr + block.get_size() + 4:
-
 
144
        print("%08X: Previous free block (%08X) lies within the block itself" % (prev_addr, pfa))
-
 
145
    except:
-
 
146
      print("%08X: Invalid previous free block pointer: %08X" % (prev_addr, block.prev_free))
135
    print("%08X: %08X bytes free" % (prev_addr + 4, block.get_size() + 4))
147
    print("%08X: %08X bytes free" % (prev_addr + 4, block.get_size() + 4))
136
    free_blocks.append(prev_addr)
148
    free_blocks.append(prev_addr)
137
    bytes_free = bytes_free + block.get_size() + 4
149
    bytes_free = bytes_free + block.get_size() + 4
138
  else:
150
  else:
139
    owner_address = prev_addr - image_base + block.get_size() - 4
151
    owner_address = prev_addr - image_base + block.get_size() + 4
140
    owner = struct.unpack("<I", data[owner_address : owner_address + 4])[0]
152
    owner = struct.unpack("<I", data[owner_address : owner_address + 4])[0]
-
 
153
    if (owner & 3) == 0:
-
 
154
      if (owner & 0xfffc0000) == 0x22000000: name = "<KERNEL_THREAD>"
-
 
155
      else:
-
 
156
        try:
-
 
157
          thread = scheduler_thread(data, image_base, owner & ~3)
-
 
158
          name = "Thread: " + string_from_image(data, image_base, thread.name, 128)
-
 
159
        except: name = "<BAD_THREAD>"
-
 
160
    elif (owner & 3) == 1:
-
 
161
      try:
-
 
162
        handle = struct.unpack("<I", data[(owner & ~3) - image_base + 4 : (owner & ~3) - image_base + 8])[0]
-
 
163
        lib = struct.unpack("<4sI", data[(handle & ~3) - image_base + 4 : (handle & ~3) - image_base + 12])
-
 
164
        name = "Library: " + lib[0].decode("latin_1") + "_v%d" % lib[1]
-
 
165
      except: name = "<BAD_LIBRARY>"
-
 
166
    elif (owner & 3) == 2:
-
 
167
      if (owner >> 2) == 0: name = "<KERNEL_UNKNOWN>";
-
 
168
      elif (owner >> 2) == 1: name = "<KERNEL_USB_MONITOR>";
-
 
169
      elif (owner >> 2) == 2: name = "<KERNEL_FILE_HANDLE>";
-
 
170
      elif (owner >> 2) == 3: name = "<KERNEL_DIR_HANDLE>";
-
 
171
      elif (owner >> 2) == 4: name = "<KERNEL_ATA_BBT>";
-
 
172
      else: name = "<KERNEL_UNKNOWN_TYPE>";
-
 
173
    else: name = "<UNKNOWN_TYPE>"
141
    print("%08X: %08X+8 bytes owned by %08X" % (prev_addr + 8, block.get_size() - 4, owner))
174
    print("%08X: %08X+8 bytes owned by %08X (%s)" % (prev_addr + 8, block.get_size() - 4, owner, name))
142
    bytes_used = bytes_used + block.get_size() + 4
175
    bytes_used = bytes_used + block.get_size() + 4
143
  try: block = block.get_next_phys()
176
  try: block = block.get_next_phys()
144
  except:
177
  except:
145
    print("Block %08X has invalid size: %08X" % (prev_addr, block.get_size()))
178
    print("Block %08X has invalid size: %08X" % (prev_addr, block.get_size()))
146
    print("Fatal error in block chain, continuing with map check")
179
    print("Fatal error in block chain, continuing with map check")
Line 164... Line 197...
164
        print("[%d:%d:%08X] Block list must be null, but isn't" % (i, j, ba))
197
        print("[%d:%d:%08X] Block list must be null, but isn't" % (i, j, ba))
165
      continue
198
      continue
166
    elif block.is_null():
199
    elif block.is_null():
167
      print("[%d:%d:%08X] Block list is null, but second-level map indicates there are free blocks" % (i, j, ba))
200
      print("[%d:%d:%08X] Block list is null, but second-level map indicates there are free blocks" % (i, j, ba))
168
    blocks = []
201
    blocks = []
-
 
202
    prev = None
169
    while not block.is_null():
203
    while not block.is_null():
170
      fatal = False
204
      fatal = False
171
      addr = block.get_address()
205
      addr = block.get_address()
172
      if blocks.count(addr) > 0:
206
      if blocks.count(addr) > 0:
173
        print("[%d:%d:%08X] Detected block loop" % (i, j, addr))
207
        print("[%d:%d:%08X] Detected block loop" % (i, j, addr))
174
        break
208
        break
175
      blocks.append(addr)
209
      blocks.append(addr)
-
 
210
      size = block.get_size()
-
 
211
      print("[%d:%d] Block at %08X (%08X bytes)" % (i, j, addr, size + 4))
176
      if not block.is_free():
212
      if not block.is_free():
177
        print("[%d:%d:%08X] Non-free block on free list" % (i, j, addr))
213
        print("[%d:%d:%08X] Non-free block on free list" % (i, j, addr))
178
        fatal = True
214
        fatal = True
179
      if block.is_prev_free():
215
      if block.is_prev_free():
180
        print("[%d:%d:%08X] Block should have coalesced with previous one" % (i, j, addr))
216
        print("[%d:%d:%08X] Block should have coalesced with previous one" % (i, j, addr))
181
      try:
217
      try:
182
        if block.get_next_phys().is_free():
218
        if block.get_next_phys().is_free():
183
          print("[%d:%d:%08X] Block should have coalesced with next one" % (i, j, addr))
219
          print("[%d:%d:%08X] Block should have coalesced with next one" % (i, j, addr))
184
      except:
220
      except:
185
        print("Block %08X has invalid size: %08X" % (addr, block.get_size()))
221
        print("Block %08X has invalid size: %08X" % (addr, block.get_size()))
186
        fatal = True
-
 
187
      size = block.get_size()
-
 
188
      if size < block_size_min:
222
      if size < block_size_min:
189
        print("[%d:%d:%08X] Block violates minimum size: %d (should be at least %d)" % (i, j, addr, size, block_size_min))
223
        print("[%d:%d:%08X] Block violates minimum size: %d (should be at least %d)" % (i, j, addr, size, block_size_min))
190
      if size > block_size_max:
224
      if size > block_size_max:
191
        print("[%d:%d:%08X] Block violates maximum size: %d (should be at most %d)" % (i, j, addr, size, block_size_max))
225
        print("[%d:%d:%08X] Block violates maximum size: %d (should be at most %d)" % (i, j, addr, size, block_size_max))
192
      if size < SMALL_BLOCK_SIZE:
226
      if size < SMALL_BLOCK_SIZE:
Line 207... Line 241...
207
          size = size << 2
241
          size = size << 2
208
          fl = fl - 2
242
          fl = fl - 2
209
        if (size & 0x80000000) == 0:
243
        if (size & 0x80000000) == 0:
210
          size = size << 1
244
          size = size << 1
211
          fl = fl - 1
245
          fl = fl - 1
-
 
246
        size = block.get_size()
212
        sl = (block.get_size() >> (fl - SL_INDEX_COUNT_LOG2 + FL_INDEX_SHIFT - 1)) ^ (1 << SL_INDEX_COUNT_LOG2)
247
        sl = (size >> (fl - SL_INDEX_COUNT_LOG2 + FL_INDEX_SHIFT - 1)) ^ (1 << SL_INDEX_COUNT_LOG2)
213
      if fl != i or sl != j:
248
      if fl != i or sl != j:
214
        print("Block %08X is in wrong free list: [%d:%d] (should be [%d:%d])" % (addr, i, j, fl, sl))
249
        print("Block %08X is in wrong free list: [%d:%d] (should be [%d:%d])" % (addr, i, j, fl, sl))
215
      if free_blocks.count(addr) != 1:
250
      if free_blocks.count(addr) != 1:
216
        print("[%d:%d:%08X] Block is in free list, but was not found in pool" % (i, j, addr))
251
        print("[%d:%d:%08X] Block is in free list, but was not found in pool" % (i, j, addr))
217
      if handled_blocks.count(addr) > 0:
252
      if handled_blocks.count(addr) > 0:
218
        print("[%d:%d:%08X] Block appears in multiple free lists" % (i, j, addr))
253
        print("[%d:%d:%08X] Block appears in multiple free lists" % (i, j, addr))
219
      else: handled_blocks.append(addr)
254
      else: handled_blocks.append(addr)
-
 
255
      try:
-
 
256
        nfa = block.get_next_free().get_address()
-
 
257
        if nfa >= addr and nfa < addr + size + 4:
-
 
258
          print("[%d:%d:%08X] Next free block (%08X) lies within the block itself" % (i, j, addr, nfa))
-
 
259
          fatal = True
-
 
260
      except:
-
 
261
        print("[%d:%d:%08X] Invalid next free block pointer: %08X" % (i, j, addr, block.next_free))
-
 
262
        fatal = True
-
 
263
      try:
-
 
264
        pfa = block.get_prev_free().get_address()
-
 
265
        if pfa >= addr and pfa < addr + size + 4:
-
 
266
          print("[%d:%d:%08X] Previous free block (%08X) lies within the block itself" % (i, j, addr, pfa))
-
 
267
        if prev == None and not block.get_prev_free().is_null():
-
 
268
          print("[%d:%d:%08X] Previous free block pointer is broken: %08X (should be NULL)" % (i, j, addr, pfa))
-
 
269
        if prev != None and prev != pfa:
-
 
270
          print("[%d:%d:%08X] Previous free block pointer is broken: %08X (should be %08X)" % (i, j, addr, pfa, prev))
-
 
271
      except:
-
 
272
        print("[%d:%d:%08X] Invalid previous free block pointer: %08X" % (i, j, addr, block.prev_free))
220
      if fatal:
273
      if fatal:
221
        print("Fatal error in block chain, continuing with next chain")
274
        print("Fatal error in block chain, continuing with next chain")
222
        break
275
        break
-
 
276
      prev = addr
223
      block = block.get_next_free()
277
      block = block.get_next_free()
224
      
278
      
225
for addr in free_blocks:
279
for addr in free_blocks:
226
  if handled_blocks.count(addr) != 1:
280
  if handled_blocks.count(addr) != 1:
227
    print("Free block %08X does not appear in any free list" % (addr))
281
    print("Free block %08X does not appear in any free list" % (addr))