gdb.rb 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/ext/extconf.rb +7 -7
  2. data/gdb.rb.gemspec +4 -4
  3. data/scripts/ruby-gdb.py +178 -86
  4. metadata +6 -11
@@ -11,27 +11,27 @@ end
11
11
  require 'mkmf'
12
12
  require 'fileutils'
13
13
 
14
- if RUBY_VERSION >= "1.9"
14
+ if RUBY_PLATFORM !~ /(i686|x86_64)-linux/
15
15
  STDERR.puts "\n\n"
16
16
  STDERR.puts "***************************************************************************************"
17
- STDERR.puts "************************** ruby 1.9 is not supported (yet) =( *************************"
17
+ STDERR.puts "*********************** Only x86 linux is supported (for now) =( **********************"
18
18
  STDERR.puts "***************************************************************************************"
19
19
  exit(1)
20
20
  end
21
21
 
22
- if RUBY_PLATFORM !~ /(i686|x86_64)-linux/
22
+ dir_config('python')
23
+ unless have_header('python2.5/Python.h') or have_header('python2.6/Python.h') or have_header('python2.4/Python.h')
23
24
  STDERR.puts "\n\n"
24
25
  STDERR.puts "***************************************************************************************"
25
- STDERR.puts "*********************** Only x86 linux is supported (for now) =( **********************"
26
+ STDERR.puts "***************** Python required (apt-get install python2.5-dev) =( ******************"
26
27
  STDERR.puts "***************************************************************************************"
27
28
  exit(1)
28
29
  end
29
30
 
30
- dir_config('python')
31
- unless have_header('python2.5/Python.h') or have_header('python2.6/Python.h') or have_header('python2.4/Python.h')
31
+ unless have_header('ncurses.h') or have_header('ncurses/ncurses.h')
32
32
  STDERR.puts "\n\n"
33
33
  STDERR.puts "***************************************************************************************"
34
- STDERR.puts "***************** Python required (apt-get install python2.5-dev) =( ******************"
34
+ STDERR.puts "**************** ncurses required (apt-get install libncurses5-dev) =( ****************"
35
35
  STDERR.puts "***************************************************************************************"
36
36
  exit(1)
37
37
  end
@@ -1,10 +1,10 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'gdb.rb'
3
- s.version = '0.1.5'
4
- s.date = '2010-11-04'
3
+ s.version = '0.1.6'
4
+ s.date = '2010-11-16'
5
5
  s.rubyforge_project = 'gdb-rb'
6
- s.summary = 'gdb hooks for MRI and REE'
7
- s.description = 'A set of gdb7 extensions for the MRI/REE 1.8.x interpreter'
6
+ s.summary = 'gdb hooks for MRI/REE and YARV'
7
+ s.description = 'A set of gdb7 extensions for the MRI/REE 1.8.x interpreter (and basic support for YARV 1.9.2)'
8
8
 
9
9
  s.homepage = "http://github.com/tmm1/gdb.rb"
10
10
 
@@ -234,9 +234,9 @@ class RubyObjects (gdb.Command):
234
234
  self.print_nodes()
235
235
  elif arg == 'strings':
236
236
  self.print_strings()
237
- elif arg == 'hashes':
237
+ elif Ruby.is_18 and arg == 'hashes':
238
238
  self.print_hashes()
239
- elif arg == 'arrays':
239
+ elif Ruby.is_18 and arg == 'arrays':
240
240
  self.print_arrays()
241
241
  else:
242
242
  self.print_stats()
@@ -244,24 +244,33 @@ class RubyObjects (gdb.Command):
244
244
  def complete (self, text, word):
245
245
  if text == word:
246
246
  if word == '':
247
- return ['classes', 'strings', 'nodes', 'hashes', 'arrays']
247
+ if Ruby.is_18:
248
+ return ['classes', 'nodes', 'strings', 'hashes', 'arrays']
249
+ else:
250
+ return ['classes', 'nodes', 'strings']
248
251
  elif word[0] == 'c':
249
252
  return ['classes']
250
253
  elif word[0] == 'n':
