Trees | Indices | Help |
---|
|
1 """ 2 Darwin Platform Module 3 """ 4 # Copyright (C) 2007 Invisigoth - See LICENSE file for details 5 import os 6 import struct 7 import ctypes 8 import signal 9 import ctypes.util as c_util 10 11 import envi.memory as e_mem 12 13 import vtrace 14 import vtrace.archs.i386 as v_i386 15 import vtrace.archs.amd64 as v_amd64 16 import vtrace.platforms.base as v_base 17 import vtrace.platforms.posix as v_posix 18 19 addrof = ctypes.pointer 20 21 # The OSX ptrace defines... 22 PT_TRACE_ME = 0 # child declares it's being traced 23 PT_READ_I = 1 # read word in child's I space 24 PT_READ_D = 2 # read word in child's D space 25 PT_READ_U = 3 # read word in child's user structure 26 PT_WRITE_I = 4 # write word in child's I space 27 PT_WRITE_D = 5 # write word in child's D space 28 PT_WRITE_U = 6 # write word in child's user structure 29 PT_CONTINUE = 7 # continue the child 30 PT_KILL = 8 # kill the child process 31 PT_STEP = 9 # single step the child 32 PT_ATTACH = 10 # trace some running process 33 PT_DETACH = 11 # stop tracing a process 34 PT_SIGEXC = 12 # signals as exceptions for current_proc 35 PT_THUPDATE = 13 # signal for thread# 36 PT_ATTACHEXC = 14 # attach to running process with signal exception 37 PT_FORCEQUOTA = 30 # Enforce quota for root 38 PT_DENY_ATTACH = 31 39 40 # Top-level identifiers 41 CTL_UNSPEC = 0 # unused 42 CTL_KERN = 1 # "high kernel": proc, limits 43 CTL_VM = 2 # virtual memory 44 CTL_VFS = 3 # file system, mount type is next 45 CTL_NET = 4 # network, see socket.h 46 CTL_DEBUG = 5 # debugging parameters 47 CTL_HW = 6 # generic cpu/io 48 CTL_MACHDEP = 7 # machine dependent 49 CTL_USER = 8 # user-level 50 CTL_MAXID = 9 # number of valid top-level ids 51 52 KERN_OSTYPE = 1 # string: system version 53 KERN_OSRELEASE = 2 # string: system release 54 KERN_OSREV = 3 # int: system revision 55 KERN_VERSION = 4 # string: compile time info 56 KERN_MAXVNODES = 5 # int: max vnodes 57 KERN_MAXPROC = 6 # int: max processes 58 KERN_MAXFILES = 7 # int: max open files 59 KERN_ARGMAX = 8 # int: max arguments to exec 60 KERN_SECURELVL = 9 # int: system security level 61 KERN_HOSTNAME = 10 # string: hostname 62 KERN_HOSTID = 11 # int: host identifier 63 KERN_CLOCKRATE = 12 # struct: struct clockrate 64 KERN_VNODE = 13 # struct: vnode structures 65 KERN_PROC = 14 # struct: process entries 66 KERN_FILE = 15 # struct: file entries 67 KERN_PROF = 16 # node: kernel profiling info 68 KERN_POSIX1 = 17 # int: POSIX.1 version 69 KERN_NGROUPS = 18 # int: # of supplemental group ids 70 KERN_JOB_CONTROL = 19 # int: is job control available 71 KERN_SAVED_IDS = 20 # int: saved set-user/group-ID 72 KERN_BOOTTIME = 21 # struct: time kernel was booted 73 KERN_NISDOMAINNAME = 22 # string: YP domain name 74 KERN_DOMAINNAME = KERN_NISDOMAINNAME 75 KERN_MAXPARTITIONS = 23 # int: number of partitions/disk 76 KERN_KDEBUG = 24 # int: kernel trace points 77 KERN_UPDATEINTERVAL = 25 # int: update process sleep time 78 KERN_OSRELDATE = 26 # int: OS release date 79 KERN_NTP_PLL = 27 # node: NTP PLL control 80 KERN_BOOTFILE = 28 # string: name of booted kernel 81 KERN_MAXFILESPERPROC = 29 # int: max open files per proc 82 KERN_MAXPROCPERUID = 30 # int: max processes per uid 83 KERN_DUMPDEV = 31 # dev_t: device to dump on 84 KERN_IPC = 32 # node: anything related to IPC 85 KERN_DUMMY = 33 # unused 86 KERN_PS_STRINGS = 34 # int: address of PS_STRINGS 87 KERN_USRSTACK32 = 35 # int: address of USRSTACK 88 KERN_LOGSIGEXIT = 36 # int: do we log sigexit procs? 89 KERN_SYMFILE = 37 # string: kernel symbol filename 90 KERN_PROCARGS = 38 91 #/* 39 was KERN_PCSAMPLES... now deprecated 92 KERN_NETBOOT = 40 # int: are we netbooted? 1=yes,0=no 93 KERN_PANICINFO = 41 # node: panic UI information 94 KERN_SYSV = 42 # node: System V IPC information 95 KERN_AFFINITY = 43 # xxx 96 KERN_TRANSLATE = 44 # xxx 97 KERN_CLASSIC = KERN_TRANSLATE # XXX backwards compat 98 KERN_EXEC = 45 # xxx 99 KERN_CLASSICHANDLER = KERN_EXEC # XXX backwards compatibility 100 KERN_AIOMAX = 46 # int: max aio requests 101 KERN_AIOPROCMAX = 47 # int: max aio requests per process 102 KERN_AIOTHREADS = 48 # int: max aio worker threads 103 KERN_PROCARGS2 = 49 104 KERN_COREFILE = 50 # string: corefile format string 105 KERN_COREDUMP = 51 # int: whether to coredump at all 106 KERN_SUGID_COREDUMP = 52 # int: whether to dump SUGID cores 107 KERN_PROCDELAYTERM = 53 # int: set/reset current proc for delayed termination during shutdown 108 KERN_SHREG_PRIVATIZABLE = 54 # int: can shared regions be privatized ? 109 KERN_PROC_LOW_PRI_IO = 55 # int: set/reset current proc for low priority I/O 110 KERN_LOW_PRI_WINDOW = 56 # int: set/reset throttle window - milliseconds 111 KERN_LOW_PRI_DELAY = 57 # int: set/reset throttle delay - milliseconds 112 KERN_POSIX = 58 # node: posix tunables 113 KERN_USRSTACK64 = 59 # LP64 user stack query 114 KERN_NX_PROTECTION = 60 # int: whether no-execute protection is enabled 115 KERN_TFP = 61 # Task for pid settings 116 KERN_PROCNAME = 62 # setup process program name(2*MAXCOMLEN) 117 KERN_THALTSTACK = 63 # for compat with older x86 and does nothing 118 KERN_SPECULATIVE_READS = 64 # int: whether speculative reads are disabled 119 KERN_OSVERSION = 65 # for build number i.e. 9A127 120 KERN_SAFEBOOT = 66 # are we booted safe? 121 KERN_LCTX = 67 # node: login context 122 KERN_RAGEVNODE = 68 123 KERN_TTY = 69 # node: tty settings 124 KERN_CHECKOPENEVT = 70 # spi: check the VOPENEVT flag on vnodes at open time 125 KERN_MAXID = 71 # number of valid kern ids 126 # # KERN_RAGEVNODE types 127 KERN_RAGE_PROC = 1 128 KERN_RAGE_THREAD = 2 129 KERN_UNRAGE_PROC = 3 130 KERN_UNRAGE_THREAD = 4 131 132 # # KERN_OPENEVT types 133 KERN_OPENEVT_PROC = 1 134 KERN_UNOPENEVT_PROC = 2 135 136 # # KERN_TFP types 137 KERN_TFP_POLICY = 1 138 139 # # KERN_TFP_POLICY values . All policies allow task port for self 140 KERN_TFP_POLICY_DENY = 0 # Deny Mode: None allowed except privileged 141 KERN_TFP_POLICY_DEFAULT = 2 # Default Mode: related ones allowed and upcall authentication 142 143 # # KERN_KDEBUG types 144 KERN_KDEFLAGS = 1 145 KERN_KDDFLAGS = 2 146 KERN_KDENABLE = 3 147 KERN_KDSETBUF = 4 148 KERN_KDGETBUF = 5 149 KERN_KDSETUP = 6 150 KERN_KDREMOVE = 7 151 KERN_KDSETREG = 8 152 KERN_KDGETREG = 9 153 KERN_KDREADTR = 10 154 KERN_KDPIDTR = 11 155 KERN_KDTHRMAP = 12 156 # # Don't use 13 as it is overloaded with KERN_VNODE 157 KERN_KDPIDEX = 14 158 KERN_KDSETRTCDEC = 15 159 KERN_KDGETENTROPY = 16 160 161 # # KERN_PANICINFO types 162 KERN_PANICINFO_MAXSIZE = 1 # quad: panic UI image size limit 163 KERN_PANICINFO_IMAGE = 2 # panic UI in 8-bit kraw format 164 165 # * KERN_PROC subtypes 166 KERN_PROC_ALL = 0 # everything 167 KERN_PROC_PID = 1 # by process id 168 KERN_PROC_PGRP = 2 # by process group id 169 KERN_PROC_SESSION = 3 # by session of pid 170 KERN_PROC_TTY = 4 # by controlling tty 171 KERN_PROC_UID = 5 # by effective uid 172 KERN_PROC_RUID = 6 # by real uid 173 KERN_PROC_LCID = 7 # by login context id 174 175 # Stupid backwards perms defs... 176 VM_PROT_READ = 1 177 VM_PROT_WRITE = 2 178 VM_PROT_EXECUTE = 4 179 180 # Thread status types... 181 x86_THREAD_STATE32 = 1 182 x86_FLOAT_STATE32 = 2 183 x86_EXCEPTION_STATE32 = 3 184 x86_THREAD_STATE64 = 4 185 x86_FLOAT_STATE64 = 5 186 x86_EXCEPTION_STATE64 = 6 187 x86_THREAD_STATE = 7 188 x86_FLOAT_STATE = 8 189 x86_EXCEPTION_STATE = 9 190 x86_DEBUG_STATE32 = 10 191 x86_DEBUG_STATE64 = 11 192 x86_DEBUG_STATE = 12 193 THREAD_STATE_NONE = 13 194 200202 _fields_ = [ 203 #('tsh', X86_STATE_HDR), 204 ('eax', ctypes.c_uint32), 205 ('ebx', ctypes.c_uint32), 206 ('ecx', ctypes.c_uint32), 207 ('edx', ctypes.c_uint32), 208 ('edi', ctypes.c_uint32), 209 ('esi', ctypes.c_uint32), 210 ('ebp', ctypes.c_uint32), 211 ('esp', ctypes.c_uint32), 212 ('ss', ctypes.c_uint32), 213 ('eflags', ctypes.c_uint32), 214 ('eip', ctypes.c_uint32), 215 ('cs', ctypes.c_uint32), 216 ('ds', ctypes.c_uint32), 217 ('es', ctypes.c_uint32), 218 ('fs', ctypes.c_uint32), 219 ('gs', ctypes.c_uint32), 220 ]221223 _fields_ = [ 224 ('trapno', ctypes.c_uint32), 225 ('err', ctypes.c_uint32), 226 ('faultvaddr', ctypes.c_uint32), 227 ]228 231233 _fields_ = [ 234 #('tsh', X86_STATE_HDR), 235 ('rax', ctypes.c_uint64), 236 ('rbx', ctypes.c_uint64), 237 ('rcx', ctypes.c_uint64), 238 ('rdx', ctypes.c_uint64), 239 ('rdi', ctypes.c_uint64), 240 ('rsi', ctypes.c_uint64), 241 ('rbp', ctypes.c_uint64), 242 ('rsp', ctypes.c_uint64), 243 ('r8', ctypes.c_uint64), 244 ('r9', ctypes.c_uint64), 245 ('r10', ctypes.c_uint64), 246 ('r11', ctypes.c_uint64), 247 ('r12', ctypes.c_uint64), 248 ('r13', ctypes.c_uint64), 249 ('r14', ctypes.c_uint64), 250 ('r15', ctypes.c_uint64), 251 ('rip', ctypes.c_uint64), 252 ('rflags', ctypes.c_uint64), 253 ('cs', ctypes.c_uint64), 254 ('fs', ctypes.c_uint64), 255 ('gs', ctypes.c_uint64), 256 ]257 258260 _fields_ = [ 261 ('trapno', ctypes.c_uint32), 262 ('err', ctypes.c_uint32), 263 ('faultvaddr', ctypes.c_uint64), 264 ]265 268 269 ########################################################################### 270 # 271 # mach port enumerations 272 # 273 MACH_PORT_NULL = 0 274 275 #MACH_PORT_RIGHT_* definitions are used as arguments 276 MACH_PORT_RIGHT_SEND = 0 277 MACH_PORT_RIGHT_RECEIVE = 1 278 MACH_PORT_RIGHT_SEND_ONCE = 2 279 MACH_PORT_RIGHT_PORT_SET = 3 280 MACH_PORT_RIGHT_DEAD_NAME = 4 281 MACH_PORT_RIGHT_LABELH = 5 282 MACH_PORT_RIGHT_NUMBER = 6 283 286 287 MACH_PORT_TYPE_SEND = MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND) 288 MACH_PORT_TYPE_RECEIVE = MACH_PORT_TYPE(MACH_PORT_RIGHT_RECEIVE) 289 MACH_PORT_TYPE_SEND_ONCE = MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND_ONCE) 290 MACH_PORT_TYPE_PORT_SET = MACH_PORT_TYPE(MACH_PORT_RIGHT_PORT_SET) 291 MACH_PORT_TYPE_DEAD_NAME = MACH_PORT_TYPE(MACH_PORT_RIGHT_DEAD_NAME) 292 MACH_PORT_TYPE_LABELH = MACH_PORT_TYPE(MACH_PORT_RIGHT_LABELH) 293 294 ########################################################################### 295 # 296 # mach message types and structures 297 # 298 MACH_MSG_TIMEOUT_NONE = 0 299 MACH_MSG_OPTION_NONE = 0 300 301 MACH_SEND_MSG = 0x00000001 302 MACH_RCV_MSG = 0x00000002 303 MACH_RCV_LARGE = 0x00000004 304 305 MACH_SEND_TIMEOUT = 0x00000010 306 MACH_SEND_INTERRUPT = 0x00000040 # libmach implements 307 MACH_SEND_CANCEL = 0x00000080 308 MACH_SEND_ALWAYS = 0x00010000 # internal use only 309 MACH_SEND_TRAILER = 0x00020000 310 311 MACH_RCV_TIMEOUT = 0x00000100 312 MACH_RCV_NOTIFY = 0x00000200 313 MACH_RCV_INTERRUPT = 0x00000400 # libmach implements 314 MACH_RCV_OVERWRITE = 0x00001000 315 316 # Return codes from mach_msg... 317 MACH_RCV_TIMED_OUT = 0x10004003 318 319 MACH_MSG_TYPE_MOVE_RECEIVE = 16 # Must hold receive rights 320 MACH_MSG_TYPE_MOVE_SEND = 17 # Must hold send rights 321 MACH_MSG_TYPE_MOVE_SEND_ONCE = 18 # Must hold sendonce rights 322 MACH_MSG_TYPE_COPY_SEND = 19 # Must hold send rights 323 MACH_MSG_TYPE_MAKE_SEND = 20 # Must hold receive rights 324 MACH_MSG_TYPE_MAKE_SEND_ONCE = 21 # Must hold receive rights 325 MACH_MSG_TYPE_COPY_RECEIVE = 22 # Must hold receive rights 326 327 size_t = ctypes.c_ulong 328 329 mach_port_t = ctypes.c_uint32 330 mach_port_name_t = ctypes.c_uint32 331 mach_port_right_t = ctypes.c_uint32 332 mach_msg_size_t = ctypes.c_uint32 333 mach_msg_bits_t = ctypes.c_uint32 334 mach_msg_id_t = ctypes.c_uint32 335 336 ipc_space_t = ctypes.c_uint32 337 338 kern_return_t = ctypes.c_uint32 339341 _fields_ = [ 342 ('msgh_bits', mach_msg_bits_t), 343 ('msgh_size', mach_msg_size_t), 344 ('msgh_remote_port', mach_port_t), 345 ('msgh_local_port', mach_port_t), 346 ('msgh_reserved', mach_msg_size_t), 347 ('msgh_id', mach_msg_id_t), 348 ]349 354356 _fields_ = [ 357 ('name', mach_port_t), 358 ('pad1', mach_msg_size_t), 359 ('pad2', ctypes.c_uint32), 360 ]361363 _fields_ = [ 364 ('mig_vers', ctypes.c_uint8), 365 ('if_vers', ctypes.c_uint8), 366 ('reserved', ctypes.c_uint8), 367 ('mig_encoding', ctypes.c_uint8), 368 ('int_rep', ctypes.c_uint8), 369 ('char_rep', ctypes.c_uint8), 370 ('float_rep', ctypes.c_uint8), 371 ('reserved2', ctypes.c_uint8), 372 ]373 374 exception_type_t = ctypes.c_uint32 375 mach_msg_type_number_t = ctypes.c_uint32 376 exception_data_t = ctypes.POINTER(ctypes.c_uint32) 377 378 # the message type we receive from the kernel for exceptions380 _fields_ = [ 381 ('Head', mach_msg_header_t), 382 #('data', ctypes.c_uint8 * 1024), 383 384 ('body', mach_msg_body_t), 385 ('thread', mach_msg_port_descriptor_t), 386 ('task', mach_msg_port_descriptor_t), 387 ('NDR', NDR_record_t), 388 ('exception', exception_type_t), 389 ('codeCnt', mach_msg_type_number_t), 390 ('codes', ctypes.c_uint32 * 128), 391 392 393 ##('codes', exception_data_t), 394 ##('pad', ctypes.c_uint8 * 512) 395 396 ]397 398 # The response message we send back400 _fields_ = [ 401 ('Head', mach_msg_header_t), 402 ('data', ctypes.c_uint8 * 1024), 403 #('NDR', NDR_record_t), 404 #('RetCode', ctypes.c_uint32) 405 ]406 407 ########################################################################## 408 # mach generic exception codes 409 # 410 EXC_BAD_ACCESS = 1 411 EXC_BAD_INSTRUCTION = 2 412 EXC_ARITHMETIC = 3 413 EXC_EMULATION = 4 414 EXC_SOFTWARE = 5 415 EXC_BREAKPOINT = 6 416 EXC_SYSCALL = 7 417 EXC_MACH_SYSCALL = 8 418 EXC_RPC_ALERT = 9 419 EXC_CRASH = 10 420 421 # EXC_SOFTWARE will have code[0] == EXC_SOFT_SIGNAL for posix sigs 422 EXC_SOFT_SIGNAL = 0x10003 # Unix signal exceptions 423 424 EXC_MASK_MACHINE = 0 425 EXC_MASK_BAD_ACCESS = 1 << EXC_BAD_ACCESS 426 EXC_MASK_BAD_INSTRUCTION = 1 << EXC_BAD_INSTRUCTION 427 EXC_MASK_ARITHMETIC = 1 << EXC_ARITHMETIC 428 EXC_MASK_EMULATION = 1 << EXC_EMULATION 429 EXC_MASK_SOFTWARE = 1 << EXC_SOFTWARE 430 EXC_MASK_BREAKPOINT = 1 << EXC_BREAKPOINT 431 EXC_MASK_SYSCALL = 1 << EXC_SYSCALL 432 EXC_MASK_MACH_SYSCALL = 1 << EXC_MACH_SYSCALL 433 EXC_MASK_RPC_ALERT = 1 << EXC_RPC_ALERT 434 EXC_MASK_CRASH = 1 << EXC_CRASH 435 436 EXC_MASK_ALL = (EXC_MASK_BAD_ACCESS | 437 EXC_MASK_BAD_INSTRUCTION | 438 EXC_MASK_ARITHMETIC | 439 EXC_MASK_EMULATION | 440 EXC_MASK_SOFTWARE | 441 EXC_MASK_BREAKPOINT | 442 EXC_MASK_SYSCALL | 443 EXC_MASK_MACH_SYSCALL | 444 EXC_MASK_RPC_ALERT | 445 EXC_MASK_CRASH | 446 EXC_MASK_MACHINE) 447 448 EXCEPTION_DEFAULT = 1 # Send a catch_exception_raise message including the identity. 449 EXCEPTION_STATE = 2 # Send a catch_exception_raise_state message including the thread state. 450 EXCEPTION_STATE_IDENTITY = 3 # Send a catch_exception_raise_state_identity message including the thread identity and state. 451 MACH_EXCEPTION_CODES = 0x80000000 # Send 64-bit code and subcode in the exception header 452 453 boolean_t = ctypes.c_uint32 454 pid_t = ctypes.c_uint32 455 #u_int = ctypes.c_uint32 456 #pvoid = ctypes.c_void_p 457 #fixpt_t = ctypes.c_uint32 458 #u_quad_t = ctypes.c_ulonglong 459 #sigset_t = ctypes.c_uint32 460 thread_t = ctypes.c_uint32 461 462 463 #################################################################### 464 # 465 # mach VM related stuff.... 466 # 467 vm_prot_t = ctypes.c_uint32 468 vm_inherit_t = ctypes.c_uint32 469 vm_behavior_t = ctypes.c_uint32 470 memory_object_offset_t = ctypes.c_ulonglong 471 472 VM_REGION_BASIC_INFO_64 = 9 473475 _fields_ = [ 476 ('protection', vm_prot_t), 477 ('max_protection', vm_prot_t), 478 ('inheritance', vm_inherit_t), 479 ('shared', boolean_t), 480 ('reserved', boolean_t), 481 ('offset', memory_object_offset_t), 482 ('behavior', vm_behavior_t), 483 ('user_wired_count',ctypes.c_ushort), 484 ]485 486 print 'vm_region_basic_info_64',ctypes.sizeof(vm_region_basic_info_64) 487 VM_REGION_BASIC_INFO_COUNT_64 = ctypes.sizeof(vm_region_basic_info_64) / 4 488 489 #mach_helper = ctypes.CDLL('./darwin_mach.dylib') 490 491 # 492 # These are used by the machhelper library code 493 #495 _fields_ = [ 496 ('dbgtask', mach_port_t), 497 ('task', mach_port_t), 498 ('portset', mach_port_name_t), 499 ('excport', mach_port_name_t), 500 ('msgin', ctypes.c_void_p), 501 ('msgout', ctypes.c_void_p), 502 ]503 509 510 darwindir = os.path.dirname(__file__) 511 machhelp_path = os.path.join(darwindir, 'machhelper.dylib') 512 machhelper = ctypes.CDLL(machhelp_path) 513 514 #machhelper.initDebugContext.restype = ctypes.c_uint32 515 #machhelper.initDebugContext.argtypes = (ctypes.POINTER(DarwinDebugCtx), ctypes.c_uint32) 516 517 machhelper.platformPs.restype = ctypes.POINTER(ProcessListEntry) 518 519 #################################################################### 520522859 860 # FIXME use vm_allocate for allocate memory 861 # FIXME use vm_protect 862524 v_posix.PosixMixin.__init__(self) 525 v_posix.PtraceMixin.__init__(self) 526 527 self.libc = ctypes.CDLL(c_util.find_library('c')) 528 self.myport = self.libc.mach_task_self() 529 530 self.libc.mach_port_allocate.argtypes = [ipc_space_t, mach_port_right_t, ctypes.POINTER(mach_port_name_t)] 531 self.libc.mach_port_allocate.restype = kern_return_t 532 533 self.libc.mach_vm_read.argtypes = [ mach_port_t, size_t, size_t, ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(ctypes.c_uint32)] 534 self.libc.mach_vm_read.restype = kern_return_t 535 #FIXME mach_port_insert_right 536 537 self.portset = self.newMachPort(MACH_PORT_RIGHT_PORT_SET) 538 self.excport = self.newMachRWPort() 539 self.addPortToSet(self.excport)540542 543 ret = [] 544 y = machhelper.platformPs() 545 i = 0 546 while y[i].pid != 0xffffffff: 547 ret.append((y[i].pid, y[i].name)) 548 i += 1 549 550 # FIXME free! 551 ret.reverse() 552 return ret553 556 560562 pid = v_posix.PtraceMixin.platformExec(self, cmdline) 563 self.task = self.taskForPid(pid) 564 self.setExceptionPort() 565 return pid566568 count = ctypes.c_uint32() 569 tlist = ctypes.POINTER(thread_t)() 570 r = self.libc.task_threads(self.task, addrof(tlist), addrof(count)) 571 if r != 0: 572 raise Exception('task_threads Failed: 0x%.8x' % r) 573 574 ret = [ tlist[i] for i in range(count.value)] 575 self.libc.vm_deallocate(self.task, tlist) 576 return ret577579 self.libc.thread_suspend(tid)580582 self.libc.thread_resume(tid)583 589591 592 maps = [] 593 address = ctypes.c_ulong(0) 594 mapsize = ctypes.c_ulong(0) 595 name = ctypes.c_uint32(0) 596 count = ctypes.c_uint32(VM_REGION_BASIC_INFO_COUNT_64) 597 info = vm_region_basic_info_64() 598 599 while True: 600 601 r = self.libc.mach_vm_region(self.task, addrof(address), 602 addrof(mapsize), VM_REGION_BASIC_INFO_64, 603 addrof(info), addrof(count), 604 addrof(name)) 605 606 # If we get told "invalid address", we have crossed into kernel land... 607 if r == 1: 608 break 609 610 if r != 0: 611 self.libc.mach_error("mach_vm_region", r) 612 raise Exception('vm_region Failed for 0x%.8x: 0x%.8x' % (address.value,r)) 613 614 perms = 0 615 p = info.protection 616 if p & VM_PROT_READ: 617 perms |= e_mem.MM_READ 618 if p & VM_PROT_WRITE: 619 perms |= e_mem.MM_WRITE 620 if p & VM_PROT_EXECUTE: 621 perms |= e_mem.MM_EXEC 622 if info.shared: 623 perms |= e_mem.MM_SHARED 624 # If we got any perms, report the map 625 if perms: 626 maps.append((address.value, mapsize.value, perms, '')) 627 628 address.value += mapsize.value 629 630 return maps631633 """ 634 Handle a mach exception message 635 """ 636 threadid, excode, codes = event 637 638 # Set the thread that signaled. 639 self.setMeta('ThreadId', threadid) 640 self.setMeta('StoppedThreadId', threadid) 641 642 self.setMeta('MachException', event) 643 644 if excode == EXC_SOFTWARE: 645 print 'exc_software' 646 647 if len(codes) != 2: 648 raise Exception('EXC_SOFTWARE with codeCnt != 2: %d' % len(codes)) 649 650 if codes[0] != EXC_SOFT_SIGNAL: 651 raise Exception('codes[0] != EXC_SOFT_SIGNAL: %.8x' % codes[0]) 652 653 sig = codes[1] 654 print 'SOFT SIG',sig 655 656 if sig == signal.SIGTRAP: 657 # FIXME I think we can catch these! 658 # Traps on posix systems are a little complicated 659 if self.stepping: 660 self.stepping = False 661 self.fireNotifiers(vtrace.NOTIFY_STEP) 662 663 # FIXME and these too... 664 elif self.checkBreakpoints(): 665 # It was either a known BP or a sendBreak() 666 return 667 668 elif self.execing: 669 self.execing = False 670 self.handleAttach() 671 672 else: 673 self._fireSignal(sig) 674 675 elif sig == signal.SIGSTOP: 676 # We get a regular POSIX stop signal on attach 677 self.handleAttach() 678 679 else: 680 self._fireSignal(sig) 681 682 elif excode == EXC_BAD_ACCESS: 683 print 'exc_bad_access',repr([hex(x) for x in codes ]) 684 self._fireSignal(0) 685 686 elif excode == EXC_CRASH: 687 print 'exc_crash' 688 print 'Crash:',repr([hex(x) for x in codes]) 689 self._fireExit(0xffffffff) 690 691 elif excode == EXC_BREAKPOINT: 692 print 'exc_breakpoint',codes 693 self._fireSignal(0) # FIXME 694 695 else: 696 print 'Unprocessed Exception Type: %d' % excode 697 self.fireNotifiers(vtrace.NOTIFY_SIGNAL) 698 699 return700702 print 'CLASSIC',machhelper.is_pid_classic(pid) 703 self.task = self.taskForPid(pid) 704 self.setExceptionPort() 705 if v_posix.ptrace(PT_ATTACHEXC, pid, 0, 0) != 0: 706 #self.libc.perror('ptrace( PT_ATTACHEXC, %d, 0, 0) Failed' % (pid)) 707 raise Exception("PT_ATTACH failed!")708 #FIXME setMeta("ExeName", stuff) 709 #self.setMeta("ExeName", self._findExe(pid)) 710712 task = ctypes.c_uint32() 713 ret = self.libc.task_for_pid(self.myport, pid, addrof(task)) 714 if ret != 0: 715 raise Exception('task_for_pid failed: 0x%.8x\n' % ret) 716 return task.value717719 port = mach_port_name_t() 720 ret = self.libc.mach_port_allocate(self.myport, right, addrof(port)) 721 if ret != 0: 722 raise Exception('mach_port_allocate (right: %d) failed: 0x%.8x' % (right, ret)) 723 return port.value724726 port = self.newMachPort(MACH_PORT_RIGHT_RECEIVE) 727 r = self.libc.mach_port_insert_right(self.myport, port, port, MACH_MSG_TYPE_MAKE_SEND) 728 if r != 0: 729 raise Exception('mach_port_insert_right (MACH_PORT_RIGHT_RECEIVE) Failed: 0x%.8x' % r) 730 return port731733 r = self.libc.mach_port_move_member(self.myport, port, self.portset) 734 if r != 0: 735 raise Exception('mach_port_move_member for portset failed: 0x%.8x' % r)736738 # Set the target task's exception port to our excport 739 #r = self.libc.task_set_exception_ports(self.task, EXC_MASK_ALL, self.excport, 740 r = self.libc.task_set_exception_ports(self.task, EXC_MASK_SOFTWARE, self.excport, 741 EXCEPTION_DEFAULT, THREAD_STATE_NONE) 742 if r != 0: 743 raise Exception('task_set_exception_ports failed: 0x%.8x' % r)744746 exc = exc_msg() 747 r = self.libc.mach_msg(addrof(exc), 748 #MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TIMEOUT, 749 MACH_RCV_MSG|MACH_RCV_INTERRUPT, 750 0, # Send size... 751 ctypes.sizeof(exc), # Recv msg size 752 self.excport, 753 timeout, 754 MACH_PORT_NULL) 755 if r == MACH_RCV_TIMED_OUT: 756 return None 757 if r != 0: 758 raise Exception('mach_msg (RECV) failed: 0x%.8x' % r) 759 760 #print 'BITS',hex(exc.Head.msgh_bits) 761 #print 'ID',exc.Head.msgh_id 762 #print 'EXCEPTION',exc.exception 763 #print 'codeCnt', exc.codeCnt 764 #for i in range(exc.codeCnt): 765 #print 'code: 0x%.16x' % exc.codes[i] 766 767 return exc768770 # Wait for a mach message on the exception port 771 exc = None 772 while exc == None: 773 exc = self._getNextExc() 774 print 'EXC',exc 775 776 print 'EXC THREAD',exc.thread.name 777 778 self.setMeta('ThreadId', exc.thread.name) 779 self.setMeta('StoppedThreadId', exc.thread.name) 780 #e2 = self._getNextExc(timeout=0) 781 #if e2 != None: 782 #print "ALSO GOT",e2 783 784 # Suspend the task so reading etc is safe... 785 self.libc.task_suspend(self.task) 786 787 # Sometimes there are still posix signals anyway... 788 while os.waitpid(-1, os.WNOHANG) != (0,0): 789 pass 790 791 # NOTE We must extract *all* needed info from the event here! 792 codes = [exc.codes[i] for i in range(exc.codeCnt)] 793 ret = (exc.thread.name, exc.exception, codes) 794 795 res = self.buildExcResp(exc) 796 797 x = self.libc.mach_msg(addrof(res), MACH_SEND_MSG, ctypes.sizeof(res),0,MACH_MSG_TIMEOUT_NONE,MACH_PORT_NULL) 798 if x != 0: 799 raise Exception('mach_msg MACH_SEND_MSG failed: 0x%.8x' % (x,)) 800 801 return ret802 #return exc 803805 # This is from straight reversing exc_server from libc... 806 807 #res = exc_rep_msg() 808 809 #res.Head.msgh_bits = exc.Head.msgh_bits & 0xff 810 #res.Head.msgh_size = 0x24 811 #res.Head.msgh_remote_port = exc.Head.msgh_remote_port 812 #res.Head.msgh_local_port = 0 813 #res.Head.msgh_id = exc.Head.msgh_id + 0x64 814 #res.NDR.int_rep = 1 815 #res.RetCode = 0 816 817 #print 'exc_server',self.libc.exc_server(ctypes.pointer(exc), ctypes.pointer(res)) 818 #return res 819 820 print 'exc_server',self.libc.exc_server(ctypes.pointer(exc), ctypes.pointer(exc)) 821 return exc822824 self.stepping = True 825 tid = self.getMeta("ThreadId", 0) 826 if v_posix.ptrace(v_posix.PT_STEP, self.pid, 1, 0) != 0: 827 raise Exception("ERROR ptrace failed!") 828 self.libc.task_resume(self.task)829831 sig = self.getCurrentSignal() 832 if sig == None: 833 sig = 0 834 print 'PT_THUPDATE',v_posix.ptrace(PT_THUPDATE, self.pid, self.getMeta('StoppedThreadId'), sig) 835 v_posix.ptrace(PT_CONTINUE, self.pid, 1, sig) 836 self.libc.task_resume(self.task)837839 #for tid in self.getThreads().keys(): 840 #self.libc.thread_resume(tid) 841 self.libc.task_resume(self.task) 842 v_posix.ptrace(PT_DETACH, self.pid, 0, 0)843845 pval = ctypes.c_void_p(0) 846 sval = ctypes.c_uint32(0) 847 r = self.libc.mach_vm_read(self.task, address, size, addrof(pval), addrof(sval)); 848 #r = self.libc.vm_read(self.task, address, size, addrof(pval), addrof(sval)); 849 if r != 0: 850 raise Exception('mach_vm_read failed at 0x%.8x: 0x%.8x' % (address,r)) 851 buf = ctypes.string_at(pval.value, sval.value) 852 self.libc.vm_deallocate(self.myport, pval, sval) 853 return buf854863 -class Darwini386Trace( 864 vtrace.Trace, 865 DarwinMixin, 866 v_i386.i386Mixin, 867 v_base.TracerBase):868928870 vtrace.Trace.__init__(self) 871 v_base.TracerBase.__init__(self) 872 v_i386.i386Mixin.__init__(self) 873 DarwinMixin.__init__(self)874876 # Each arch trace must implement this... 877 state = STRUCT_X86_EXCEPTION_STATE32() 878 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 879 ret = self.libc.thread_get_state(tid, x86_EXCEPTION_STATE32, addrof(state), addrof(scount)); 880 if ret != 0: 881 raise Exception('thread_get_state failed: 0x%.8x' % ret) 882 return state.trapno, state.err, state.faultvaddr883885 ctx = self.archGetRegCtx() 886 # NOTE: the tid *is* the port... 887 888 state = STRUCT_X86_THREAD_STATE32() 889 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 890 ret = self.libc.thread_get_state(tid, x86_THREAD_STATE32, addrof(state), addrof(scount)); 891 if ret != 0: 892 raise Exception('thread_get_state (THREAD_STATE32) failed: 0x%.8x' % ret) 893 ctx._rctx_Import(state) 894 895 state = STRUCT_X86_DEBUG_STATE32() 896 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 897 ret = self.libc.thread_get_state(tid, x86_DEBUG_STATE32, addrof(state), addrof(scount)); 898 if ret != 0: 899 raise Exception('thread_get_state (DEBUG_STATE32) failed: 0x%.8x' % ret) 900 ctx._rctx_Import(state) 901 902 return ctx903905 906 state = STRUCT_X86_THREAD_STATE32() 907 908 # Sync up a struct first... 909 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 910 ret = self.libc.thread_get_state(tid, x86_THREAD_STATE32, addrof(state), addrof(scount)); 911 if ret != 0: 912 raise Exception('thread_get_state (THREAD_STATE32) failed: 0x%.8x' % ret) 913 914 # Export our shit into it... 915 ctx._rctx_Export(state) 916 917 scount = ctypes.sizeof(state) / 4 918 r = self.libc.thread_set_state(tid, x86_THREAD_STATE32, addrof(state), scount) 919 if r != 0: 920 raise Exception('thread_set_state (THREAD_STATE32) failed: 0x%.8x' % r) 921 922 state = STRUCT_X86_DEBUG_STATE32() 923 ctx._rctx_Export(state) 924 scount = ctypes.sizeof(state) / 4 925 r = self.libc.thread_set_state(tid, x86_DEBUG_STATE32, addrof(state), scount) 926 if r != 0: 927 raise Exception('thread_set_state (DEBUG_STATE32) failed: 0x%.8x' % r)929 -class DarwinAmd64Trace( 930 vtrace.Trace, 931 DarwinMixin, 932 v_amd64.Amd64Mixin, 933 v_base.TracerBase):934996936 vtrace.Trace.__init__(self) 937 v_base.TracerBase.__init__(self) 938 v_amd64.Amd64Mixin.__init__(self) 939 DarwinMixin.__init__(self)940942 # Each arch trace must implement this... 943 state = STRUCT_X86_EXCEPTION_STATE64() 944 scount = ctypes.c_uint32(ctypes.sizeof(state) / 8) 945 ret = self.libc.thread_get_state(tid, x86_EXCEPTION_STATE64, addrof(state), addrof(scount)); 946 if ret != 0: 947 raise Exception('thread_get_state failed: 0x%.8x' % ret) 948 return state.trapno, state.err, state.faultvaddr949951 ctx = self.archGetRegCtx() 952 # NOTE: the tid *is* the port... 953 954 state = STRUCT_X86_THREAD_STATE64() 955 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 956 ret = self.libc.thread_get_state(tid, x86_THREAD_STATE64, addrof(state), addrof(scount)); 957 if ret != 0: 958 self.libc.mach_error("thread_get_state x86_THREAD_STATE64 failed:", ret) 959 raise Exception('thread_get_state (THREAD_STATE64) failed: 0x%.8x' % ret) 960 ctx._rctx_Import(state) 961 962 state = STRUCT_X86_DEBUG_STATE64() 963 scount = ctypes.c_uint32(ctypes.sizeof(state) / 4) 964 ret = self.libc.thread_get_state(tid, x86_DEBUG_STATE64, addrof(state), addrof(scount)); 965 if ret != 0: 966 self.libc.mach_error("thread_get_state x86_DEBUG_STATE64 failed:", ret) 967 raise Exception('thread_get_state (DEBUG_STATE64) failed: 0x%.8x' % ret) 968 ctx._rctx_Import(state) 969 970 return ctx971973 974 state = STRUCT_X86_THREAD_STATE64() 975 976 # Sync up a struct first... 977 scount = ctypes.c_uint32(ctypes.sizeof(state) / 8) 978 ret = self.libc.thread_get_state(tid, x86_THREAD_STATE64, addrof(state), addrof(scount)); 979 if ret != 0: 980 raise Exception('thread_get_state (THREAD_STATE64) failed: 0x%.8x' % ret) 981 982 # Export our shit into it... 983 ctx._rctx_Export(state) 984 985 scount = ctypes.sizeof(state) / 8 986 r = self.libc.thread_set_state(tid, x86_THREAD_STATE64, addrof(state), scount) 987 if r != 0: 988 raise Exception('thread_set_state (THREAD_STATE64) failed: 0x%.8x' % r) 989 990 state = STRUCT_X86_DEBUG_STATE64() 991 ctx._rctx_Export(state) 992 scount = ctypes.sizeof(state) / 8 993 r = self.libc.thread_set_state(tid, x86_DEBUG_STATE64, addrof(state), scount) 994 if r != 0: 995 raise Exception('thread_set_state (DEBUG_STATE64) failed: 0x%.8x' % r)
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Fri Nov 16 18:22:26 2012 | http://epydoc.sourceforge.net |