Package vtrace :: Package platforms :: Module posix
[hide private]
[frames] | no frames]

Source Code for Module vtrace.platforms.posix

  1  """ 
  2  Posix Signaling Module 
  3  """ 
  4  # Copyright (C) 2007 Invisigoth - See LICENSE file for details 
  5  import sys 
  6  import os 
  7  import struct 
  8  import signal 
  9  import platform 
 10   
 11   
 12  import vtrace 
 13  import vtrace.util as v_util 
 14  import vtrace.platforms.base as v_base 
 15   
 16  import Elf 
 17  from ctypes import * 
 18  import ctypes.util as cutil 
 19   
 20  import envi.resolver as e_resolv 
 21  import envi.memory as e_mem 
 22  import envi.cli as e_cli 
 23   
 24   
 25  libc = None 
26 27 -class PosixMixin:
28 29 """ 30 A mixin for systems which use POSIX signals and 31 things like wait() 32 """ 33
34 - def __init__(self):
35 """ 36 Setup for the fact that we support signal driven 37 debugging on posix platforms 38 """ 39 self.stepping = False # Set this on stepi to diff the TRAP 40 self.execing = False # Set this on exec to diff the TRAP 41 self.pthreads = [] # Some platforms make a pthread list 42 43 self.fireTracerThread()
44
45 - def platformKill(self):
46 self.sendSignal(signal.SIGKILL)
47
48 - def sendSignal(self, signo):
49 self.requireAttached() 50 os.kill(self.pid, signo)
51
52 - def platformSendBreak(self):
53 self.sendSignal(signal.SIGTRAP) # FIXME maybe change to SIGSTOP
54
55 - def platformWait(self):
56 pid, status = os.waitpid(self.pid,0) 57 return status
58
59 - def handleAttach(self):
60 self.fireNotifiers(vtrace.NOTIFY_ATTACH) 61 self._findLibraryMaps('\x7fELF') 62 self._simpleCreateThreads() 63 # We'll emulate windows here and send an additional 64 # break after our library load events to make things easy 65 self.runAgain(False) # Clear this, if they want BREAK to run, it will 66 self.fireNotifiers(vtrace.NOTIFY_BREAK)
67
68 - def platformProcessEvent(self, status):
69 70 if os.WIFEXITED(status): 71 tid = self.getMeta("ThreadId", -1) 72 if tid != self.getPid(): 73 # Set the selected thread ID to the pid cause 74 # the old one's invalid 75 if tid in self.pthreads: 76 self.pthreads.remove(tid) 77 self.setMeta("ThreadId", self.getPid()) 78 self._fireExitThread(tid, os.WEXITSTATUS(status)) 79 else: 80 self._fireExit(os.WEXITSTATUS(status)) 81 82 elif os.WIFSIGNALED(status): 83 self.setMeta("ExitCode", os.WTERMSIG(status)) 84 self.fireNotifiers(vtrace.NOTIFY_EXIT) 85 86 elif os.WIFSTOPPED(status): 87 sig = os.WSTOPSIG(status) 88 self.handlePosixSignal(sig) 89 90 else: 91 print "OMG WTF JUST HAPPENED??!?11/!?1?>!"
92
93 - def handlePosixSignal(self, sig):
94 """ 95 Handle a basic posix signal for this trace. This was seperated from 96 platformProcessEvent so extenders could skim events and still use this logic. 97 """ 98 if sig == signal.SIGTRAP: 99 100 # Traps on posix systems are a little complicated 101 if self.stepping: 102 #FIXME try out was single step thing for intel 103 self.stepping = False 104 self._fireStep() 105 106 elif self.checkWatchpoints(): 107 return 108 109 elif self.checkBreakpoints(): 110 # It was either a known BP or a sendBreak() 111 return 112 113 elif self.execing: 114 self.execing = False 115 self.handleAttach() 116 117 else: 118 self._fireSignal(sig) 119 120 elif sig == signal.SIGSTOP: 121 #FIXME only on attaching.. 122 self.handleAttach() 123 124 else: 125 self._fireSignal(sig)
126
127 128 -class ElfMixin:
129 """ 130 A platform mixin to parse Elf binaries 131 """
132 - def __init__(self):
133 self.setMeta('Format','elf')
134
135 - def platformParseBinary(self, filename, baseaddr, normname):
136 typemap = { 137 Elf.STT_FUNC:e_resolv.FunctionSymbol, 138 Elf.STT_SECTION:e_resolv.SectionSymbol, 139 } 140 141 fd = self.platformOpenFile(filename) 142 elf = Elf.Elf(fd) 143 addbase = 0 144 if not elf.isPreLinked() and elf.isSharedObject(): 145 addbase = baseaddr 146 147 for sec in elf.sections: 148 sym = e_resolv.SectionSymbol(sec.name, sec.sh_addr+addbase, sec.sh_size, normname) 149 self.addSymbol(sym) 150 151 for sym in elf.symbols: 152 symclass = typemap.get((sym.st_info & 0xf), e_resolv.Symbol) 153 sym = symclass(sym.name, sym.st_value+addbase, sym.st_size, normname) 154 self.addSymbol(sym) 155 156 for sym in elf.dynamic_symbols: 157 symclass = typemap.get((sym.st_info & 0xf), e_resolv.Symbol) 158 sym = symclass(sym.name, sym.st_value+addbase, sym.st_size, normname) 159 self.addSymbol(sym)
160 161 # As much as I would *love* if all the ptrace defines were the same all the time, 162 # there seem to be small platform differences... 163 # These are the ones upon which most agree 164 PT_TRACE_ME = 0 # child declares it's being traced */ 165 PT_READ_I = 1 # read word in child's I space */ 166 PT_READ_D = 2 # read word in child's D space */ 167 PT_READ_U = 3 # read word in child's user structure */ 168 PT_WRITE_I = 4 # write word in child's I space */ 169 PT_WRITE_D = 5 # write word in child's D space */ 170 PT_WRITE_U = 6 # write word in child's user structure */ 171 PT_CONTINUE = 7 # continue the child */ 172 PT_KILL = 8 # kill the child process */ 173 PT_STEP = 9 # single step the child */
174 175 -def ptrace(code, pid, addr, data):
176 """ 177 The contents of this call are basically cleanly 178 passed to the libc implementation of ptrace. 179 """ 180 global libc 181 if not libc: 182 cloc = cutil.find_library("c") 183 if not cloc: 184 raise Exception("ERROR: can't find C library on posix system!") 185 libc = CDLL(cloc) 186 libc.ptrace.restype = c_size_t 187 libc.ptrace.argtypes = [c_int, c_uint32, c_size_t, c_size_t] 188 return libc.ptrace(code, pid, c_size_t(addr), c_size_t(data))
189
190 -class PtraceMixin:
191 """ 192 A platform mixin for using the ptrace functions 193 to attach/detach/continue/stepi etc. Many *nix systems 194 will probably use this... 195 196 NOTE: if you get a PT_FOO undefined, it *probably* means that 197 the PT_FOO macro isn't defined for that platform (which means 198 it need to be done another way like PT_GETREGS on darwin doesn't 199 exist... but the darwin mixin over-rides platformGetRegs) 200 """ 201
202 - def __init__(self):
203 """ 204 Setup supported modes 205 """ 206 207 self.conthack = 0 208 if sys.platform == "darwin": 209 self.conthack = 1 210 211 self.fireTracerThread()
212 213 @v_base.threadwrap
214 - def platformExec(self, cmdline):
215 self.execing = True 216 cmdlist = e_cli.splitargs(cmdline) 217 os.stat(cmdlist[0]) 218 pid = os.fork() 219 if pid == 0: 220 ptrace(PT_TRACE_ME, 0, 0, 0) 221 os.execv(cmdlist[0], cmdlist) 222 sys.exit(-1) 223 return pid
224 225 @v_base.threadwrap
226 - def platformWriteMemory(self, address, bytes):
227 wordsize = len(struct.pack("P",0)) 228 remainder = len(bytes) % wordsize 229 230 if remainder: 231 pad = self.readMemory(address+(len(bytes)-remainder), wordsize) 232 bytes += pad[remainder:] 233 234 for i in range(len(bytes)/wordsize): 235 offset = wordsize*i 236 dword = struct.unpack("L",bytes[offset:offset+wordsize])[0] 237 if ptrace(PT_WRITE_D, self.pid, long(address+offset), long(dword)) != 0: 238 raise Exception("ERROR ptrace PT_WRITE_D failed!")
239