251
254
  return ['nodes']
252
255
  elif word[0] == 's':
253
256
  return ['strings']
254
- elif word[0] == 'h':
257
+ elif Ruby.is_18 and word[0] == 'h':
255
258
  return ['hashes']
256
- elif word[0] == 'a':
259
+ elif Ruby.is_18 and word[0] == 'a':
257
260
  return ['arrays']
258
261
 
259
262
  def print_nodes (self):
260
263
  nodes = ZeroDict()
261
264
 
262
265
  for (obj, type) in self.live_objects():
263
- if type == 0x3f:
264
- nodes[ (int(obj['as']['node']['flags']) >> 12) & 0xff ] += 1
266
+ if type == RubyObjects.ITYPES['node']:
267
+ if Ruby.is_18:
268
+ # for performance only, the 1.9 path below will work as well
269
+ # but requires a call to gdb.parse_and_eval
270
+ type = (int(obj['as']['node']['flags']) >> 12) & 0xff
271
+ else:
272
+ type = int(gdb.parse_and_eval('nd_type(%s)' % obj))
273
+ nodes[ type ] += 1
265
274
 
266
275
  for (node, num) in sorted(nodes.items(), key=lambda(k,v):(v,k)):
267
276
  print "% 8d %s" % (num, gdb.parse_and_eval('(enum node_type) (%d)' % node))
@@ -295,11 +304,11 @@ class RubyObjects (gdb.Command):
295
304
  bytes = 0
296
305
 
297
306
  for (obj, type) in self.live_objects():
298
- if type == 0x7:
307
+ if type == RubyObjects.ITYPES['string']:
299
308
  s = obj['as']['string']
300
- ptr = s['ptr']
301
- if ptr:
302
- bytes += s['len']
309
+ ptr = Ruby.is_18 and s['ptr'] or gdb.parse_and_eval('RSTRING_PTR(%s)' % obj)
310
+ if ptr != None:
311
+ bytes += (Ruby.is_18 and s['len'] or int(gdb.parse_and_eval('RSTRING_LEN(%s)' % obj)))
303
312
  try:
304
313
  strings[ ptr.string() ] += 1
305
314
  except:
@@ -310,7 +319,7 @@ class RubyObjects (gdb.Command):
310
319
 
311
320
  print
312
321
  print "% 9d" % len(strings), "unique strings"
313
- print "% 9d" % bytes, "bytes"
322
+ print "% 9d" % bytes, "bytes (this double counts shared strings)"
314
323
  print
315
324
 
316
325
  def print_hashes (self):
@@ -367,7 +376,7 @@ class RubyObjects (gdb.Command):
367
376
  for (obj, flags) in self.all_objects():
368
377
  if flags:
369
378
  live += 1
370
- types[ int(flags & 0x3f) ] += 1
379
+ types[ int(flags & RubyObjects.T_MASK) ] += 1
371
380
  else:
372
381
  free += 1
373
382
 
@@ -399,7 +408,7 @@ class RubyObjects (gdb.Command):
399
408
  def live_objects (self):
400
409
  for (obj, flags) in self.all_objects():
401
410
  if flags:
402
- yield obj, int(flags & 0x3f)
411
+ yield obj, int(flags & RubyObjects.T_MASK)
403
412
 
404
413
  def obj_type (self, type):
405
414
  return RubyObjects.TYPES.get(type, 'unknown')
@@ -450,104 +459,187 @@ class RubyEval (gdb.Command):
450
459
 
451
460
  def invoke (self, arg, from_tty):
452
461
  self.dont_repeat()
462
+ # check if rb_during_gc
453
463
  arg = arg.replace('\\', '\\\\').replace('"', '\\\"')
454
- print gdb.parse_and_eval("((struct RString*)rb_eval_string_protect(\"begin; (%s).inspect; rescue Exception => e; e.inspect; end\", 0))->ptr" % arg).string()
464
+ print gdb.parse_and_eval("RSTRING_PTR(rb_eval_string_protect(\"begin; (%s).inspect; rescue Exception => e; e.inspect; end\", 0))" % arg).string()
455
465
 
