readapt 0.7.1 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -14
  3. data/.rspec +2 -2
  4. data/.travis.yml +18 -13
  5. data/CHANGELOG.md +76 -53
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +21 -21
  8. data/README.md +37 -29
  9. data/Rakefile +14 -25
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/exe/readapt +5 -5
  13. data/ext/readapt/breakpoints.c +83 -88
  14. data/ext/readapt/breakpoints.h +11 -12
  15. data/ext/readapt/extconf.rb +0 -0
  16. data/ext/readapt/frame.c +137 -0
  17. data/ext/readapt/frame.h +17 -0
  18. data/ext/readapt/hash_table.c +211 -212
  19. data/ext/readapt/hash_table.h +30 -32
  20. data/ext/readapt/inspector.c +51 -0
  21. data/ext/readapt/inspector.h +8 -0
  22. data/ext/readapt/monitor.c +40 -27
  23. data/ext/readapt/monitor.h +0 -0
  24. data/ext/readapt/normalize.c +59 -53
  25. data/ext/readapt/normalize.h +7 -7
  26. data/ext/readapt/readapt.c +18 -16
  27. data/ext/readapt/stack.c +86 -0
  28. data/ext/readapt/stack.h +20 -0
  29. data/ext/readapt/threads.c +111 -17
  30. data/ext/readapt/threads.h +11 -4
  31. data/lib/readapt.rb +21 -19
  32. data/lib/readapt/adapter.rb +98 -138
  33. data/lib/readapt/breakpoint.rb +20 -13
  34. data/lib/readapt/data_reader.rb +62 -0
  35. data/lib/readapt/debugger.rb +220 -204
  36. data/lib/readapt/error.rb +63 -0
  37. data/lib/readapt/finder.rb +20 -20
  38. data/lib/readapt/frame.rb +40 -42
  39. data/lib/readapt/input.rb +7 -0
  40. data/lib/readapt/message.rb +62 -59
  41. data/lib/readapt/message/attach.rb +11 -11
  42. data/lib/readapt/message/base.rb +32 -32
  43. data/lib/readapt/message/configuration_done.rb +11 -11
  44. data/lib/readapt/message/continue.rb +15 -15
  45. data/lib/readapt/message/disconnect.rb +13 -14
  46. data/lib/readapt/message/evaluate.rb +18 -18
  47. data/lib/readapt/message/initialize.rb +13 -13
  48. data/lib/readapt/message/launch.rb +11 -11
  49. data/lib/readapt/message/next.rb +12 -12
  50. data/lib/readapt/message/pause.rb +11 -11
  51. data/lib/readapt/message/scopes.rb +26 -25
  52. data/lib/readapt/message/set_breakpoints.rb +25 -25
  53. data/lib/readapt/message/set_exception_breakpoints.rb +8 -8
  54. data/lib/readapt/message/stack_trace.rb +38 -26
  55. data/lib/readapt/message/step_in.rb +11 -11
  56. data/lib/readapt/message/step_out.rb +11 -11
  57. data/lib/readapt/message/threads.rb +18 -18
  58. data/lib/readapt/message/variables.rb +61 -57
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -0
  61. data/lib/readapt/references.rb +27 -0
  62. data/lib/readapt/server.rb +22 -0
  63. data/lib/readapt/shell.rb +104 -39
  64. data/lib/readapt/snapshot.rb +1 -13
  65. data/lib/readapt/thread.rb +23 -39
  66. data/lib/readapt/variable.rb +1 -1
  67. data/lib/readapt/version.rb +3 -3
  68. data/readapt.gemspec +39 -39
  69. metadata +19 -8
  70. data/lib/readapt/location.rb +0 -25
