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

Source Code for Module vtrace.platforms.gdbstub

  1  ''' 
  2  GDB support 
  3  ''' 
  4  import os 
  5  import re 
  6  import code 
  7  import time 
  8  import socket 
  9  import struct 
 10  import platform 
 11  import tempfile 
 12   
 13  import PE 
 14  import vdb 
 15  import envi 
 16  import envi.bits as e_bits 
 17  import envi.resolver as e_resolv 
 18  import vtrace 
 19   
 20  import envi.registers as e_registers 
 21  import vtrace.platforms.base as v_base 
 22   
 23  ''' 
 24  VMWare config options... 
 25  debugStub.listen.guest64 = "TRUE" # ends up on port 8864 (or next avail) 
 26  debugStub.listen.guest32 = "TRUE" # ....            8832 
 27   
 28  debugStub.listen.guest32.remote = "TRUE" 
 29   
 30  debugStub.hideBreakpoints = "TRUE" # Enable breakpoints 
 31   
 32  From GDB stuff...   
 33  ===== i386  
 34  src/gdb/i386-tdep.c 
 35  src/gdb/regformats/reg-i386.dat 
 36  ===== amd64 
 37  src/gdb/amd64-tdep.c 
 38  src/gdb/regformats/reg-x86-64.dat 
 39  ===== arm 
 40  name:arm 
 41  expedite:r11,sp,pc 
 42  32:r0 
 43  32:r1 
 44  32:r2 
 45  32:r3 
 46  32:r4 
 47  32:r5 
 48  32:r6 
 49  32:r7 
 50  32:r8 
 51  32:r9 
 52  32:r10 
 53  32:r11 
 54  32:r12 
 55  32:sp 
 56  32:lr 
 57  32:pc 
 58  96:f0 
 59  96:f1 
 60  96:f2 
 61  96:f3 
 62  96:f4 
 63  96:f5 
 64  96:f6 
 65  96:f7 
 66  32:fps 
 67  32:cpsr 
 68  ''' 
 69   
 70  gdb_reg_defs = { 
 71      'i386': ( 
 72          ['eax','ecx','edx','ebx','esp','ebp','esi','edi','eip','eflags','cs','ss','ds','es','fs','gs' 
 73          ], 
 74          '<16I' 
 75      ), 
 76   
 77      'amd64': ( 
 78          ['rax','rbx','rcx','rdx','rsi','rdi','rbp','rsp', 
 79           'r8','r9','r10','r11','r12','r13','r14','r15','rip', 
 80           'eflags','cs','ss','ds','es','fs','gs', 
 81           #'st0','st1','st2','st3','st4','st5','st6','st7', 
 82           #'fctrl','fstat','ftag','fiseg','fioff','foseg','fooff','fop' 
 83          ], 
 84   
 85          #'<17Q7L' + ('10s' * 8) + '8L' 
 86          '<17Q7L' 
 87      ), 
 88   
 89      # FIXME we will need arm flavors... 
 90      'arm': ( 
 91          ["r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","sl","fp","ip","sp", 
 92           "lr","pc", None, "cpsr"], 
 93          '<16I96sI' 
 94      ), 
 95  } 
 96   
 97  exit_types = ('X', 'W') 
 98   