456
466
 
457
467
  ##
458
- # Create GDB commands
468
+ # Create common GDB commands
459
469
 
460
470
  Ruby()
461
- RubyThreads()
462
- RubyTrace()
463
- RubyObjects()
464
- RubyMethodCache()
465
- RubyPrint()
466
471
  RubyEval()
472
+ RubyObjects()
467
473
 
468
474
  ##
469
- # Detect MRI vs REE
475
+ # Detect ruby version
470
476
 
471
477
  ruby = gdb.execute("info files", to_string=True).split("\n")[0]
472
478
  ruby = re.search('"(.+)"\.?$', ruby)
473
479
  ruby = ruby.group(1)
474
480
  ruby = os.popen("%s -v" % ruby).read()
475
481
 
476
- if re.search('Enterprise', ruby):
477
- gdb.execute("macro define FL_USHIFT 12")
478
- else:
479
- gdb.execute("macro define FL_USHIFT 11")
480
-
481
482
  ##
482
- # Define common macros
483
+ # Common macros for 1.8 and 1.9
483
484
 
484
485
  macros = """
485
- macro define R_CAST(st) (struct st*)
486
- macro define RNODE(obj) (R_CAST(RNode)(obj))
487
- macro define CHAR_BIT 8
488
- macro define NODE_LSHIFT (FL_USHIFT+8)
489
- macro define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
490
- macro define nd_line(n) ((unsigned int)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK))
491
- macro define nd_type(n) ((int)(((RNODE(n))->flags>>FL_USHIFT)&0xff))
492
-
493
- macro define T_MASK 0x3f
494
- macro define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
495
-
496
- macro define WAIT_FD (1<<0)
497
- macro define WAIT_SELECT (1<<1)
498
- macro define WAIT_TIME (1<<2)
499
- macro define WAIT_JOIN (1<<3)
500
- macro define WAIT_PID (1<<4)
501
-
502
- macro define RUBY_EVENT_CALL 0x08
503
- macro define RUBY_EVENT_C_CALL 0x20
504
- """.split("\n")
486
+ #define R_CAST(st) (struct st*)
487
+ #define RBASIC(obj) (R_CAST(RBasic)(obj))
488
+ #define RSTRING(obj) (R_CAST(RString)(obj))
489
+ #define RNODE(obj) (R_CAST(RNode)(obj))
490
+
491
+ #define FL_USER0 (((VALUE)1)<<(FL_USHIFT+0))
492
+ #define FL_USER1 (((VALUE)1)<<(FL_USHIFT+1))
493
+ #define FL_USER2 (((VALUE)1)<<(FL_USHIFT+2))
494
+ #define FL_USER3 (((VALUE)1)<<(FL_USHIFT+3))
495
+ #define FL_USER4 (((VALUE)1)<<(FL_USHIFT+4))
496
+ #define FL_USER5 (((VALUE)1)<<(FL_USHIFT+5))
497
+ #define FL_USER6 (((VALUE)1)<<(FL_USHIFT+6))
498
+ #define FL_USER7 (((VALUE)1)<<(FL_USHIFT+7))
499
+ #define FL_USER8 (((VALUE)1)<<(FL_USHIFT+8))
500
+ """
501
+
502
+ ##
503
+ # Constants
504
+
505
+ Ruby.is_18 = False
506
+ Ruby.is_19 = False
507
+ Ruby.is_ree = False
508
+
509
+ ##
510
+ # Version specific macros and commands
511
+
512
+ if re.search('1\.9\.\d', ruby):
513
+ Ruby.is_19 = True
514
+ RubyObjects.T_MASK = 0x1f
515
+
516
+ ##
517
+ # Common 1.9 macros
518
+ macros += """
519
+ #define NODE_TYPESHIFT 8
520
+ #define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
521
+ #define nd_type(n) ((int) (((RNODE(n))->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
505
522
 
