Esempio n. 1
0
  def trace (self):
    self.type = 'list'
    self.curr = None
    self.main = gdb.eval('rb_main_thread')

    self.unwind = gdb.parameter('unwindonsignal')
    gdb.execute('set unwindonsignal on')

    gdb.execute('watch rb_curr_thread')
    gdb.breakpoints()[-1].silent = True
    num = gdb.breakpoints()[-1].number

    try:
      prev = None
      while True:
        gdb.execute('continue')
        curr = gdb.eval('rb_curr_thread')
        if curr == prev: break
        self.print_thread(curr)
        prev = curr
    except KeyboardInterrupt:
      None

    gdb.execute('delete %d' % num)
    gdb.execute('set unwindonsignal %s' % (self.unwind and 'on' or 'off'))
Esempio n. 2
0
  def invoke (self, arg, from_tty):
    self.dont_repeat()
    num = arg and int(arg) or 100
    self.setup()

    try:
      while num > 0:
        num -= 1
        gdb.execute('continue')

        frame = gdb.selected_frame()
        if frame.pc() != self.func:
          raise KeyboardInterrupt

        node = gdb.eval('(NODE*) $rsi')
        file = node['nd_file'].string()
        line = gdb.eval('nd_line(%s)' % node)
        method = gdb.eval('rb_id2name($rcx)')
        method = method > 0 and method.string() or '(unknown)'

        print "%s in %s:%d" % (method,file,line)

      self.teardown()
    except KeyboardInterrupt:
      self.teardown()
    except RuntimeError, text:
      self.teardown()
      if not re.search('signaled while in a function called from GDB', text):
        raise
Esempio n. 3
0
  def print_stack (self, th, frame, node):
    while True:
      stk_pos = th['stk_pos']
      stk_ptr = th['stk_ptr']
      stk_len = th['stk_len']
      addr = gdb.eval('(VALUE*)%s' % frame)

      if not self.is_heap_stack and th != self.curr and stk_pos < addr and addr < (stk_pos+stk_len):
        frame = (addr-stk_pos) + stk_ptr
        frame = gdb.eval('(struct FRAME *)%s' % frame)
        node = frame['node']

      file = node['nd_file'].string()
      line = gdb.eval('nd_line(%s)' % node)
      type = gdb.eval('(enum node_type) nd_type(%s)' % node)

      if frame['last_func']:
        try:
          method = gdb.eval('rb_id2name(%s)' % frame['last_func']).string()
        except:
          method = '(unknown)'
      else:
        method = '(unknown)'

      print "  ",
      print str(type).lower().center(18), "%s in %s:%d" % (method, file, line)

      if frame['prev'] == 0 or frame['last_func'] == 0: break
      frame = frame['prev']
      node = frame['node']
      if node == 0: break
Esempio n. 4
0
  def all_objects (self):
    self.heaps_used = gdb.eval('heaps_used')

    for i in xrange(self.heaps_used):
      p = gdb.eval("(RVALUE*) heaps[%i].slot" % i)
      pend = p + gdb.eval("heaps[%i].limit" % i)

      while p < pend:
        yield p, p['as']['basic']['flags']
        p += 1
Esempio n. 5
0
  def invoke (self, arg, from_tty):
    self.dont_repeat()
    cache = gdb.eval('cache')
    size = 0x800
    empty = 0

    for i in xrange(size):
      entry = cache[i]
      if entry['mid'] != 0:
        klass = gdb.eval('rb_class2name(%d)' % entry['klass'])
        method = gdb.eval('rb_id2name(%d)' % entry['mid'])
        print " %s#%s" % (klass and klass.string() or '(unknown)',  method and method.string() or '(unknown)')
      else:
        empty += 1

    print
    print "%d empty slots (%.2f%%)" % (empty, empty*100.0/size)
    print