@@ -1,32 +1,30 @@
1
- #ifndef HASH_TABLE_H_
2
- #define HASH_TABLE_H_
3
-
4
- #include "ruby.h"
5
-
6
- typedef struct ht_long_array
7
- {
8
- long *items;
9
- long size;
10
- } ht_long_array;
11
-
12
- // ht_item is an item in the hash table
13
- typedef struct ht_item
14
- {
15
- char *key;
16
- ht_long_array *value;
17
- } ht_item;
18
-
19
- typedef struct ht_hash_table
20
- {
21
- long size;
22
- ht_item **items;
23
- } ht_hash_table;
24
-
25
- ht_hash_table *ht_new();
26
- void ht_del_hash_table(ht_hash_table *ht);
27
-
28
- void ht_insert(ht_hash_table *ht, char *key, const long *value, const long size);
29
- ht_long_array *ht_search(ht_hash_table *ht, char *key);
30
- void ht_delete(ht_hash_table *h, char *key);
31
-
32
- #endif // HASH_TABLE_H_
1
+ #ifndef HASH_TABLE_H_
2
+ #define HASH_TABLE_H_
3
+
4
+ typedef struct ht_long_array
5
+ {
6
+ long *items;
7
+ long size;
8
+ } ht_long_array;
9
+
10
+ // ht_item is an item in the hash table
11
+ typedef struct ht_item
12
+ {
13
+ char *key;
14
+ ht_long_array *value;
15
+ } ht_item;
16
+
17
+ typedef struct ht_hash_table
18
+ {
19
+ long size;
20
+ ht_item **items;
21
+ } ht_hash_table;
22
+
23
+ ht_hash_table *ht_new();
24
+ void ht_del_hash_table(ht_hash_table *ht);
25
+
26
+ void ht_insert(ht_hash_table *ht, char *key, const long *value, const long size);
27
+ ht_long_array *ht_search(ht_hash_table *ht, char *key);
28
+ void ht_delete(ht_hash_table *h, char *key);
29
+
30
+ #endif // HASH_TABLE_H_
@@ -0,0 +1,51 @@
1
+ #include "ruby.h"
2
+ #include "ruby/debug.h"
3
+ #include "frame.h"
4
+ #include "threads.h"
5
+ #include "normalize.h"
6
+
7
+ static VALUE process_inspection(const rb_debug_inspector_t *inspector, void *ptr)
8
+ {
9
+ VALUE locations;
10
+ long i_size;
11
+ long i;
12
+ VALUE loc;
13
+ VALUE path;
14
+ int line;
15
+ VALUE bnd;
16
+ thread_reference_t *data;
17
+ frame_t *frm;
18
+ VALUE iseq;
19
+
20
+ data = ptr;
21
+
22
+ locations = rb_debug_inspector_backtrace_locations(inspector);
23
+ i_size = locations == Qnil ? 0 : RARRAY_LENINT(locations);
24
+ for (i = i_size - 1; i >= 0; i--)
25
+ {
26
+ iseq = rb_debug_inspector_frame_iseq_get(inspector, i);
27
+ if (iseq != Qnil)
28
+ {
29
+ loc = rb_ary_entry(locations, i);
30
+ path = rb_funcall(loc, rb_intern("absolute_path"), 0);
31
+ line = NUM2INT(rb_funcall(loc, rb_intern("lineno"), 0));
32
+ bnd = rb_debug_inspector_frame_binding_get(inspector, i);
33
+
34
+ frm = malloc(sizeof(frame_t));
35
+ frm->file = normalize_path_new_cstr(StringValueCStr(path));
36
+ frm->line = line;
37
+ frm->binding = bnd;
38
+ stack_push(data->frames, frm);
39
+ }
40
+ }
41
+
42
+ return Qnil;
43
+ }
44
+
45
+ /**
46
+ * Get an array of frames from the Ruby debug inspector.
47
+ */
48
+ void inspector_inspect(thread_reference_t *data)
49
+ {
50
+ rb_debug_inspector_open(process_inspection, (void *)data);
51
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef INSPECTOR_H_
2
+ #define INSPECTOR_H_
3
+
4
+ #include "ruby.h"
5
+
6
+ void inspector_inspect(thread_reference_t *);
7
+
8
+ #endif
@@ -46,18 +46,16 @@ static int match_step(thread_reference_t *ptr)
46
46
  static ID
47
47
  monitor_debug(const char *file, const long line, VALUE tracepoint, thread_reference_t *ptr, ID event)
48
48
  {
49
- VALUE bind, bid, snapshot, result;
49
+ VALUE snapshot, result, gc_disabled;
50
50
 
51
- bind = rb_funcall(tracepoint, rb_intern("binding"), 0);
52
- bid = rb_funcall(bind, rb_intern("object_id"), 0);
53
- snapshot = rb_funcall(c_Snapshot, rb_intern("new"), 7,
54
- LONG2NUM(ptr->id),
55
- bid,
51
+ // Disable garbage collection to avoid segfaults in Frame#frame_binding
52
+ gc_disabled = rb_gc_disable();
53
+ thread_reference_build_frames(ptr);
54
+ snapshot = rb_funcall(c_Snapshot, rb_intern("new"), 4,
55
+ INT2NUM(ptr->id),
56
56
  rb_str_new_cstr(file),
57
57
  INT2NUM(line),
58
- Qnil,
59
- ID2SYM(event),
60
- INT2NUM(ptr->depth)
58
+ ID2SYM(event)
61
59
  );
62
60
  rb_io_flush(rb_stdout);
63
61
  rb_io_flush(rb_stderr);
@@ -68,33 +66,44 @@ monitor_debug(const char *file, const long line, VALUE tracepoint, thread_refere
68
66
  ptr->cursor = ptr->depth;
69
67
  ptr->control = result;
70
68
  }
69
+ thread_reference_clear_frames(ptr);
70
+ if (!RTEST(gc_disabled))
71
+ {
72
+ rb_gc_enable();
73
+ }
71
74
  return result;
72
75
  }
73
76
 
74
77
  static void
75
78
  process_line_event(VALUE tracepoint, void *data)
76
79
  {
77
- VALUE ref, tmp;
78
- char *tp_file;
79
- long tp_line;
80
+ VALUE ref;
80
81
  thread_reference_t *ptr;
81
- rb_trace_arg_t *tp;
82
+ rb_trace_arg_t *arg;
82
83
  int threadPaused;
83
84
  ID dapEvent;
85
+ VALUE tmp;
86
+ char *tp_file;
87
+ long tp_line;
84
88
 
85
89
  ref = thread_current_reference();
86
90
  if (ref != Qnil)
87
91
  {
88
92
  ptr = thread_reference_pointer(ref);
89
93
  threadPaused = (ptr->control == id_pause);
94
+
90
95
  if (firstLineEvent && ptr->control == id_continue && breakpoints_files() == 0)
91
96
  {
92
97
  return;
93
98
  }
94
- tp = rb_tracearg_from_tracepoint(tracepoint);
95
- tmp = rb_tracearg_path(tp);
96
- tp_file = normalize_path_new_cstr(StringValueCStr(tmp));
97
- tp_line = NUM2LONG(rb_tracearg_lineno(tp));
99
+
100
+ arg = rb_tracearg_from_tracepoint(tracepoint);
101
+ tmp = rb_tracearg_path(arg);
102
+ // tp_file = normalize_path_new_cstr(StringValueCStr(tmp));
103
+ tp_file = StringValueCStr(tmp);
104
+ normalize_path(tp_file);
105
+ tmp = rb_tracearg_lineno(arg);
106
+ tp_line = NUM2INT(tmp);
98
107
 
99
108
  dapEvent = id_continue;
100
109
  if (!firstLineEvent)
@@ -128,7 +137,7 @@ process_line_event(VALUE tracepoint, void *data)
128
137
  monitor_debug(tp_file, tp_line, tracepoint, ptr, dapEvent);
129
138
  }
130
139
 
131
- free(tp_file);
140
+ // free(tp_file);
132
141
  }
133
142
  }
134
143
 
@@ -163,7 +172,7 @@ process_return_event(VALUE tracepoint, void *data)
163
172
  static void
164
173
  process_thread_begin_event(VALUE tracepoint, void *data)
165
174
  {
166
- VALUE list, here, prev, ref;
175
+ VALUE list, here, ref;
167
176
  thread_reference_t *ptr;
168
177
 
169
178
  list = rb_funcall(rb_cThread, rb_intern("list"), 0);
@@ -189,12 +198,15 @@ process_thread_end_event(VALUE tracepoint, void *data)
189
198
  thread_reference_t *ptr;
190
199
 
191
200
  thr = rb_thread_current();
192
- ref = thread_reference(thr);
193
- if (ref != Qnil)
201
+ if (thr != Qnil)
194
202
  {
195
- ptr = thread_reference_pointer(ref);
196
- monitor_debug("", 0, tracepoint, ptr, rb_intern("thread_end"));
197
- thread_delete_reference(thr);
203
+ ref = thread_reference(thr);
204
+ if (ref != Qnil)
205
+ {
206
+ ptr = thread_reference_pointer(ref);
207
+ monitor_debug("", 0, tracepoint, ptr, rb_intern("thread_end"));
208
+ thread_delete_reference(thr);
209
+ }
198
210
  }
199
211
  }
200
212
 
@@ -255,6 +267,7 @@ monitor_disable_s(VALUE self)
255
267
 
256
268
  free(entryFile);
257
269
  entryFile = NULL;
270
+ thread_clear();
258
271
 
259
272
  return previous;
260
273
  }