99 -def pkt(cmd):
100 return '$%s#%.2x' % (cmd, csum(cmd))
101
102 -def csum(bytes):
103 sum = 0 104 for b in bytes: 105 sum += ord(b) 106 return sum & 0xff
107 108 SIGINT = 2 109 SIGTRAP = 5 110 111 trap_sigs = (SIGINT, SIGTRAP) 112
113 -class GdbServerDisconnected(Exception):
114 pass
115
116 -class KeBugCheckBreak(vtrace.Breakpoint):
117
118 - def __init__(self, symname):
119 vtrace.Breakpoint.__init__(self, None, expression=symname) 120 self.fastbreak = True
121
122 - def notify(self, event, trace):
123 sp = trace.getStackCounter() 124 savedpc, exccode = trace.readMemoryFormat(sp, '<PP') 125 trace._fireSignal(exccode)
126
127 -class GdbStubMixin:
128
129 - def __init__(self, host=None, port=None):
130 self._gdb_host = host 131 self._gdb_port = port 132 self._gdb_sock = None 133 134 self._gdb_filemagic = None # Tracers may use this to trigger _findLibraryMaps 135 136 # These get set by _gdbSetRegisterInfo 137 self._gdb_regfmt = '' 138 self._gdb_regsize = 0 139 self._gdb_reg_xlat = [] 140 self._gdb_regnames = [] 141 142 self.breaking = False
143
144 - def _recvUntil(self, c):
145 ret = '' 146 while not ret.endswith(c): 147 x = self._gdb_sock.recv(1) 148 if len(x) == 0: 149 raise Exception('socket closed prematurely!') 150 ret += x 151 return ret
152
153 - def _recvPkt(self):
154 b = self._gdb_sock.recv(1) 155 if len(b) == 0: 156 raise GdbServerDisconnected() 157 158 if b != '$': 159 raise Exception('Invalid Pkt Beginning! ->%s<-' % b) 160 161 bytes = self._recvUntil('#') 162 bytes = bytes[:-1] 163 164 isum = int(self._gdb_sock.recv(2), 16) 165 ssum = csum(bytes) 166 if isum != ssum: 167 raise Exception('Invalid Checksum! his: 0x%.2x ours: 0x%.2x' % (isum, ssum)) 168 169 self._gdb_sock.sendall('+') 170 171 #print 'RECV: ->%s<-' % bytes 172 return bytes
173
174 - def _cmdTransact(self, cmd):
175 self._sendPkt(cmd) 176 return self._recvPkt()
177
178 - def _sendPkt(self, cmd):
179 #print 'SEND: ->%s<-' % cmd 180 self._gdb_sock.sendall(pkt(cmd)) 181 b = self._gdb_sock.recv(1) 182 if b != '+': 183 raise Exception('Retrans! ->%s<-' % b)
184
185 - def _connectSocket(self):
186 if self._gdb_sock != None: 187 self._gdb_sock.shutdown(2) 188 189 tries = 0 190 while tries < 10: 191 self._gdb_sock = socket.socket() 192 try: 193 self._gdb_sock.connect( (self._gdb_host, self._gdb_port) ) 194 195 # Some gdb stubs seem to send/expect an initial '+' 196 try: 197 self._gdb_sock.settimeout(1) 198 self._gdb_sock.recv(1) 199 self._gdb_sock.sendall('+') 200 201 except socket.timeout, t: 202 pass 203 204 self._gdb_sock.settimeout(None) 205 break 206 207 except Exception, e: 208 time.sleep(0.2) 209 tries += 1
210
211 - def _monitorCommand(self, cmd):
212 resp = '' 213 cmd = 'qRcmd,%s' % cmd.encode('hex') 214 pkt = self._cmdTransact(cmd) 215 while not pkt.startswith('OK'): 216 self._raiseIfError(pkt) 217 if not pkt.startswith('O'): 218 return pkt.decode('hex') 219 resp += pkt[1:].decode('hex') 220 pkt = self._recvPkt() 221 return resp
222
223 - def platformAttach(self, pid):
224 self._connectSocket() 225 self.attaching = True 226 # Wait for the debug stub to stop the target 227 while True: 228 pkt = self._cmdTransact('?') 229 if len(pkt) == 0: 230 raise Exception('Attach Response Error!') 231 232 if int(pkt[1:3], 16) == 0: 233 import time 234 time.sleep(0.1) 235 self.platformSendBreak() 236 pkt = self._cmdTransact('?') 237 break 238 self._sendPkt('?')
239
240 - def platformContinue(self):
241 sig = self.getCurrentSignal() 242 cmd = 'c' 243 if sig != None: 244 cmd = 'C%.2x' % sig 245 self._sendPkt(cmd)
246 #self._cmdTransact(cmd) 247
248 - def platformStepi(self):
249 # FIXME by selected thread? and address? 250 #self._cmdTransact('s') 251 self._sendPkt('s') 252 self.stepping = True
253
254 - def platformDetach(self):
255 if not self.running: 256 self.platformContinue() 257 self._gdb_sock.shutdown(2) 258 self._gdb_sock = None
259
260 - def platformSendBreak(self):
261 ''' 262 For now, the only way I know how to re-break the target 263 is to disconnect and re-connect... TOTALLY GHETTO HACK! 264 ''' 265 # If this isn't a break during attach, tell everybody we are 266 # breaking... 267 if not self.attaching: 268 self.breaking = True 269 self._gdb_sock.sendall('\x03')
270
271 - def platformWait(self):
272 while True: 273 pkt = self._recvPkt() 274 if pkt.startswith('O'): 275 print 'GDBSTUB SAID: %s' % pkt[1:].decode('hex') 276 continue 277 break 278 return pkt
279
280 - def platformProcessEvent(self, event):
281 #print 'EVENT ->%s<-' % event 282 283 if len(event) == 0: 284 self.setMeta('ExitCode', 0xffffffff) 285 self.fireNotifiers(vtrace.NOTIFY_EXIT) 286 self._gdb_sock.shutdown(2) 287 self._gdb_sock = None 288 return 289 290 atype = event[0] 291 signo = int(event[1:3], 16) 292 293 # Is this a thread specific signal? 294 if atype == 'T': 295 296 #print 'SIGNAL',sig 297 298 dictbytes = event[3:] 299 300 evdict = {} 301 for kvstr in dictbytes.split(';'): 302 if not kvstr: break 303 #print 'KVSTR ->%s<-' % kvstr 304 key, value = kvstr.split(':', 1) 305 evdict[key.lower()] = value 306 307 # Did we get a specific thread? 308 tidstr = evdict.get('thread') 309 if tidstr != None: 310 tid = int(tidstr, 16) 311 self.setMeta('ThreadId', tid) 312 #else: 313 #print "WE SHOULD ASK FOR THE CURRENT THREAD HERE!" 314 315 elif atype == 'S': 316 pass 317 318 elif atype in exit_types: 319 320 # Fire an exit event and GTFO! 321 self._fireExit(signo) 322 return 323 324 else: 325 print 'Unhandled Gdb Server Event: %s' % event 326 327 #if self.attaching and signo in trap_sigs: 328 if self.attaching: 329 self.attaching = False 330 #self._enumGdbTarget() 331 if self._gdb_filemagic: 332 self._findLibraryMaps(self._gdb_filemagic, always=True) 333 self._simpleCreateThreads() 334 self.runAgain(False) # Clear this, if they want BREAK to run, it will 335 self.fireNotifiers(vtrace.NOTIFY_BREAK) 336 337 elif self.breaking and signo in trap_sigs: 338 self.breaking = False 339 self.fireNotifiers(vtrace.NOTIFY_BREAK) 340 341 # Process the signal and decide what to do... 342 elif signo == SIGTRAP: 343 344 # Traps on posix systems are a little complicated 345 if self.stepping: 346 #FIXME try out was single step thing for intel 347 self.stepping = False 348 self.fireNotifiers(vtrace.NOTIFY_STEP) 349 350 elif self.checkBreakpoints(): 351 return 352 353 #elif self.checkWatchpoints(): 354 #return 355 356 #elif self.checkBreakpoints(): 357 # It was either a known BP or a sendBreak() 358 #return 359 360 #elif self.execing: 361 ##self.execing = False 362 #self.handleAttach() 363 364 else: 365 self._fireSignal(signo) 366 367 #elif signo == signal.SIGSTOP: 368 #self.handleAttach() 369 370 else: 371 self._fireSignal(signo)
372
373 - def _gdbCreateThreads(self):
374 initid = self.getMeta('ThreadId') 375 for tid in self.platformGetThreads().keys(): 376 self.setMeta('ThreadId', tid) 377 self.fireNotifiers(vtrace.NOTIFY_CREATE_THREAD) 378 self.setMeta('ThreadId', initid)
379
380 - def _gdbSetRegisterInfo(self, fmt, names):
381 # Used by the Trace implementations to tell the gdb 382 # stub code how to unpack the register buf 383 384 self._gdb_regfmt = fmt 385 self._gdb_regnames = names 386 387 self._gdb_reg_xlat = [] 388 self._gdb_regsize = struct.calcsize(fmt) 389 390 391 for i,name in enumerate(names): 392 if name == None: # So we can skip parts of the gdb definition... 393 continue 394 j = self.getRegisterIndex(name) 395 if j != None: 396 self._gdb_reg_xlat.append( (i, j) )
397
398 - def platformGetRegCtx(self, tid):
399 ''' 400 Get an envi register context from the target stub. 401 ''' 402 # FIXME tid! 403 regbuf = self._cmdTransact('g') 404 regbytes = self._runLengthDecode(regbuf) 405 rvals = struct.unpack(self._gdb_regfmt, regbytes[:self._gdb_regsize]) 406 ctx = self.arch.archGetRegCtx() 407 for myidx, enviidx in self._gdb_reg_xlat: 408 ctx.setRegister(enviidx, rvals[myidx]) 409 return ctx
410
411 - def platformSetRegCtx(self, tid, ctx):
412 ''' 413 Set the target stub's register context from the envi register context 414 ''' 415 # FIXME tid! 416 regbytes = self._cmdTransact('g').decode('hex') 417 regremain = regbytes[self._gdb_regsize:] 418 rvals = struct.unpack(self._gdb_regfmt, regbytes[:self._gdb_regsize]) 419 rvals = list(rvals) # So we can assign to them... 420 for myidx, enviidx in self._gdb_reg_xlat: 421 rvals[myidx] = ctx.getRegister(enviidx) 422 newbytes = struct.pack(self._gdb_regfmt, rvals) + regremain 423 return self._cmdTransact('G'+newbytes.encode('hex'))
424
425 - def platformGetThreads(self):
426 427 ret = {} 428 429 self._sendPkt('qfThreadInfo') 430 tbytes = self._recvPkt() 431 432 while tbytes.startswith('m'): 433 434 if tbytes.find(','): 435 for bval in tbytes[1:].split(','): 436 ret[int(bval, 16)] = 0 437 else: 438 ret[int(tbytes[1:], 16)] = 0 439 440 self._sendPkt('qsThreadInfo') 441 tbytes = self._recvPkt() 442 443 return ret
444
445 - def _raiseIfError(self, msg):
446 if msg.startswith('E'): 447 raise Exception('Error: %s' % msg)
448
449 - def _runLengthDecode(self, buf):
450 # GDB RSP implements some run-length encoding to save space 451 i = buf.find('*') 452 while i != -1: 453 cnt = ord(buf[i+1]) - 29 # Run-length encoding is minus 29... 454 pad = buf[i-1] * cnt 455 buf = buf[:i] + pad + buf[i+2:] 456 457 i = buf.find('*') 458 459 return buf.decode('hex')
460
461 - def platformReadMemory(self, addr, size):
462 mbytes = '' 463 offset = 0 464 while len(mbytes) < size: 465 # FIXME is this 256 problem just in the VMWare gdb stub? 466 cmd = 'm%x,%x' % (addr + offset, min(256, size-offset)) 467 pkt = self._cmdTransact(cmd) 468 self._raiseIfError(pkt) 469 pbytes = self._runLengthDecode(pkt) 470 offset += len(pbytes) 471 mbytes += pbytes 472 return mbytes
473
474 - def platformWriteMemory(self, addr, mbytes):
475 cmd = 'M%x,%x:%s' % (addr, len(mbytes), mbytes.encode('hex')) 476 pkt = self._cmdTransact(cmd) 477 self._raiseIfError(pkt)
478
479 - def platformGetMaps(self):
480 return []
481 482 # FROM HERE DOWN IS ALL CRAP THAT IS STILL GETTING SORTED OUT 483
484 -class GdbStubMixin_old(e_registers.RegisterContext):
485
486 - def __init__(self):
487 488 self.stepping = False 489 self.attaching = False 490 self.breaking = False 491 492 self.bigmask = e_bits.u_maxes[ self.getPointerSize() ] 493 494 aname = self.getMeta('Architecture') 495 self._addArchNamespace(aname) 496 497 self.setMeta('Platform', 'gdbstub') 498 499 self.setMeta('GdbServerHost', 'localhost') 500 self.setMeta('GdbServerPort', 0) 501 self.setMeta('GdbPlatform', 'Unknown') 502 self.setMeta('GdbTargetPlatform', 'Unknown') 503 504 self.setMeta('BinaryFormat', None) 505 506 arch_reg_info = gdb_reg_defs.get(aname) 507 if arch_reg_info == None: 508 raise Exception('We dont know the GDB register definition for arch: %s' % name) 509 510 self._arch_regnames, self._arch_regfmt = arch_reg_info 511 self._arch_regsize = struct.calcsize(self._arch_regfmt) 512 513 self._arch_rctx = self.arch.archGetRegCtx() 514 self._arch_reg_xlat = [] 515 for i,name in enumerate(self._arch_regnames): 516 if name == None: # So we can skip parts of the gdb definition... 517 continue 518 j = self._arch_rctx.getRegisterIndex(name) 519 if j != None: 520 self._arch_reg_xlat.append((i,j)) 521 522 # Load up our register definition! 523 e_registers.RegisterContext.__init__(self) 524 rinfo = self._arch_rctx.getRegisterInfo(meta=True) 525 self.setRegisterInfo(rinfo)
526
527 - def _addArchNamespace(self, aname):
528 if aname == 'arm': 529 import vstruct.defs.arm7 as vs_arm7 530 self.vsbuilder.addVStructNamespace('arm7', vs_arm7)
531
532 - def normFileName(self, fname):
533 # We don't know if it's / or \ ... do both! 534 basename = fname.split('/')[-1].split('\\')[-1] 535 return basename.split(".")[0].split("-")[0].lower()
536
537 - def platformParseBinary(self, filename, baseaddr, normname):
538 print 'platformParseBinary: 0x%.8x %s' % (baseaddr, normname)
539
540 - def platformParseBinaryPe(self, filename, baseaddr, normname):
541 542 # If we're on windows, fake out the PE header and use dbghelp 543 #if platform.system() in ['Microsoft', 'Windows']: 544 if False: 545 # FIXME this code is stolen and should be a function! 546 import vtrace.platforms.win32 as vt_win32 547 fakepe = self.readMemory(baseaddr, 1024) 548 tfile = tempfile.NamedTemporaryFile(delete=False) 549 tfilename = tfile.name 550 import ctypes 551 pebuf = ctypes.create_string_buffer(fakepe) 552 try: 553 try: 554 tfile.write(fakepe) 555 tfile.close() 556 #parser = vt_win32.Win32SymbolParser(-1, tfilename, baseaddr) 557 parser = vt_win32.Win32SymbolParser(-1, None, ctypes.addressof(pebuf)) 558 parser.parse() 559 parser.loadSymsIntoTrace(self, normname) 560 finally: 561 os.unlink(tfilename) 562 except Exception, e: 563 print e 564 565 else: 566 pe = PE.peFromMemoryObject(self, baseaddr) 567 for rva, ord, name in pe.getExports(): 568 self.addSymbol(e_resolv.Symbol(name, baseaddr+rva, 0, normname))
569
570 - def platformPs(self):
571 return [ (1, 'SystemProcess'), ]
572
573 - def _getVmwareReg(self, rname):
574 ''' 575 Use VMWare's monitor extension to get a register we wouldn't 576 normally have... 577 ''' 578 #fs 0x30 base 0xffdff000 limit 0x00001fff type 0x3 s 1 dpl 0 p 1 db 1 579 fsstr = self._monitorCommand('r %s' % rname) 580 fsparts = fsstr.split() 581 return int(fsparts[3], 16)
582
583 - def _getVmwareIdtr(self):
584 istr = self._monitorCommand('r idtr') 585 m = re.match('.* base=(0x\w+) .*', istr) 586 idtr = long(m.groups()[0], 0) 587 return idtr
588
589 - def _getNtOsKrnl(self, idtr):
590 x1, kptr, x2 = self.readMemoryFormat(idtr, '<IQI') 591 try: 592 kptr -= kptr & 0xfff 593 while not self.readMemory(kptr, 16).startswith('MZ\x90\x00'): 594 kptr -= 4096 595 return kptr 596 except Exception, e: 597 return None
598
599 - def _enumTargetOs(self, fsbase):
600 601 self.setVariable('fsbase', fsbase) 602 603 fs_fields = self.readMemoryFormat(fsbase, '<8I') 604 605 # Windows has a self reference in the KPCR... 606 if fs_fields[7] == fsbase: 607 608 # Use KPCR from XP for now... 609 import vstruct.defs.windows.win_5_1_i386.ntoskrnl as vs_w_ntoskrnl 610 self.vsbuilder.addVStructNamespace('nt', vs_w_ntoskrnl) 611 612 self.setMeta('GdbTargetPlatform', 'Windows') 613 self.casesens = False 614 615 kpcr = self.getStruct('nt.KPCR', fsbase) 616 kver = self.getStruct('nt.DBGKD_GET_VERSION64', kpcr.KdVersionBlock) 617 618 #print kpcr.tree() 619 #print kver.tree() 620 621 kernbase = kver.KernBase & self.bigmask 622 modlist = kver.PsLoadedModuleList & self.bigmask 623 624 self.setVariable('PsLoadedModuleList', modlist) 625 self.setVariable('KernelBase', kernbase) 626 627 self.platformParseBinary = self.platformParseBinaryPe 628 629 self.fireNotifiers(vtrace.NOTIFY_ATTACH) 630 631 self.addLibraryBase('nt', kernbase, always=True) 632 ldr_entry = self.readMemoryFormat(modlist, '<I')[0] 633 while ldr_entry != modlist: 634 ldte = self.getStruct('nt.LDR_DATA_TABLE_ENTRY', ldr_entry) 635 dllname = self.readMemory(ldte.FullDllName.Buffer, ldte.FullDllName.Length).decode('utf-16le') 636 dllbase = ldte.DllBase & self.bigmask 637 self.addLibraryBase(dllname, dllbase, always=True) 638 ldr_entry = ldte.InLoadOrderLinks.Flink & self.bigmask 639 640 try: 641 self.addBreakpoint(KeBugCheckBreak('nt.KeBugCheck')) 642 except Exception, e: 643 print 'Error Seting KeBugCheck Bp: %s' % e 644 645 try: 646 self.addBreakpoint(KeBugCheckBreak('nt.KeBugCheckEx')) 647 except Exception, e: 648 print 'Error Seting KeBugCheck Bp: %s' % e 649 650 else: 651 # FIXME enumerate non-windows OSs! 652 self.fireNotifiers(vtrace.NOTIFY_ATTACH)
653
654 - def _enumGdbTarget(self):
655 psize = self.getPointerSize() 656 vercmd = self._monitorCommand('version') 657 658 monhelp = self._monitorCommand('help') 659 660 if monhelp.find('netdev_add') != -1: 661 662 self.setMeta('GdbPlatform', 'Qemu32') 663 664 fsbase = None 665 monreg = self._monitorCommand('info registers') 666 for line in monreg.split('\n'): 667 if not line.startswith('FS'): 668 continue 669 parts = line.split() 670 fsbase = int(parts[2], 16) 671 break 672 673 self._enumTargetOs(fsbase) 674 #print monreg 675 #m = re.match('FS =\w+ (\w+)', monreg, re.G) 676 #fsbase = long(m.groups()[0], 0) 677 #print 'FSBASE',hex(fsbase) 678 679 elif monhelp.find('linuxoffsets') != -1: 680 681 self.setMeta('GdbPlatform', 'VMware%d' % (psize * 8)) 682 683 if psize == 4: # Use the fs register to get KPCR 684 fsbase = self._getVmwareReg('fs') 685 self._enumTargetOs(fsbase) 686 687 else: # FIXME 64bit vmware! 688 689 idtr = self._getVmwareIdtr() 690 self.setVariable('idtr', idtr) 691 692 win_kpcr = 0x07fffffde000 693 694 fields = [-1,] 695 try: 696 fields = self.readMemoryFormat(win_kpcr, '<7Q') 697 except Exception, e: 698 print 'Exception:',e 699 700 # FIXME other heuristics for linux/bsd/etc... 701 if fields[-1] == win_kpcr: 702 self._initWin64(win_kpcr) 703 else: 704 self.fireNotifiers(vtrace.NOTIFY_ATTACH) 705 706 #fsbase = self._getVmwareReg('fs') 707 #self.setVariable('fsbase', fsbase) 708 709 #fs_fields = self.readMemoryFormat(fsbase, '<8I') 710 711 #nt = self._getNtOsKrnl(idtr) 712 #if nt != None: 713 # We are 64bit windows! 714 #import vstruct.defs.windows.win_6_1_amd64.ntoskrnl as vs_w_ntoskrnl 715 #self.vsbuilder.addVStructNamespace('nt', vs_w_ntoskrnl) 716 #self.setMeta('GdbTargetPlatform', 'Windows') 717 #self.setVariable('KernelBase', nt) 718 #self.platformParseBinary = self.platformParseBinaryPe 719 #self.fireNotifiers(vtrace.NOTIFY_ATTACH) 720 #self.addLibraryBase('nt', nt, always=True) 721 722 #else: 723 724 elif vercmd.lower().find('open on-chip debugger') != -1: 725 726 self.setMeta('GdbPlatform', 'OpenOCD') 727 self.fireNotifiers(vtrace.NOTIFY_ATTACH) 728 729 else: 730 print 'Unidentified gdbstub: %s' % vercmd 731 self.fireNotifiers(vtrace.NOTIFY_ATTACH)
732 733 734 # FIXME implement getRegister(idx) and steal get/set for regs which are not part of the whole...
735 - def _initWin64(self, kpcr):
736 737 import vstrct.defs.windows.win_6_1_amd64.ntoskrnl as vs_w_ntoskrnl 738 self.vsbuilder.addVStructNamespace('nt', vs_w_ntoskrnl) 739 self._initWinBase()
740 #nt = self._getNtOsKrnl(idtr) 741 #if nt != None: 742 # We are 64bit windows! 743 #import vstruct.defs.windows.win_6_1_amd64.ntoskrnl as vs_w_ntoskrnl 744 #self.vsbuilder.addVStructNamespace('nt', vs_w_ntoskrnl) 745 #self.setMeta('GdbTargetPlatform', 'Windows') 746 #self.setVariable('KernelBase', nt) 747 #self.platformParseBinary = self.platformParseBinaryPe 748 #self.fireNotifiers(vtrace.NOTIFY_ATTACH) 749 #self.addLibraryBase('nt', nt, always=True) 750
751 - def _initWinBase(self, kpcr):
752 753 self.setMeta('GdbTargetPlatform', 'Windows') 754 self.casesens = False 755 756 kpcr = self.getStruct('nt.KPCR', kpcr) 757 kver = self.getStruct('nt.DBGKD_GET_VERSION64', kpcr.KdVersionBlock) 758 759 kernbase = kver.KernBase & self.bigmask 760 modlist = kver.PsLoadedModuleList & self.bigmask 761 762 self.setVariable('PsLoadedModuleList', modlist) 763 self.setVariable('KernelBase', kernbase) 764 765 self.platformParseBinary = self.platformParseBinaryPe 766 767 self.fireNotifiers(vtrace.NOTIFY_ATTACH) 768 769 self.addLibraryBase('nt', kernbase, always=True) 770 ldr_entry = self.readMemoryFormat(modlist, '<P')[0] 771 while ldr_entry != modlist: 772 ldte = self.getStruct('nt.LDR_DATA_TABLE_ENTRY', ldr_entry) 773 dllname = self.readMemory(ldte.FullDllName.Buffer, ldte.FullDllName.Length).decode('utf-16le') 774 dllbase = ldte.DllBase & self.bigmask 775 self.addLibraryBase(dllname, dllbase, always=True) 776 ldr_entry = ldte.InLoadOrderLinks.Flink & self.bigmask 777 778 try: 779 self.addBreakpoint(KeBugCheckBreak('nt.KeBugCheck')) 780 except Exception, e: 781 print 'Error Seting KeBugCheck Bp: %s' % e 782 783 try: 784 self.addBreakpoint(KeBugCheckBreak('nt.KeBugCheckEx')) 785 except Exception, e: 786 print 'Error Seting KeBugCheck Bp: %s' % e
787 788 789 GDB_BP_SOFTWARE = 0 790 GDB_BP_HARDWARE = 1 791 GDB_BP_WATCH_WRITE = 2 792 GDB_BP_WATCH_READ = 3 793 GDB_BP_WATCH_ACCESS = 4 794
795 -class GdbStubTrace( 796 vtrace.Trace, 797 GdbStubMixin, 798 v_base.TracerBase):
799
800 - def __init__(self, archname):
801 802 # First things first, lets steal ourself an arch! 803 envi.stealArchMethods(self, archname) 804 vtrace.Trace.__init__(self, archname=archname) 805 v_base.TracerBase.__init__(self) 806 GdbStubMixin.__init__(self) 807 808 self._break_after_bp = False # We break *at* the bp
809 810 # FIXME this should have a cleaner abstraction to allow for stuff... 811 # platformActivateBreak / Watch! 812 # platformDeactivateBreak / Watch! 813 814 # FIXME we also need cleaner abstraction for checkBreakpoints 815 # (some platforms stop *on* break and some stop *after...) 816
817 - def _activateBreak(self, bp):
818 # For now, we don't support watchpoints... 819 if not bp.active: 820 addr = bp.resolveAddress(self) 821 self._cmdTransact('Z%d,%x,%x' % (GDB_BP_SOFTWARE,addr,1))
822
823 - def _cleanupBreakpoints(self, force=False):
824 ''' 825 Cleanup any non-fastbreak breakpoints. This routine doesn't even get 826 called in the event of mode FastBreak=True. 827 ''' 828 self.fb_bp_done = False 829 for bp in self.breakpoints.itervalues(): 830 # No harm in calling deactivate on 831 # an inactive bp 832 if force or not bp.fastbreak: 833 self._cmdTransact('z%d,%x,%x' % (GDB_BP_SOFTWARE,bp.getAddress(),1)) 834 bp.active = False
835 #bp.deactivate(self) 836
837 - def _checkForBreak(self):
838 """ 839 Check to see if we've landed on a breakpoint, and if so 840 deactivate and step us past it. 841 842 WARNING: Unfortunatly, cause this is used immidiatly before 843 a call to run/wait, we must block briefly even for the GUI 844 """ 845 # Steal a reference because the step should 846 # clear curbp... 847 bp = self.curbp 848 if bp != None and bp.isEnabled(): 849 # We had to remove a check for active and a deactivate here... 850 orig = self.getMode("FastStep") 851 self.setMode("FastStep", True) 852 self.stepi() 853 self.setMode("FastStep", orig) 854 self._activateBreak(bp)
855
856 - def buildNewTrace(self):
857 arch = self.getMeta('Architecture') 858 newt = GdbStubTrace(arch) 859 newt.setMeta('GdbServerHost', self.getMeta('GdbServerHost')) 860 newt.setMeta('GdbServerPort', self.getMeta('GdbServerPort')) 861 return newt
862