Esempio n. 6
0
  def print_nodes (self):
    nodes = ZeroDict()

    for (obj, type) in self.live_objects():
      if type == 0x3f:
        nodes[ (int(obj['as']['node']['flags']) >> 12) & 0xff ] += 1

    for (node, num) in sorted(nodes.items(), key=lambda(k,v):(v,k)):
      print "% 8d %s" % (num, gdb.eval('(enum node_type) (%d)' % node))
Esempio n. 7
0
  def print_classes (self):
    classes = ZeroDict()

    for (obj, type) in self.live_objects():
      if type == 0x2:
        classes[ int(obj['as']['basic']['klass']) ] += 1

    for (klass, num) in sorted(classes.items(), key=lambda(k,v):(v,k)):
      print "% 8d %s" % (num, gdb.eval('rb_class2name(%d)' % klass).string())
Esempio n. 8
0
  def print_thread (self, th):
    if self.type != 'list': print
    print th,
    print th == self.main and 'main' or '    ',
    print th == self.curr and 'curr' or '    ',
    print "thread", " %s" % str(th['status']).ljust(16), "%s" % self.wait_state(th), "   ",
    if th != self.curr:
      print "% 8d bytes" % th['stk_len']
    else:
      print

    if self.type == 'list': return

    if th == self.curr:
      frame = gdb.eval('ruby_frame')
      node = gdb.eval('ruby_current_node')
    else:
      frame = th['frame']
      node = frame['node']

    self.print_stack(th, frame, node)
Esempio n. 9
0
  def invoke (self, arg, from_tty):
    self.dont_repeat()

    type = int(gdb.eval("((struct RBasic *)(%d))->flags & 0x3f" % int(arg,0)))
    rtype = RubyObjects.TYPES.get(type, 'unknown')

    if rtype == 'array':
      print rtype
    elif rtype == 'hash':
      print rtype
    else:
      print 'unknown'
Esempio n. 10
0
  def show (self):
    self.main = gdb.eval('rb_main_thread')
    self.curr = gdb.eval('rb_curr_thread')
    self.now = time.time()

    try:
      gdb.eval('rb_thread_start_2')
    except RuntimeError:
      self.is_heap_stack = False
    else:
      self.is_heap_stack = True

    if self.main == 0:
      print "Ruby VM is not running!"
    else:
      th = self.main
      while True:
        self.print_thread(th)
        th = th['next']
        if th == self.main: break

      print
Esempio n. 11
0
  def setup (self):
    commands = """
      set $func = malloc(1)
      p ((char*)$func)[0] = '\xc3'
      p mprotect(($func&0xfffffffffffff000), 1, 0x7)
      p rb_add_event_hook($func, RUBY_EVENT_C_CALL|RUBY_EVENT_CALL)
      b *$func
    """.split("\n")

    for c in commands:
      gdb.execute(c)

    gdb.breakpoints()[-1].silent = True
    self.func = gdb.eval('$func')

    self.unwind = gdb.parameter('unwindonsignal')
    gdb.execute('set unwindonsignal on')
Esempio n. 12
0
  def print_classes (self):
    classes = ZeroDict()

    for (obj, type) in self.live_objects():
      if type == 0x0:
        pass # none
      elif type == 0x3b:
        pass # blktag
      elif type == 0x3c:
        pass # undef
      elif type == 0x3d:
        pass # varmap
      elif type == 0x3e:
        pass # scope
      elif type == 0x3f:
        pass # node
      else:
        klass = obj['as']['basic']['klass']
        if klass:
          classes[ int(klass) ] += 1

    for (klass, num) in sorted(classes.items(), key=lambda(k,v):(v,k)):
      print "% 8d %s" % (num, gdb.eval('rb_class2name(%d)' % klass).string())
Esempio n. 13
0
 def invoke (self, arg, from_tty):
   self.dont_repeat()
   arg = arg.replace('\\', '\\\\').replace('"', '\\\"')
   print gdb.eval("((struct RString*)rb_eval_string_protect(\"begin; (%s).inspect; rescue Exception => e; e.inspect; end\", 0))->ptr" % arg).string()