@@ -280,15 +293,15 @@ void initialize_monitor(VALUE m_Readapt)
280
293
  m_Monitor = rb_define_module_under(m_Readapt, "Monitor");
281
294
  c_Snapshot = rb_define_class_under(m_Readapt, "Snapshot", rb_cObject);
282
295
 
283
- initialize_threads();
296
+ initialize_threads(m_Readapt);
284
297
 
285
298
  rb_define_singleton_method(m_Monitor, "start", monitor_enable_s, 1);
286
299
  rb_define_singleton_method(m_Monitor, "stop", monitor_disable_s, 0);
287
300
  rb_define_singleton_method(m_Monitor, "pause", monitor_pause_s, 1);
288
301
 
289
302
  tpLine = rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, process_line_event, NULL);
290
- tpCall = rb_tracepoint_new(Qnil, RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS, process_call_event, NULL);
291
- tpReturn = rb_tracepoint_new(Qnil, RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END, process_return_event, NULL);
303
+ tpCall = rb_tracepoint_new(Qnil, RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS | RUBY_EVENT_C_CALL, process_call_event, NULL);
304
+ tpReturn = rb_tracepoint_new(Qnil, RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END | RUBY_EVENT_C_RETURN, process_return_event, NULL);
292
305
  tpThreadBegin = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_BEGIN, process_thread_begin_event, NULL);
