Index: emcore/trunk/tools/misc.py |
— | — | @@ -284,6 +284,22 @@ |
285 | 285 | thread = scheduler_thread()._to_bunch()
|
286 | 286 | thread.name = "[Invalid Thread 0x%08X]" % address
|
287 | 287 | return thread
|
| 288 | +
|
| 289 | +
|
| 290 | +def string_from_image(data, base, ptr, maxlen):
|
| 291 | + if ptr == 0: name = "<NULL>"
|
| 292 | + try:
|
| 293 | + string = ""
|
| 294 | + end = data.find(b"\0", ptr - base, ptr - base + maxlen)
|
| 295 | + if end < 0: return "<BAD_STRING>"
|
| 296 | + else:
|
| 297 | + d = data[ptr - base : end]
|
| 298 | + for i in range(len(d)):
|
| 299 | + byte = ord(d[i : i + 1])
|
| 300 | + if byte < 0x20: return "<BAD_STRING>"
|
| 301 | + else: string = string + chr(byte)
|
| 302 | + except: return "<BAD_PTR>"
|
| 303 | + return string
|
288 | 304 |
|
289 | 305 |
|
290 | 306 | def gethwname(id):
|
— | — | @@ -445,4 +461,5 @@ |
446 | 462 | Returns the major version of python
|
447 | 463 | """
|
448 | 464 | import sys
|
449 | | - return sys.hexversion // 0x1000000 |
\ No newline at end of file |
| 465 | + return sys.hexversion // 0x1000000
|
| 466 | + |
\ No newline at end of file |
Index: emcore/trunk/tools/tlsfanalyze.py |
— | — | @@ -24,7 +24,8 @@ |
25 | 25 |
|
26 | 26 | import sys
|
27 | 27 | import struct
|
28 | | -from misc import ExtendedCStruct
|
| 28 | +from misc import ExtendedCStruct, string_from_image
|
| 29 | +from libemcoredata import scheduler_thread
|
29 | 30 | from ctypes import *
|
30 | 31 |
|
31 | 32 |
|
— | — | @@ -132,13 +133,45 @@ |
133 | 134 | break
|
134 | 135 | blocks.append(prev_addr)
|
135 | 136 | if prev_free:
|
| 137 | + try:
|
| 138 | + nfa = block.get_next_free().get_address()
|
| 139 | + if nfa >= prev_addr and nfa < prev_addr + block.get_size() + 4:
|
| 140 | + print("%08X: Next free block (%08X) lies within the block itself" % (prev_addr, nfa))
|
| 141 | + except: print("%08X: Invalid next free block pointer: %08X" % (prev_addr, block.next_free))
|
| 142 | + try:
|
| 143 | + pfa = block.get_prev_free().get_address()
|
| 144 | + if pfa >= prev_addr and pfa < prev_addr + block.get_size() + 4:
|
| 145 | + print("%08X: Previous free block (%08X) lies within the block itself" % (prev_addr, pfa))
|
| 146 | + except:
|
| 147 | + print("%08X: Invalid previous free block pointer: %08X" % (prev_addr, block.prev_free))
|
136 | 148 | print("%08X: %08X bytes free" % (prev_addr + 4, block.get_size() + 4))
|
137 | 149 | free_blocks.append(prev_addr)
|
138 | 150 | bytes_free = bytes_free + block.get_size() + 4
|
139 | 151 | else:
|
140 | | - owner_address = prev_addr - image_base + block.get_size() - 4
|
| 152 | + owner_address = prev_addr - image_base + block.get_size() + 4
|
141 | 153 | owner = struct.unpack("<I", data[owner_address : owner_address + 4])[0]
|
142 | | - print("%08X: %08X+8 bytes owned by %08X" % (prev_addr + 8, block.get_size() - 4, owner))
|
| 154 | + if (owner & 3) == 0:
|
| 155 | + if (owner & 0xfffc0000) == 0x22000000: name = "<KERNEL_THREAD>"
|
| 156 | + else:
|
| 157 | + try:
|
| 158 | + thread = scheduler_thread(data, image_base, owner & ~3)
|
| 159 | + name = "Thread: " + string_from_image(data, image_base, thread.name, 128)
|
| 160 | + except: name = "<BAD_THREAD>"
|
| 161 | + elif (owner & 3) == 1:
|
| 162 | + try:
|
| 163 | + handle = struct.unpack("<I", data[(owner & ~3) - image_base + 4 : (owner & ~3) - image_base + 8])[0]
|
| 164 | + lib = struct.unpack("<4sI", data[(handle & ~3) - image_base + 4 : (handle & ~3) - image_base + 12])
|
| 165 | + name = "Library: " + lib[0].decode("latin_1") + "_v%d" % lib[1]
|
| 166 | + except: name = "<BAD_LIBRARY>"
|
| 167 | + elif (owner & 3) == 2:
|
| 168 | + if (owner >> 2) == 0: name = "<KERNEL_UNKNOWN>";
|
| 169 | + elif (owner >> 2) == 1: name = "<KERNEL_USB_MONITOR>";
|
| 170 | + elif (owner >> 2) == 2: name = "<KERNEL_FILE_HANDLE>";
|
| 171 | + elif (owner >> 2) == 3: name = "<KERNEL_DIR_HANDLE>";
|
| 172 | + elif (owner >> 2) == 4: name = "<KERNEL_ATA_BBT>";
|
| 173 | + else: name = "<KERNEL_UNKNOWN_TYPE>";
|
| 174 | + else: name = "<UNKNOWN_TYPE>"
|
| 175 | + print("%08X: %08X+8 bytes owned by %08X (%s)" % (prev_addr + 8, block.get_size() - 4, owner, name))
|
143 | 176 | bytes_used = bytes_used + block.get_size() + 4
|
144 | 177 | try: block = block.get_next_phys()
|
145 | 178 | except:
|
— | — | @@ -166,6 +199,7 @@ |
167 | 200 | elif block.is_null():
|
168 | 201 | print("[%d:%d:%08X] Block list is null, but second-level map indicates there are free blocks" % (i, j, ba))
|
169 | 202 | blocks = []
|
| 203 | + prev = None
|
170 | 204 | while not block.is_null():
|
171 | 205 | fatal = False
|
172 | 206 | addr = block.get_address()
|
— | — | @@ -173,6 +207,8 @@ |
174 | 208 | print("[%d:%d:%08X] Detected block loop" % (i, j, addr))
|
175 | 209 | break
|
176 | 210 | blocks.append(addr)
|
| 211 | + size = block.get_size()
|
| 212 | + print("[%d:%d] Block at %08X (%08X bytes)" % (i, j, addr, size + 4))
|
177 | 213 | if not block.is_free():
|
178 | 214 | print("[%d:%d:%08X] Non-free block on free list" % (i, j, addr))
|
179 | 215 | fatal = True
|
— | — | @@ -183,8 +219,6 @@ |
184 | 220 | print("[%d:%d:%08X] Block should have coalesced with next one" % (i, j, addr))
|
185 | 221 | except:
|
186 | 222 | print("Block %08X has invalid size: %08X" % (addr, block.get_size()))
|
187 | | - fatal = True
|
188 | | - size = block.get_size()
|
189 | 223 | if size < block_size_min:
|
190 | 224 | print("[%d:%d:%08X] Block violates minimum size: %d (should be at least %d)" % (i, j, addr, size, block_size_min))
|
191 | 225 | if size > block_size_max:
|
— | — | @@ -209,7 +243,8 @@ |
210 | 244 | if (size & 0x80000000) == 0:
|
211 | 245 | size = size << 1
|
212 | 246 | fl = fl - 1
|
213 | | - sl = (block.get_size() >> (fl - SL_INDEX_COUNT_LOG2 + FL_INDEX_SHIFT - 1)) ^ (1 << SL_INDEX_COUNT_LOG2)
|
| 247 | + size = block.get_size()
|
| 248 | + sl = (size >> (fl - SL_INDEX_COUNT_LOG2 + FL_INDEX_SHIFT - 1)) ^ (1 << SL_INDEX_COUNT_LOG2)
|
214 | 249 | if fl != i or sl != j:
|
215 | 250 | print("Block %08X is in wrong free list: [%d:%d] (should be [%d:%d])" % (addr, i, j, fl, sl))
|
216 | 251 | if free_blocks.count(addr) != 1:
|
— | — | @@ -217,9 +252,28 @@ |
218 | 253 | if handled_blocks.count(addr) > 0:
|
219 | 254 | print("[%d:%d:%08X] Block appears in multiple free lists" % (i, j, addr))
|
220 | 255 | else: handled_blocks.append(addr)
|
| 256 | + try:
|
| 257 | + nfa = block.get_next_free().get_address()
|
| 258 | + if nfa >= addr and nfa < addr + size + 4:
|
| 259 | + print("[%d:%d:%08X] Next free block (%08X) lies within the block itself" % (i, j, addr, nfa))
|
| 260 | + fatal = True
|
| 261 | + except:
|
| 262 | + print("[%d:%d:%08X] Invalid next free block pointer: %08X" % (i, j, addr, block.next_free))
|
| 263 | + fatal = True
|
| 264 | + try:
|
| 265 | + pfa = block.get_prev_free().get_address()
|
| 266 | + if pfa >= addr and pfa < addr + size + 4:
|
| 267 | + print("[%d:%d:%08X] Previous free block (%08X) lies within the block itself" % (i, j, addr, pfa))
|
| 268 | + if prev == None and not block.get_prev_free().is_null():
|
| 269 | + print("[%d:%d:%08X] Previous free block pointer is broken: %08X (should be NULL)" % (i, j, addr, pfa))
|
| 270 | + if prev != None and prev != pfa:
|
| 271 | + print("[%d:%d:%08X] Previous free block pointer is broken: %08X (should be %08X)" % (i, j, addr, pfa, prev))
|
| 272 | + except:
|
| 273 | + print("[%d:%d:%08X] Invalid previous free block pointer: %08X" % (i, j, addr, block.prev_free))
|
221 | 274 | if fatal:
|
222 | 275 | print("Fatal error in block chain, continuing with next chain")
|
223 | 276 | break
|
| 277 | + prev = addr
|
224 | 278 | block = block.get_next_free()
|
225 | 279 |
|
226 | 280 | for addr in free_blocks:
|