1from xnu import * 2from utils import * 3from process import * 4from pmap import * 5import struct 6 7def GetBinaryNameForPC(pc_val, user_lib_info = None): 8 """ find the binary in user_lib_info that the passed pc_val falls in range of. 9 params: 10 pc_val : int - integer form of the pc address 11 user_lib_info: [] of [] which hold start, end, binary name 12 returns: 13 str - Name of binary or "unknown" if not found. 14 """ 15 retval = "unknown" 16 if not user_lib_info: 17 return retval 18 matches = [] 19 for info in user_lib_info: 20 if pc_val >= info[0] and pc_val <= info[1]: 21 matches.append((pc_val - info[0], info[2])) 22 matches.sort() 23 if matches: 24 retval = matches[0][1] 25 return retval 26 27def ShowX86UserStack(thread, user_lib_info = None): 28 """ Display user space stack frame and pc addresses. 29 params: 30 thread: obj referencing thread value 31 returns: 32 Nothing 33 """ 34 iss = Cast(thread.machine.iss, 'x86_saved_state_t *') 35 abi = int(iss.flavor) 36 user_ip = 0 37 user_frame = 0 38 user_abi_ret_offset = 0 39 if abi == 0xf: 40 debuglog("User process is 64 bit") 41 user_ip = iss.uss.ss_64.isf.rip 42 user_frame = iss.uss.ss_64.rbp 43 user_abi_ret_offset = 8 44 user_abi_type = "uint64_t" 45 else: 46 debuglog("user process is 32 bit") 47 user_ip = iss.uss.ss_32.eip 48 user_frame = iss.uss.ss_32.ebp 49 user_abi_ret_offset = 4 50 user_abi_type = "uint32_t" 51 52 if user_ip == 0: 53 print "This activation does not appear to have a valid user context." 54 return False 55 56 cur_ip = user_ip 57 cur_frame = user_frame 58 debuglog("ip= 0x%x , fr = 0x%x " % (cur_ip, cur_frame)) 59 60 frameformat = "{0:d} FP: 0x{1:x} PC: 0x{2:x}" 61 if user_lib_info is not None: 62 frameformat = "{0:d} {3: <30s} 0x{2:x}" 63 print frameformat.format(0, cur_frame, cur_ip, GetBinaryNameForPC(cur_ip, user_lib_info)) 64 65 print kern.Symbolicate(cur_ip) 66 67 frameno = 0 68 while True: 69 frameno = frameno + 1 70 frame = GetUserDataAsString(thread.task, unsigned(cur_frame), user_abi_ret_offset*2) 71 cur_ip = _ExtractDataFromString(frame, user_abi_ret_offset, user_abi_type) 72 cur_frame = _ExtractDataFromString(frame, 0, user_abi_type) 73 if not cur_frame or cur_frame == 0x0000000800000008: 74 break 75 print frameformat.format(frameno, cur_frame, cur_ip, GetBinaryNameForPC(cur_ip, user_lib_info)) 76 print kern.Symbolicate(cur_ip) 77 return 78 79def _PrintARMUserStack(task, cur_pc, cur_fp, framesize, frametype, frameformat, user_lib_info=None): 80 if cur_pc == 0: 81 "No valid user context for this activation." 82 return 83 frameno = 0 84 print frameformat.format(frameno, cur_fp, cur_pc, GetBinaryNameForPC(cur_pc, user_lib_info)) 85 while True: 86 frameno = frameno + 1 87 frame = GetUserDataAsString(task, cur_fp, framesize) 88 cur_fp = _ExtractDataFromString(frame, 0, frametype) 89 cur_pc = _ExtractDataFromString(frame, (framesize / 2), frametype) 90 if not cur_fp: 91 break 92 print frameformat.format(frameno, cur_fp, cur_pc, GetBinaryNameForPC(cur_pc, user_lib_info)) 93 94def ShowARMUserStack(thread, user_lib_info = None): 95 cur_pc = unsigned(thread.machine.PcbData.pc) 96 cur_fp = unsigned(thread.machine.PcbData.r[7]) 97 frameformat = "{0:>2d} FP: 0x{1:x} PC: 0x{2:x}" 98 if user_lib_info is not None: 99 frameformat = "{0:>2d} {3: <30s} 0x{2:0>8x}" 100 framesize = 8 101 frametype = "uint32_t" 102 _PrintARMUserStack(thread.task, cur_pc, cur_fp, framesize, frametype, frameformat, user_lib_info=user_lib_info) 103 104def ShowARM64UserStack(thread, user_lib_info = None): 105 SAVED_STATE_FLAVOR_ARM=20 106 SAVED_STATE_FLAVOR_ARM64=21 107 upcb = thread.machine.upcb 108 flavor = upcb.ash.flavor 109 frameformat = "{0:>2d} FP: 0x{1:x} PC: 0x{2:x}" 110 if flavor == SAVED_STATE_FLAVOR_ARM64: 111 cur_pc = unsigned(upcb.uss.ss_64.pc) 112 cur_fp = unsigned(upcb.uss.ss_64.fp) 113 if user_lib_info is not None: 114 frameformat = "{0:>2d} {3: <30s} 0x{2:x}" 115 framesize = 16 116 frametype = "uint64_t" 117 elif flavor == SAVED_STATE_FLAVOR_ARM: 118 cur_pc = unsigned(upcb.uss.ss_32.pc) 119 cur_fp = unsigned(upcb.uss.ss_32.r[7]) 120 if user_lib_info is not None: 121 frameformat = "{0:>2d}: {3: <30s} 0x{2:x}" 122 framesize = 8 123 frametype = "uint32_t" 124 else: 125 raise RuntimeError("Thread {0} has an invalid flavor {1}".format(unsigned(thread), flavor)) 126 127 _PrintARMUserStack(thread.task, cur_pc, cur_fp, framesize, frametype, frameformat, user_lib_info=user_lib_info) 128 129 130@lldb_command('showthreaduserstack') 131def ShowThreadUserStack(cmd_args=None): 132 """ Show user stack for a given thread. 133 Syntax: (lldb) showthreaduserstack <thread_ptr> 134 """ 135 if not cmd_args: 136 raise ArgumentError("Insufficient arguments") 137 138 thread = kern.GetValueFromAddress(ArgumentStringToInt(cmd_args[0]), 'thread *') 139 if kern.arch == "x86_64": 140 ShowX86UserStack(thread) 141 elif kern.arch == "arm": 142 ShowARMUserStack(thread) 143 elif kern.arch == "arm64": 144 ShowARM64UserStack(thread) 145 return True 146 147@lldb_command('printuserdata','X') 148def PrintUserspaceData(cmd_args=None, cmd_options={}): 149 """ Read userspace data for given task and print based on format provided. 150 Syntax: (lldb) printuserdata <task_t> <uspace_address> <format_specifier> 151 params: 152 <task_t> : pointer to task 153 <uspace_address> : address to user space memory 154 <format_specifier> : String representation for processing the data and printing it. 155 e.g Q -> unsigned long long, q-> long long, I-> unsigned int, i->int 156 options: 157 -X : print all values in hex. 158 """ 159 160 if not cmd_args or len(cmd_args) < 3: 161 raise ArgumentError("Insufficient arguments") 162 task = kern.GetValueFromAddress(cmd_args[0], 'task *') 163 uspace_addr = ArgumentStringToInt(cmd_args[1]) 164 format_specifier_str = cmd_args[2] 165 user_data_len = 0 166 try: 167 user_data_len = struct.calcsize(format_specifier_str) 168 except Exception, e: 169 raise ArgumentError("Invalid format specifier provided.") 170 171 user_data_string = GetUserDataAsString(task, uspace_addr, user_data_len) 172 if not user_data_string: 173 print "Could not read any data from userspace address." 174 return False 175 upacked_data = struct.unpack(format_specifier_str, user_data_string) 176 for i in range(len(upacked_data)): 177 if "-X" in cmd_options: 178 print "%d: " % i + hex(upacked_data[i]) 179 else: 180 print "%d: " % i + str(upacked_data[i]) 181 182 return True 183 184@lldb_command('showtaskuserstacks') 185def ShowTaskUserStacks(cmd_args=None): 186 """ Print out the user stack for each thread in a task, followed by the user libraries. 187 Syntax: (lldb) showtaskuserstacks <task_t> 188 The format is compatible with CrashTracer. You can also use the speedtracer plugin as follows 189 (lldb) showtaskuserstacks <task_t> -p speedtracer 190 191 Note: the address ranges are approximations. Also the list may not be completely accurate. This command expects memory read failures 192 and hence will skip a library if unable to read information. Please use your good judgement and not take the output as accurate 193 """ 194 if not cmd_args: 195 raise ArgumentError("Insufficient arguments") 196 197 task = kern.GetValueFromAddress(cmd_args[0], 'task *') 198 #print GetTaskSummary.header + " " + GetProcSummary.header 199 pval = Cast(task.bsd_info, 'proc *') 200 #print GetTaskSummary(task) + " " + GetProcSummary(pval) + "\n \n" 201 crash_report_format_string = """\ 202Process: {pid: <10d} 203Path: {path: <50s} 204Identifier: {pname: <30s} 205Version: ??? (???) 206Code Type: {parch: <20s} 207Parent Process: {ppname: >20s}[{ppid:d}] 208 209Date/Time: {timest:s}.000 -0800 210OS Version: {osversion: <20s} 211Report Version: 8 212 213Exception Type: n/a 214Exception Codes: n/a 215Crashed Thread: 0 216 217Application Specific Information: 218Synthetic crash log generated from Kernel userstacks 219 220""" 221 user_lib_rex = re.compile("([0-9a-fx]+)\s-\s([0-9a-fx]+)\s+(.*?)\s", re.IGNORECASE|re.MULTILINE) 222 from datetime import datetime 223 ts = datetime.fromtimestamp(int(pval.p_start.tv_sec)) 224 date_string = ts.strftime('%Y-%m-%d %H:%M:%S') 225 is_64 = False 226 if pval.p_flag & 0x4 : 227 is_64 = True 228 229 parch_s = "" 230 if kern.arch == "x86_64" or kern.arch == "i386": 231 osversion = "Mac OS X 10.8" 232 parch_s = "I386 (32 bit)" 233 if is_64: 234 parch_s = "X86-64 (Native)" 235 else: 236 parch_s = kern.arch 237 osversion = "iOS" 238 osversion += " ({:s})".format(kern.globals.osversion) 239 print crash_report_format_string.format(pid = pval.p_pid, 240 pname = pval.p_comm, 241 path = pval.p_comm, 242 ppid = pval.p_ppid, 243 ppname = GetProcNameForPid(pval.p_ppid), 244 timest = date_string, 245 parch = parch_s, 246 osversion = osversion 247 248 ) 249 print "Binary Images:" 250 ShowTaskUserLibraries([hex(task)]) 251 usertask_lib_info = [] # will host [startaddr, endaddr, lib_name] entries 252 for entry in ShowTaskUserLibraries.found_images: 253 #print "processing line %s" % line 254 arr = user_lib_rex.findall(entry[3]) 255 #print "%r" % arr 256 if len(arr) == 0 : 257 continue 258 usertask_lib_info.append([int(arr[0][0],16), int(arr[0][1],16), str(arr[0][2]).strip()]) 259 260 printthread_user_stack_ptr = ShowX86UserStack 261 if kern.arch == "arm": 262 printthread_user_stack_ptr = ShowARMUserStack 263 elif kern.arch =="arm64": 264 printthread_user_stack_ptr = ShowARM64UserStack 265 266 counter = 0 267 for thval in IterateQueue(task.threads, 'thread *', 'task_threads'): 268 print "\nThread {0:d} name:0x{1:x}\nThread {0:d}:".format(counter, thval) 269 counter += 1 270 try: 271 printthread_user_stack_ptr(thval, usertask_lib_info) 272 except Exception as exc_err: 273 print "Failed to show user stack for thread 0x{0:x}".format(thval) 274 if config['debug']: 275 raise exc_err 276 else: 277 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace." 278 return 279 280 281def GetUserDataAsString(task, addr, size): 282 """ Get data from task's address space as a string of bytes 283 params: 284 task: task object from which to extract information 285 addr: int - start address to get data from. 286 size: int - no of bytes to read. 287 returns: 288 str - a stream of bytes. Empty string if read fails. 289 """ 290 err = lldb.SBError() 291 if GetConnectionProtocol() == "kdp": 292 kdp_pmap_addr = unsigned(addressof(kern.globals.kdp_pmap)) 293 if not WriteInt64ToMemoryAddress(unsigned(task.map.pmap), kdp_pmap_addr): 294 debuglog("Failed to write in kdp_pmap from GetUserDataAsString.") 295 return "" 296 content = LazyTarget.GetProcess().ReadMemory(addr, size, err) 297 if not err.Success(): 298 debuglog("Failed to read process memory. Error: " + err.description) 299 return "" 300 if not WriteInt64ToMemoryAddress(0, kdp_pmap_addr): 301 debuglog("Failed to reset in kdp_pmap from GetUserDataAsString.") 302 return "" 303 elif kern.arch in ['arm', 'arm64', 'x86_64'] and long(size) < (2 * kern.globals.page_size): 304 # Without the benefit of a KDP stub on the target, try to 305 # find the user task's physical mapping and memcpy the data. 306 # If it straddles a page boundary, copy in two passes 307 range1_addr = long(addr) 308 range1_size = long(size) 309 if kern.StraddlesPage(range1_addr, range1_size): 310 range2_addr = long(kern.TruncPage(range1_addr + range1_size)) 311 range2_size = long(range1_addr + range1_size - range2_addr) 312 range1_size = long(range2_addr - range1_addr) 313 else: 314 range2_addr = 0 315 range2_size = 0 316 range2_in_kva = 0 317 318 paddr_range1 = PmapWalk(task.map.pmap, range1_addr, vSILENT) 319 if not paddr_range1: 320 debuglog("Not mapped task 0x{:x} address 0x{:x}".format(task, addr)) 321 return "" 322 323 range1_in_kva = kern.PhysToKernelVirt(paddr_range1) 324 content = LazyTarget.GetProcess().ReadMemory(range1_in_kva, range1_size, err) 325 if not err.Success(): 326 raise RuntimeError("Failed to read process memory. Error: " + err.description) 327 328 if range2_addr: 329 paddr_range2 = PmapWalk(task.map.pmap, range2_addr, vSILENT) 330 if not paddr_range2: 331 debuglog("Not mapped task 0x{:x} address 0x{:x}".format(task, addr)) 332 return "" 333 range2_in_kva = kern.PhysToKernelVirt(paddr_range2) 334 content += LazyTarget.GetProcess().ReadMemory(range2_in_kva, range2_size, err) 335 if not err.Success(): 336 raise RuntimeError("Failed to read process memory. Error: " + err.description) 337 else: 338 raise NotImplementedError("GetUserDataAsString does not support this configuration") 339 340 return content 341 342def _ExtractDataFromString(strdata, offset, data_type, length=0): 343 """ Extract specific data from string buffer 344 params: 345 strdata: str - string data give from GetUserDataAsString 346 offset: int - 0 based offset into the data. 347 data_type: str - defines what type to be read as. Supported values are: 348 'uint64_t', 'uint32_t', 'string' 349 length: int - used when data_type=='string' 350 returns 351 None - if extraction failed. 352 obj - based on what is requested in data_type 353 """ 354 unpack_str = "s" 355 if data_type == 'uint64_t': 356 length = 8 357 unpack_str = "Q" 358 elif data_type == "uint32_t": 359 length = 4 360 unpack_str = "I" 361 else: 362 unpack_str= "%ds" % length 363 364 data_len = len(strdata) 365 if offset > data_len or (offset + length) > data_len or offset < 0: 366 debuglog("Invalid arguments to _ExtractDataFromString.") 367 return 0 368 return struct.unpack(unpack_str, strdata[offset:(offset + length)])[0] 369 370def GetPathForImage(task, path_address): 371 """ Maps 32 bytes at a time and packs as string 372 params: 373 task: obj - referencing task to read data from 374 path_address: int - address where the image path is stored 375 returns: 376 str - string path of the file. "" if failed to read. 377 """ 378 done = False 379 retval = "" 380 381 if path_address == 0: 382 done = True 383 384 while not done: 385 path_str_data = GetUserDataAsString(task, path_address, 32) 386 if len(path_str_data) == 0: 387 break 388 i = 0 389 while i < 32: 390 if ord(path_str_data[i]): 391 retval += path_str_data[i] 392 else: 393 break 394 i += 1 395 if i < 32: 396 done = True 397 else: 398 path_address += 32 399 return retval 400 401def GetImageInfo(task, mh_image_address, mh_path_address, approx_end_address=None): 402 """ Print user library informaiton. 403 params: 404 task : obj referencing the task for which Image info printed 405 mh_image_address : int - address which has image info 406 mh_path_address : int - address which holds path name string 407 approx_end_address: int - address which lldbmacros think is end address. 408 returns: 409 str - string representing image info. "" if failure to read data. 410 """ 411 if approx_end_address: 412 image_end_load_address = int(approx_end_address) -1 413 else: 414 image_end_load_address = int(mh_image_address) + 0xffffffff 415 416 print_format = "0x{0:x} - 0x{1:x} {2: <50s} (??? - ???) <{3: <36s}> {4: <50s}" 417 # 32 bytes enough for mach_header/mach_header_64 418 mh_data = GetUserDataAsString(task, mh_image_address, 32) 419 if len(mh_data) == 0: 420 debuglog("unable to get userdata for task 0x{:x} img_addr 0x{:x} path_address 0x{:x}".format( 421 task, mh_image_address, mh_path_address)) 422 return "" 423 mh_magic = _ExtractDataFromString(mh_data, (4 * 0), "uint32_t") 424 mh_cputype = _ExtractDataFromString(mh_data,(4 * 1), "uint32_t") 425 mh_cpusubtype = _ExtractDataFromString(mh_data,(4 * 2), "uint32_t") 426 mh_filetype = _ExtractDataFromString(mh_data,(4 * 3), "uint32_t") 427 mh_ncmds = _ExtractDataFromString(mh_data,(4 * 4), "uint32_t") 428 mh_sizeofcmds = _ExtractDataFromString(mh_data,(4 * 5), "uint32_t") 429 mh_flags = _ExtractDataFromString(mh_data,(4 * 6), "uint32_t") 430 431 if mh_magic == 0xfeedfacf: 432 mh_64 = True 433 lc_address = mh_image_address + 32 434 else: 435 mh_64 = False 436 lc_address = mh_image_address + 28 437 438 lc_idx = 0 439 uuid_data = 0 440 found_uuid_data = False 441 retval = None 442 while lc_idx < mh_ncmds: 443 # 24 bytes is the size of uuid_command 444 lcmd_data = GetUserDataAsString(task, lc_address, 24) 445 lc_cmd = _ExtractDataFromString(lcmd_data, 4 * 0, "uint32_t") 446 lc_cmd_size = _ExtractDataFromString(lcmd_data, 4 * 1, "uint32_t") 447 lc_data = _ExtractDataFromString(lcmd_data, 4*2, "string", 16) 448 449 uuid_out_string = "" 450 path_out_string = "" 451 452 if lc_cmd == 0x1b: 453 # need to print the uuid now. 454 uuid_data = [ord(x) for x in lc_data] 455 found_uuid_data = True 456 uuid_out_string = "{a[0]:02X}{a[1]:02X}{a[2]:02X}{a[3]:02X}-{a[4]:02X}{a[5]:02X}-{a[6]:02X}{a[7]:02X}-{a[8]:02X}{a[9]:02X}-{a[10]:02X}{a[11]:02X}{a[12]:02X}{a[13]:02X}{a[14]:02X}{a[15]:02X}".format(a=uuid_data) 457 #also print image path 458 path_out_string = GetPathForImage(task, mh_path_address) 459 path_base_name = path_out_string.split("/")[-1] 460 retval = print_format.format(mh_image_address, image_end_load_address, path_base_name, uuid_out_string, path_out_string) 461 elif lc_cmd == 0xe: 462 ShowTaskUserLibraries.exec_load_path = lc_address + _ExtractDataFromString(lcmd_data, 4*2, "uint32_t") 463 debuglog("Found load command to be 0xe for address %s" % hex(ShowTaskUserLibraries.exec_load_path)) 464 lc_address = lc_address + lc_cmd_size 465 lc_idx += 1 466 467 if not found_uuid_data: 468 path_out_string = GetPathForImage(task, mh_path_address) 469 path_base_name = path_out_string.split("/")[-1] 470 uuid_out_string = "" 471 472 retval = print_format.format(mh_image_address, image_end_load_address, path_base_name, uuid_out_string, path_out_string) 473 return retval 474 475@static_var("found_images", []) # holds entries of format (startaddr, endaddr, image_path_addr, infostring) 476@static_var("exec_load_path", 0) 477@lldb_command("showtaskuserlibraries") 478def ShowTaskUserLibraries(cmd_args=None): 479 """ Show binary images known by dyld in target task 480 For a given user task, inspect the dyld shared library state and print information about all Mach-O images. 481 Syntax: (lldb)showtaskuserlibraries <task_t> 482 Note: the address ranges are approximations. Also the list may not be completely accurate. This command expects memory read failures 483 and hence will skip a library if unable to read information. Please use your good judgement and not take the output as accurate 484 """ 485 if not cmd_args: 486 raise ArgumentError("Insufficient arguments") 487 488 #reset the found_images array 489 ShowTaskUserLibraries.found_images = [] 490 491 task = kern.GetValueFromAddress(cmd_args[0], 'task_t') 492 is_task_64 = int(task.t_flags) & 0x1 493 dyld_all_image_infos_address = unsigned(task.all_image_info_addr) 494 debuglog("dyld_all_image_infos_address = %s" % hex(dyld_all_image_infos_address)) 495 496 cur_data_offset = 0 497 if dyld_all_image_infos_address == 0: 498 print "No dyld shared library information available for task" 499 return False 500 501 debuglog("Extracting version information.") 502 vers_info_data = GetUserDataAsString(task, dyld_all_image_infos_address, 112) 503 version = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t") 504 cur_data_offset += 4 505 if version > 14: 506 print "Unknown dyld all_image_infos version number %d" % version 507 image_info_count = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t") 508 debuglog("version = %d count = %d is_task_64 = %s" % (version, image_info_count, repr(is_task_64))) 509 510 ShowTaskUserLibraries.exec_load_path = 0 511 if is_task_64: 512 image_info_size = 24 513 image_info_array_address = _ExtractDataFromString(vers_info_data, 8, "uint64_t") 514 dyld_load_address = _ExtractDataFromString(vers_info_data, 8*4, "uint64_t") 515 dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 8*13, "uint64_t") 516 else: 517 image_info_size = 12 518 image_info_array_address = _ExtractDataFromString(vers_info_data, 4*2, "uint32_t") 519 dyld_load_address = _ExtractDataFromString(vers_info_data, 4*5, "uint32_t") 520 dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 4*14, "uint32_t") 521 # Account for ASLR slide before dyld can fix the structure 522 dyld_load_address = dyld_load_address + (dyld_all_image_infos_address - dyld_all_image_infos_address_from_struct) 523 524 i = 0 525 image_info_list = [] 526 while i < image_info_count: 527 image_info_address = image_info_array_address + i * image_info_size 528 debuglog("i = %d, image_info_address = %s, image_info_size = %d" % (i, hex(image_info_address), image_info_size)) 529 n_im_info_addr = None 530 img_data = "" 531 try: 532 img_data = GetUserDataAsString(task, image_info_address, image_info_size) 533 except Exception, e: 534 debuglog("Failed to read user data for task 0x{:x} addr 0x{:x}, exception {:s}".format(task, image_info_address, str(e))) 535 pass 536 537 if is_task_64: 538 image_info_addr = _ExtractDataFromString(img_data, 0, "uint64_t") 539 image_info_path = _ExtractDataFromString(img_data, 8, "uint64_t") 540 else: 541 image_info_addr = _ExtractDataFromString(img_data, 0, "uint32_t") 542 image_info_path = _ExtractDataFromString(img_data, 4, "uint32_t") 543 544 if image_info_addr : 545 debuglog("Found image: image_info_addr = %s, image_info_path= %s" % (hex(image_info_addr), hex(image_info_path))) 546 image_info_list.append((image_info_addr, image_info_path)) 547 i += 1 548 549 image_info_list.sort() 550 num_images_found = len(image_info_list) 551 552 for ii in range(num_images_found): 553 n_im_info_addr = dyld_load_address 554 if ii + 1 < num_images_found: 555 n_im_info_addr = image_info_list[ii+1][0] 556 557 image_info_addr = image_info_list[ii][0] 558 image_info_path = image_info_list[ii][1] 559 try: 560 image_print_s = GetImageInfo(task, image_info_addr, image_info_path, approx_end_address=n_im_info_addr) 561 if len(image_print_s) > 0: 562 print image_print_s 563 ShowTaskUserLibraries.found_images.append((image_info_addr, n_im_info_addr, image_info_path, image_print_s)) 564 else: 565 debuglog("Failed to print image info for task 0x{:x} image_info 0x{:x}".format(task, image_info_addr)) 566 except Exception,e: 567 if config['debug']: 568 raise e 569 570 # load_path might get set when the main executable is processed. 571 if ShowTaskUserLibraries.exec_load_path != 0: 572 debuglog("main executable load_path is set.") 573 image_print_s = GetImageInfo(task, dyld_load_address, ShowTaskUserLibraries.exec_load_path) 574 if len(image_print_s) > 0: 575 print image_print_s 576 ShowTaskUserLibraries.found_images.append((dyld_load_address, dyld_load_address + 0xffffffff, 577 ShowTaskUserLibraries.exec_load_path, image_print_s)) 578 else: 579 debuglog("Failed to print image for main executable for task 0x{:x} dyld_load_addr 0x{:x}".format(task, dyld_load_address)) 580 else: 581 debuglog("Falling back to vm entry method for finding executable load address") 582 print "# NOTE: Failed to find executable using all_image_infos. Using fuzzy match to find best possible load address for executable." 583 ShowTaskLoadInfo([cmd_args[0]]) 584 return 585 586@lldb_command("showtaskuserdyldinfo") 587def ShowTaskUserDyldInfo(cmd_args=None): 588 """ Inspect the dyld global info for the given user task & print out all fields including error messages 589 Syntax: (lldb)showtaskuserdyldinfo <task_t> 590 """ 591 if cmd_args == None or len(cmd_args) < 1: 592 print "No arguments passed" 593 print ShowTaskUserDyldInfo.__doc__.strip() 594 return 595 596 out_str = "" 597 task = kern.GetValueFromAddress(cmd_args[0], 'task_t') 598 is_task_64 = int(task.t_flags) & 0x1 599 dyld_all_image_infos_address = unsigned(task.all_image_info_addr) 600 if dyld_all_image_infos_address == 0: 601 print "No dyld shared library information available for task" 602 return False 603 vers_info_data = GetUserDataAsString(task, dyld_all_image_infos_address, 112) 604 dyld_all_image_infos_version = _ExtractDataFromString(vers_info_data, 0, "uint32_t") 605 if dyld_all_image_infos_version > 14: 606 out_str += "Unknown dyld all_image_infos version number %d" % dyld_all_image_infos_version 607 608 # Find fields by byte offset. We assume at least version 9 is supported 609 if is_task_64: 610 dyld_all_image_infos_infoArrayCount = _ExtractDataFromString(vers_info_data, 4, "uint32_t") 611 dyld_all_image_infos_infoArray = _ExtractDataFromString(vers_info_data, 8, "uint64_t") 612 dyld_all_image_infos_notification = _ExtractDataFromString(vers_info_data, 16, "uint64_t") 613 dyld_all_image_infos_processDetachedFromSharedRegion = _ExtractDataFromString(vers_info_data, 24, "string") 614 dyld_all_image_infos_libSystemInitialized = _ExtractDataFromString(vers_info_data, 25, "string") 615 dyld_all_image_infos_dyldImageLoadAddress = _ExtractDataFromString(vers_info_data, 32, "uint64_t") 616 dyld_all_image_infos_jitInfo = _ExtractDataFromString(vers_info_data, 40, "uint64_t") 617 dyld_all_image_infos_dyldVersion = _ExtractDataFromString(vers_info_data, 48, "uint64_t") 618 dyld_all_image_infos_errorMessage = _ExtractDataFromString(vers_info_data, 56, "uint64_t") 619 dyld_all_image_infos_terminationFlags = _ExtractDataFromString(vers_info_data, 64, "uint64_t") 620 dyld_all_image_infos_coreSymbolicationShmPage = _ExtractDataFromString(vers_info_data, 72, "uint64_t") 621 dyld_all_image_infos_systemOrderFlag = _ExtractDataFromString(vers_info_data, 80, "uint64_t") 622 dyld_all_image_infos_uuidArrayCount = _ExtractDataFromString(vers_info_data, 88, "uint64_t") 623 dyld_all_image_infos_uuidArray = _ExtractDataFromString(vers_info_data, 96, "uint64_t") 624 dyld_all_image_infos_dyldAllImageInfosAddress = _ExtractDataFromString(vers_info_data, 104, "uint64_t") 625 else: 626 dyld_all_image_infos_infoArrayCount = _ExtractDataFromString(vers_info_data, 4, "uint32_t") 627 dyld_all_image_infos_infoArray = _ExtractDataFromString(vers_info_data, 8, "uint32_t") 628 dyld_all_image_infos_notification = _ExtractDataFromString(vers_info_data, 12, "uint32_t") 629 dyld_all_image_infos_processDetachedFromSharedRegion = _ExtractDataFromString(vers_info_data, 16, "string") 630 dyld_all_image_infos_libSystemInitialized = _ExtractDataFromString(vers_info_data, 17, "string") 631 dyld_all_image_infos_dyldImageLoadAddress = _ExtractDataFromString(vers_info_data, 20, "uint32_t") 632 dyld_all_image_infos_jitInfo = _ExtractDataFromString(vers_info_data, 24, "uint32_t") 633 dyld_all_image_infos_dyldVersion = _ExtractDataFromString(vers_info_data, 28, "uint32_t") 634 dyld_all_image_infos_errorMessage = _ExtractDataFromString(vers_info_data, 32, "uint32_t") 635 dyld_all_image_infos_terminationFlags = _ExtractDataFromString(vers_info_data, 36, "uint32_t") 636 dyld_all_image_infos_coreSymbolicationShmPage = _ExtractDataFromString(vers_info_data, 40, "uint32_t") 637 dyld_all_image_infos_systemOrderFlag = _ExtractDataFromString(vers_info_data, 44, "uint32_t") 638 dyld_all_image_infos_uuidArrayCount = _ExtractDataFromString(vers_info_data, 48, "uint32_t") 639 dyld_all_image_infos_uuidArray = _ExtractDataFromString(vers_info_data, 52, "uint32_t") 640 dyld_all_image_infos_dyldAllImageInfosAddress = _ExtractDataFromString(vers_info_data, 56, "uint32_t") 641 642 dyld_all_imfo_infos_slide = (dyld_all_image_infos_address - dyld_all_image_infos_dyldAllImageInfosAddress) 643 dyld_all_image_infos_dyldVersion_postslide = (dyld_all_image_infos_dyldVersion + dyld_all_imfo_infos_slide) 644 645 path_out = GetPathForImage(task, dyld_all_image_infos_dyldVersion_postslide) 646 out_str += "[dyld-{:s}]\n".format(path_out) 647 out_str += "version \t\t\t\t: {:d}\n".format(dyld_all_image_infos_version) 648 out_str += "infoArrayCount \t\t\t\t: {:d}\n".format(dyld_all_image_infos_infoArrayCount) 649 out_str += "infoArray \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_infoArray) 650 out_str += "notification \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_notification) 651 652 out_str += "processDetachedFromSharedRegion \t: " 653 if dyld_all_image_infos_processDetachedFromSharedRegion != "": 654 out_str += "TRUE\n".format(dyld_all_image_infos_processDetachedFromSharedRegion) 655 else: 656 out_str += "FALSE\n" 657 658 out_str += "libSystemInitialized \t\t\t: " 659 if dyld_all_image_infos_libSystemInitialized != "": 660 out_str += "TRUE\n".format(dyld_all_image_infos_libSystemInitialized) 661 else: 662 out_str += "FALSE\n" 663 664 out_str += "dyldImageLoadAddress \t\t\t: {:#x}\n".format(dyld_all_image_infos_dyldImageLoadAddress) 665 out_str += "jitInfo \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_jitInfo) 666 out_str += "\ndyldVersion \t\t\t\t: {:#x}".format(dyld_all_image_infos_dyldVersion) 667 if (dyld_all_imfo_infos_slide != 0): 668 out_str += " (currently {:#x})\n".format(dyld_all_image_infos_dyldVersion_postslide) 669 else: 670 out_str += "\n" 671 672 out_str += "errorMessage \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_errorMessage) 673 if dyld_all_image_infos_errorMessage != 0: 674 out_str += GetPathForImage(task, dyld_all_image_infos_errorMessage) 675 676 out_str += "terminationFlags \t\t\t: {:#x}\n".format(dyld_all_image_infos_terminationFlags) 677 out_str += "coreSymbolicationShmPage \t\t: {:#x}\n".format(dyld_all_image_infos_coreSymbolicationShmPage) 678 out_str += "systemOrderFlag \t\t\t: {:#x}\n".format(dyld_all_image_infos_systemOrderFlag) 679 out_str += "uuidArrayCount \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_uuidArrayCount) 680 out_str += "uuidArray \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_uuidArray) 681 out_str += "dyldAllImageInfosAddress \t\t: {:#x}".format(dyld_all_image_infos_dyldAllImageInfosAddress) 682 if (dyld_all_imfo_infos_slide != 0): 683 out_str += " (currently {:#x})\n".format(dyld_all_image_infos_address) 684 else: 685 out_str += "\n" 686 687 if is_task_64: 688 dyld_all_image_infos_address = dyld_all_image_infos_address + 112 689 dyld_all_image_infos_v10 = GetUserDataAsString(task, dyld_all_image_infos_address, 64) 690 dyld_all_image_infos_initialImageCount = _ExtractDataFromString(dyld_all_image_infos_v10, 112-112, "uint64_t") 691 dyld_all_image_infos_errorKind = _ExtractDataFromString(dyld_all_image_infos_v10, 120-112, "uint64_t") 692 dyld_all_image_infos_errorClientOfDylibPath = _ExtractDataFromString(dyld_all_image_infos_v10, 128-112, "uint64_t") 693 dyld_all_image_infos_errorTargetDylibPath = _ExtractDataFromString(dyld_all_image_infos_v10, 136-112, "uint64_t") 694 dyld_all_image_infos_errorSymbol = _ExtractDataFromString(dyld_all_image_infos_v10, 144-112, "uint64_t") 695 dyld_all_image_infos_sharedCacheSlide = _ExtractDataFromString(dyld_all_image_infos_v10, 152-112, "uint64_t") 696 dyld_all_image_infos_sharedCacheUUID = _ExtractDataFromString(dyld_all_image_infos_v10, 160-112, "string") 697 else: 698 dyld_all_image_infos_address = dyld_all_image_infos_address + 60 699 dyld_all_image_infos_v10 = GetUserDataAsString(task, dyld_all_image_infos_address, 40) 700 dyld_all_image_infos_initialImageCount = _ExtractDataFromString(dyld_all_image_infos_v10, 60-60, "uint32_t") 701 dyld_all_image_infos_errorKind = _ExtractDataFromString(dyld_all_image_infos_v10, 64-60, "uint32_t") 702 dyld_all_image_infos_errorClientOfDylibPath = _ExtractDataFromString(dyld_all_image_infos_v10, 68-60, "uint32_t") 703 dyld_all_image_infos_errorTargetDylibPath = _ExtractDataFromString(dyld_all_image_infos_v10, 72-60, "uint32_t") 704 dyld_all_image_infos_errorSymbol = _ExtractDataFromString(dyld_all_image_infos_v10, 76-60, "uint32_t") 705 dyld_all_image_infos_sharedCacheSlide = _ExtractDataFromString(dyld_all_image_infos_v10, 80-60, "uint32_t") 706 dyld_all_image_infos_sharedCacheUUID = _ExtractDataFromString(dyld_all_image_infos_v10, 84-60, "string") 707 708 if dyld_all_image_infos_version >= 10: 709 out_str += "\ninitialImageCount \t\t\t: {:#x}\n".format(dyld_all_image_infos_initialImageCount) 710 711 if dyld_all_image_infos_version >= 11: 712 out_str += "errorKind \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_errorKind) 713 out_str += "errorClientOfDylibPath \t\t\t: {:#x}\n".format(dyld_all_image_infos_errorClientOfDylibPath) 714 if dyld_all_image_infos_errorClientOfDylibPath != 0: 715 out_str += "\t\t\t\t" 716 out_str += GetPathForImage(task, dyld_all_image_infos_errorClientOfDylibPath) 717 out_str += "\n" 718 out_str += "errorTargetDylibPath \t\t\t: {:#x}\n".format(dyld_all_image_infos_errorTargetDylibPath) 719 if dyld_all_image_infos_errorTargetDylibPath != 0: 720 out_str += "\t\t\t\t" 721 out_str += GetPathForImage(task, dyld_all_image_infos_errorTargetDylibPath) 722 out_str += "\n" 723 out_str += "errorSymbol \t\t\t\t: {:#x}\n".format(dyld_all_image_infos_errorSymbol) 724 if dyld_all_image_infos_errorSymbol != 0: 725 out_str += "\t\t\t\t" 726 out_str += GetPathForImage(task, dyld_all_image_infos_errorSymbol) 727 out_str += "\n" 728 729 if dyld_all_image_infos_version >= 12: 730 out_str += "sharedCacheSlide \t\t\t: {:#x}\n".format(dyld_all_image_infos_sharedCacheSlide) 731 if dyld_all_image_infos_version >= 13 and dyld_all_image_infos_sharedCacheUUID != "": 732 out_str += "sharedCacheUUID \t\t\t: {:s}\n".format(dyld_all_image_infos_sharedCacheUUID) 733 else: 734 out_str += "No dyld information available for task\n" 735 print out_str 736 737# Macro: showosmalloc 738@lldb_type_summary(['OSMallocTag']) 739@header("{0: <20s} {1: >5s} {2: ^16s} {3: <5s} {4: <40s}".format("TAG", "COUNT", "STATE", "ATTR", "NAME")) 740def GetOSMallocTagSummary(malloc_tag): 741 """ Summarize the given OSMalloc tag. 742 params: 743 malloc_tag : value - value representing a _OSMallocTag_ * in kernel 744 returns: 745 out_str - string summary of the OSMalloc tag. 746 """ 747 if not malloc_tag: 748 return "Invalid malloc tag value: 0x0" 749 750 out_str = "{: <#20x} {: >5d} {: ^#16x} {: <5d} {: <40s}\n".format(malloc_tag, 751 malloc_tag.OSMT_refcnt, malloc_tag.OSMT_state, malloc_tag.OSMT_attr, malloc_tag.OSMT_name) 752 return out_str 753 754@lldb_command('showosmalloc') 755def ShowOSMalloc(cmd_args=None): 756 """ Print the outstanding allocation count of OSMalloc tags 757 Usage: showosmalloc 758 """ 759 summary_str = "" 760 tag_headp = Cast(addressof(kern.globals.OSMalloc_tag_list), 'struct _OSMallocTag_ *') 761 tagp = Cast(tag_headp.OSMT_link.next, 'struct _OSMallocTag_ *') 762 summary_str += GetOSMallocTagSummary.header + "\n" 763 while tagp != tag_headp: 764 summary_str += GetOSMallocTagSummary(tagp) 765 tagp = Cast(tagp.OSMT_link.next, 'struct _OSMallocTag_ *') 766 767 print summary_str 768 769# EndMacro: showosmalloc 770 771 772 773 774