293
306
  tpThreadEnd = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_END, process_thread_end_event, NULL);
294
307
  debugProc = Qnil;
File without changes
@@ -1,53 +1,59 @@
1
- #include "ruby.h"
2
- #include "ruby/debug.h"
3
- #include <ctype.h>
4
-
5
- static int isWindows;
6
-
7
- static int
8
- checkIfWindows()
9
- {
10
- VALUE regexp, result;
11
-
12
- regexp = rb_reg_new("/cygwin|mswin|mingw|bccwin|wince|emx/", 37, 0);
13
- result = rb_reg_match(regexp, rb_str_new_cstr(RUBY_PLATFORM));
14
- return result == Qnil ? 0 : 1;
15
- }
16
-
17
- char *normalize_path_new_cstr(char *str)
18
- {
19
- char *buffer;
20
- long i, len;
21
-
22
- buffer = malloc((strlen(str) + 1) * sizeof(char));
23
- strcpy(buffer, str);
24
- if (isWindows)
25
- {
26
- buffer[0] = toupper(buffer[0]);
27
- len = strlen(buffer);
28
- for (i = 2; i < len; i++)
29
- {
30
- if (buffer[i] == '\\')
31
- {
32
- buffer[i] = '/';
33
- }
34
- }
35
- }
36
- return buffer;
37
- }
38
-
39
- static VALUE
40
- normalize_path_s(VALUE self, VALUE str)
41
- {
42
- char *path = normalize_path_new_cstr(StringValueCStr(str));
43
- VALUE result = rb_str_new_cstr(path);
44
- free(path);
45
- return result;
46
- }
47
-
48
- void initialize_normalize(VALUE m_Readapt)
49
- {
50
- isWindows = checkIfWindows();
51
-
52
- rb_define_singleton_method(m_Readapt, "normalize_path", normalize_path_s, 1);
53
- }
1
+ #include "ruby.h"
2
+ #include "ruby/debug.h"
3
+ #include <ctype.h>
4
+
5
+ static int isWindows;
6
+
7
+ static int
8
+ checkIfWindows()
9
+ {
10
+ VALUE regexp, result;
11
+
12
+ regexp = rb_reg_new("/cygwin|mswin|mingw|bccwin|wince|emx/", 37, 0);
13
+ result = rb_reg_match(regexp, rb_str_new_cstr(RUBY_PLATFORM));
14
+ return result == Qnil ? 0 : 1;
15
+ }
16
+
17
+ void normalize_path(char *str)
18
+ {
19
+ long i, len;
20
+
21
+ if (isWindows)
22
+ {
23
+ str[0] = toupper(str[0]);
24
+ len = strlen(str);
25
+ for (i = 2; i < len; i++)
26
+ {
27
+ if (str[i] == '\\')
28
+ {
29
+ str[i] = '/';
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ char *normalize_path_new_cstr(char *str)
36
+ {
37
+ char *buffer;
38
+
39
+ buffer = malloc((strlen(str) + 1) * sizeof(char));
40
+ strcpy(buffer, str);
41
+ normalize_path(buffer);
42
+ return buffer;
43
+ }
44
+
45
+ static VALUE
46
+ normalize_path_s(VALUE self, VALUE str)
47
+ {
48
+ char *path = normalize_path_new_cstr(StringValueCStr(str));
49
+ VALUE result = rb_str_new_cstr(path);
50
+ free(path);
51
+ return result;
52
+ }
53
+
54
+ void initialize_normalize(VALUE m_Readapt)
55
+ {
56
+ isWindows = checkIfWindows();
57
+
58
+ rb_define_singleton_method(m_Readapt, "normalize_path", normalize_path_s, 1);
59
+ }
@@ -1,7 +1,7 @@
1
- #ifndef NORMALIZE_H_
2
- #define NORMALIZE_H_
3
-
4
- void initialize_normalize(VALUE);
5
- char *normalize_path_new_cstr(char *str);
6
-
7
- #endif
1
+ #ifndef NORMALIZE_H_
2
+ #define NORMALIZE_H_
3
+
4
+ void initialize_normalize(VALUE);
5
+ char *normalize_path_new_cstr(char *str);
6
+ void normalize_path(char *str);
7
+ #endif
@@ -1,16 +1,18 @@
1
- #include "ruby.h"
2
- #include "ruby/debug.h"
3
- #include "monitor.h"
4
- #include "normalize.h"
5
- #include "breakpoints.h"
6
-
7
- static VALUE m_Readapt;
8
-
9
- void Init_readapt()
10
- {
11
- m_Readapt = rb_define_module("Readapt");
12
-
13
- initialize_normalize(m_Readapt);
14
- initialize_breakpoints(m_Readapt);
15
- initialize_monitor(m_Readapt);
16
- }
1
+ #include "ruby.h"
2
+ #include "ruby/debug.h"
3
+ #include "monitor.h"
4
+ #include "normalize.h"
5
+ #include "breakpoints.h"
6
+ #include "frame.h"
7
+
8
+ static VALUE m_Readapt;
9
+
10
+ void Init_readapt()
11
+ {
12
+ m_Readapt = rb_define_module("Readapt");
13
+
14
+ initialize_normalize(m_Readapt);
15
+ initialize_breakpoints(m_Readapt);
16
+ initialize_frame(m_Readapt);
17
+ initialize_monitor(m_Readapt);
18
+ }
@@ -0,0 +1,86 @@
1
+ #include <stdlib.h>
2
+ #include "stack.h"
3
+
4
+ #define STACK_CAPACITY 20
5
+
6
+ /**
7
+ * Allocate a stack. The `elem_size` is the expected size of each element,
8
+ * e.g., `sizeof(some_struct)`. The optional `free_func` argument is a pointer
9
+ * to a function that will be called when an element is popped off the stack.
10
+ */
11
+ readapt_stack_t *stack_alloc(size_t elem_size, void (*free_func)(void *))
12
+ {
13
+ readapt_stack_t *s = malloc(sizeof(readapt_stack_t));
14
+ s->elem_size = elem_size;
15
+ s->free_func = free_func;
16
+ s->size = 0;
17
+ s->capacity = 0;
18
+ return s;
19
+ }
20
+
21
+ /**
22
+ * Add an element to the end of the stack
23
+ */
24
+ void stack_push(readapt_stack_t *stack, void *element)
25
+ {
26
+ if (stack->size == stack->capacity)
27
+ {
28
+ if (stack->capacity == 0)
29
+ {
30
+ stack->capacity = STACK_CAPACITY;
31
+ stack->elements = malloc(stack->elem_size * stack->capacity);
32
+ }
33
+ else
34
+ {
35
+ stack->capacity += STACK_CAPACITY;
36
+ stack->elements = realloc(stack->elements, stack->elem_size * stack->capacity);
37
+ }
38
+ }
39
+ stack->elements[stack->size] = element;
40
+ stack->size++;
41
+ }
42
+
43
+ /**
44
+ * Get a pointer to the last element in the stack.
45
+ */
46
+ void *stack_peek(readapt_stack_t *stack)
47
+ {
48
+ return stack->size == 0 ? NULL : stack->elements[stack->size - 1];
49
+ }
50
+
51
+ /**
52
+ * Pop the last element off the stack and pass it to free_func.
53
+ */
54
+ void stack_pop(readapt_stack_t *stack)
55
+ {
56
+ void *e;
57
+
58
+ if (stack->size > 0)
59
+ {
60
+ e = stack->elements[stack->size - 1];
61
+ if (stack->free_func)
62
+ {
63
+ stack->free_func(e);
64
+ }
65
+ // stack->elements[stack->size - 1] = NULL;
66
+ stack->size--;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Free the stack from memory. If it still contains any elements, pass them to
72
+ * free_func.
73
+ */
74
+ void stack_free(readapt_stack_t *stack)
75
+ {
76
+ int i;
77
+
78
+ if (stack->free_func)
79
+ {
80
+ for (i = 0; i < stack->size; i++)
81
+ {
82
+ stack->free_func(stack->elements[i]);
83
+ }
84
+ }
85
+ free(stack);
86
+ }