506
- for m in macros:
523
+ #define RSTRING_NOEMBED FL_USER1
524
+ #define RSTRING_PTR(str) (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? RSTRING(str)->as.ary : RSTRING(str)->as.heap.ptr)
525
+ #define RSTRING_EMBED_LEN_MASK (FL_USER2|FL_USER3|FL_USER4|FL_USER5|FL_USER6)
526
+ #define RSTRING_EMBED_LEN_SHIFT (FL_USHIFT+2)
527
+ #define RSTRING_LEN(str) (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? (long)((RBASIC(str)->flags >> RSTRING_EMBED_LEN_SHIFT) & (RSTRING_EMBED_LEN_MASK >> RSTRING_EMBED_LEN_SHIFT)) : RSTRING(str)->as.heap.len)
528
+
529
+ #define FL_USHIFT 12
530
+
531
+ #define GET_VM() ruby_current_vm
532
+ #define rb_objspace (*GET_VM()->objspace)
533
+ #define objspace rb_objspace
534
+
535
+ #define heaps objspace->heap.ptr
536
+ #define heaps_length objspace->heap.length
537
+ #define heaps_used objspace->heap.used
538
+ """
539
+
540
+ else:
541
+ Ruby.is_18 = True
542
+ RubyObjects.T_MASK = 0x3f
543
+
544
+ ##
545
+ # 1.8 specific ruby commands
546
+ RubyThreads()
547
+ RubyTrace()
548
+ RubyMethodCache()
549
+ RubyPrint()
550
+
551
+ ##
552
+ # Detect REE vs MRI
553
+ if re.search('Enterprise', ruby):
554
+ Ruby.is_ree = True
555
+ macros += """
556
+ #define FL_USHIFT 12
557
+ """
558
+ else:
559
+ macros += """
560
+ #define FL_USHIFT 11
561
+ """
562
+
563
+ ##
564
+ # Common 1.8 macros
565
+ macros += """
566
+ #define RSTRING_PTR(obj) (RSTRING(obj)->ptr)
567
+ #define CHAR_BIT 8
568
+ #define NODE_LSHIFT (FL_USHIFT+8)
569
+ #define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
570
+ #define nd_line(n) ((unsigned int)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK))
571
+ #define nd_type(n) ((int)(((RNODE(n))->flags>>FL_USHIFT)&0xff))
572
+
573
+ #define T_MASK 0x3f
574
+ #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
575
+
576
+ #define WAIT_FD (1<<0)
577
+ #define WAIT_SELECT (1<<1)
578
+ #define WAIT_TIME (1<<2)
579
+ #define WAIT_JOIN (1<<3)
580
+ #define WAIT_PID (1<<4)
581
+
582
+ #define RUBY_EVENT_CALL 0x08
583
+ #define RUBY_EVENT_C_CALL 0x20
584
+ """
585
+
586
+ ##
587
+ # Execute macro definitions
588
+
589
+ for m in macros.split("\n"):
507
590
  if len(m.strip()) > 0:
508
- gdb.execute(m)
591
+ gdb.execute(m.replace('#', 'macro ', 1))
509
592
 
510
593
  ##
511
594
  # Define types
512
595
 
513
- types = """
514
- T_NONE 0x00
515
-
516
- T_NIL 0x01
517
- T_OBJECT 0x02
518
- T_CLASS 0x03
519
- T_ICLASS 0x04
520
- T_MODULE 0x05
521
- T_FLOAT 0x06
522
- T_STRING 0x07
523
- T_REGEXP 0x08
524
- T_ARRAY 0x09
525
- T_FIXNUM 0x0a
526
- T_HASH 0x0b
527
- T_STRUCT 0x0c
528
- T_BIGNUM 0x0d
529
- T_FILE 0x0e
530
-
531
- T_TRUE 0x20
532
- T_FALSE 0x21
533
- T_DATA 0x22
534
- T_MATCH 0x23
535
- T_SYMBOL 0x24
536
-
537
- T_BLKTAG 0x3b
538
- T_UNDEF 0x3c
539
- T_VARMAP 0x3d
540
- T_SCOPE 0x3e
541
- T_NODE 0x3f
542
- """.split("\n")
543
-
544
596
  RubyObjects.TYPES = {}
545
597
 
546
- for t in types:
547
- if len(t.strip()) > 0:
548
- name, val = t.split()
549
- gdb.execute("macro define %s %s" % (name, val))
550
- RubyObjects.TYPES[int(val,16)] = name[2:].lower()
598
+ if Ruby.is_19:
599
+ for t in gdb.lookup_type('enum ruby_value_type').fields():
600
+ name = t.name
601
+ val = int(gdb.parse_and_eval(name))
602
+ gdb.execute("macro define %s %s" % (name[5:], val))
603
+ RubyObjects.TYPES[val] = name[7:].lower()
604
+ else:
605
+ types = """
606
+ T_NONE 0x00
607
+
608
+ T_NIL 0x01
609
+ T_OBJECT 0x02
610
+ T_CLASS 0x03
611
+ T_ICLASS 0x04
612
+ T_MODULE 0x05
613
+ T_FLOAT 0x06
614
+ T_STRING 0x07
615
+ T_REGEXP 0x08
616
+ T_ARRAY 0x09
617
+ T_FIXNUM 0x0a
618
+ T_HASH 0x0b
619
+ T_STRUCT 0x0c
620
+ T_BIGNUM 0x0d
621
+ T_FILE 0x0e
622
+
623
+ T_TRUE 0x20
624
+ T_FALSE 0x21
625
+ T_DATA 0x22
626
+ T_MATCH 0x23
627
+ T_SYMBOL 0x24
628
+
629
+ T_BLKTAG 0x3b
630
+ T_UNDEF 0x3c
631
+ T_VARMAP 0x3d
632
+ T_SCOPE 0x3e
633
+ T_NODE 0x3f
634
+ """.split("\n")
635
+
636
+ for t in types:
637
+ if len(t.strip()) > 0:
638
+ name, val = t.split()
639
+ gdb.execute("macro define %s %s" % (name, val))
640
+ RubyObjects.TYPES[int(val,16)] = name[2:].lower()
641
+
642
+ RubyObjects.ITYPES = dict([[v,k] for k,v in RubyObjects.TYPES.items()])
551
643
 
552
644
  ##
553
645
  # Set GDB options
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdb.rb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 1
9
- - 5
10
- version: 0.1.5
8
+ - 6
9
+ version: 0.1.6
11
10
  platform: ruby
12
11
  authors:
13
12
  - Aman Gupta
@@ -15,11 +14,11 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-11-04 00:00:00 -07:00
17
+ date: 2010-11-16 00:00:00 -05:00
19
18
  default_executable:
20
19
  dependencies: []
21
20
 
22
- description: A set of gdb7 extensions for the MRI/REE 1.8.x interpreter
21
+ description: A set of gdb7 extensions for the MRI/REE 1.8.x interpreter (and basic support for YARV 1.9.2)
23
22
  email: gdb@tmm1.net
24
23
  executables:
25
24
  - gdb.rb
@@ -47,29 +46,25 @@ rdoc_options: []
47
46
  require_paths:
48
47
  - lib
49
48
  required_ruby_version: !ruby/object:Gem::Requirement
50
- none: false
51
49
  requirements:
52
50
  - - ">="
53
51
  - !ruby/object:Gem::Version
54
- hash: 3
55
52
  segments:
56
53
  - 0
57
54
  version: "0"
58
55
  required_rubygems_version: !ruby/object:Gem::Requirement
59
- none: false
60
56
  requirements:
61
57
  - - ">="
62
58
  - !ruby/object:Gem::Version
63
- hash: 3
64
59
  segments:
65
60
  - 0
66
61
  version: "0"
67
62
  requirements: []
68
63
 
69
64
  rubyforge_project: gdb-rb
70
- rubygems_version: 1.3.7
65
+ rubygems_version: 1.3.6
71
66
  signing_key:
72
67
  specification_version: 3
73
- summary: gdb hooks for MRI and REE
68
+ summary: gdb hooks for MRI/REE and YARV
74
69
  test_files: []
75
70