Merge pull request #4444 from lateralusX/jlorenss/windows-unwind-info
[mono.git] / mono / mini / lldb.c
1 /*
2  * lldb.c: Mono support for LLDB.
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * Copyright 2016 Xamarin, Inc (http://www.xamarin.com)
8  */
9
10 #include "config.h"
11 #include "mini.h"
12 #include "lldb.h"
13 #include "seq-points.h"
14
15 #include <mono/metadata/debug-internals.h>
16 #include <mono/utils/mono-counters.h>
17
18 #if !defined(DISABLE_JIT) && !defined(DISABLE_LLDB)
19
20 typedef enum {
21         ENTRY_CODE_REGION = 1,
22         ENTRY_METHOD = 2,
23         ENTRY_TRAMPOLINE = 3,
24         ENTRY_UNLOAD_CODE_REGION = 4
25 } EntryType;
26
27 /*
28  * Need to make sure these structures have the same size and alignment on
29  * all platforms.
30  */
31
32 /* One data packet sent from the runtime to the debugger */
33 typedef struct {
34         /* Pointer to the next entry */
35         guint64 next_addr;
36         /* The type of data pointed to by ADDR */
37         /* One of the ENTRY_ constants */
38         guint32 type;
39         /* Align */
40         guint32 dummy;
41         guint64 size;
42         guint64 addr;
43 } DebugEntry;
44
45 typedef struct
46 {
47         /* (MAJOR << 16) | MINOR */
48         guint32 version;
49         /* Align */
50         guint32 dummy;
51         DebugEntry *entry;
52         /* List of all entries */
53         /* Keep this as a pointer so accessing it is atomic */
54         DebugEntry *all_entries;
55         /* The current entry embedded here to reduce the amount of roundtrips */
56         guint32 type;
57         guint32 dummy2;
58         guint64 size;
59         guint64 addr;
60 } JitDescriptor;
61
62 /*
63  * Represents a memory region used for code.
64  */
65 typedef struct {
66         /*
67          * OBJFILE_MAGIC. This is needed to make it easier for lldb to
68          * create object files from this packet.
69          */
70         char magic [32];
71         guint64 start;
72         guint32 size;
73         int id;
74 } CodeRegionEntry;
75
76 typedef struct {
77         int id;
78 } UnloadCodeRegionEntry;
79
80 /*
81  * Represents a managed method
82  */
83 typedef struct {
84         guint64 code;
85         int id;
86         /* The id of the codegen region which contains CODE */
87         int region_id;
88         int code_size;
89         /* Align */
90         guint32 dummy;
91         /* Followed by variable size data */
92 } MethodEntry;
93
94 /*
95  * Represents a trampoline
96  */
97 typedef struct {
98         guint64 code;
99         int id;
100         /* The id of the codegen region which contains CODE */
101         int region_id;
102         int code_size;
103         /* Align */
104         guint32 dummy;
105         /* Followed by variable size data */
106 } TrampolineEntry;
107
108 #define MAJOR_VERSION 1
109 #define MINOR_VERSION 0
110
111 static const char* OBJFILE_MAGIC = { "MONO_JIT_OBJECT_FILE" };
112
113 JitDescriptor __mono_jit_debug_descriptor = { (MAJOR_VERSION << 16) | MINOR_VERSION };
114
115 static gboolean enabled;
116 static int id_generator;
117 static GHashTable *codegen_regions;
118 static DebugEntry *last_entry;
119 static mono_mutex_t mutex;
120 static GHashTable *dyn_codegen_regions;
121 static double register_time;
122 static int num_entries;
123
124 #define lldb_lock() mono_os_mutex_lock (&mutex)
125 #define lldb_unlock() mono_os_mutex_unlock (&mutex)
126
127 void MONO_NEVER_INLINE __mono_jit_debug_register_code (void);
128
129 /* The native debugger puts a breakpoint in this function. */
130 void MONO_NEVER_INLINE
131 __mono_jit_debug_register_code (void)
132 {
133         /* Make sure that even compilers that ignore __noinline__ don't inline this */
134 #if defined(__GNUC__)
135         asm ("");
136 #endif
137 }
138
139 /*
140  * Functions to encode protocol data
141  */
142
143 typedef struct {
144         guint8 *buf, *p, *end;
145 } Buffer;
146
147 static inline void
148 buffer_init (Buffer *buf, int size)
149 {
150         buf->buf = (guint8 *)g_malloc (size);
151         buf->p = buf->buf;
152         buf->end = buf->buf + size;
153 }
154
155 static inline int
156 buffer_len (Buffer *buf)
157 {
158         return buf->p - buf->buf;
159 }
160
161 static inline void
162 buffer_make_room (Buffer *buf, int size)
163 {
164         if (buf->end - buf->p < size) {
165                 int new_size = buf->end - buf->buf + size + 32;
166                 guint8 *p = (guint8 *)g_realloc (buf->buf, new_size);
167                 size = buf->p - buf->buf;
168                 buf->buf = p;
169                 buf->p = p + size;
170                 buf->end = buf->buf + new_size;
171         }
172 }
173
174 static inline void
175 buffer_add_byte (Buffer *buf, guint8 val)
176 {
177         buffer_make_room (buf, 1);
178         buf->p [0] = val;
179         buf->p++;
180 }
181
182 static inline void
183 buffer_add_short (Buffer *buf, guint32 val)
184 {
185         buffer_make_room (buf, 2);
186         buf->p [0] = (val >> 8) & 0xff;
187         buf->p [1] = (val >> 0) & 0xff;
188         buf->p += 2;
189 }
190
191 static inline void
192 buffer_add_int (Buffer *buf, guint32 val)
193 {
194         buffer_make_room (buf, 4);
195         buf->p [0] = (val >> 24) & 0xff;
196         buf->p [1] = (val >> 16) & 0xff;
197         buf->p [2] = (val >> 8) & 0xff;
198         buf->p [3] = (val >> 0) & 0xff;
199         buf->p += 4;
200 }
201
202 static inline void
203 buffer_add_long (Buffer *buf, guint64 l)
204 {
205         buffer_add_int (buf, (l >> 32) & 0xffffffff);
206         buffer_add_int (buf, (l >> 0) & 0xffffffff);
207 }
208
209 static inline void
210 buffer_add_id (Buffer *buf, int id)
211 {
212         buffer_add_int (buf, (guint64)id);
213 }
214
215 static inline void
216 buffer_add_data (Buffer *buf, guint8 *data, int len)
217 {
218         buffer_make_room (buf, len);
219         memcpy (buf->p, data, len);
220         buf->p += len;
221 }
222
223 static inline void
224 buffer_add_string (Buffer *buf, const char *str)
225 {
226         int len;
227
228         if (str == NULL) {
229                 buffer_add_int (buf, 0);
230         } else {
231                 len = strlen (str);
232                 buffer_add_int (buf, len);
233                 buffer_add_data (buf, (guint8*)str, len);
234         }
235 }
236
237 static inline void
238 buffer_add_buffer (Buffer *buf, Buffer *data)
239 {
240         buffer_add_data (buf, data->buf, buffer_len (data));
241 }
242
243 static inline void
244 buffer_free (Buffer *buf)
245 {
246         g_free (buf->buf);
247 }
248
249 typedef struct {
250         gpointer code;
251         gpointer region_start;
252         guint32 region_size;
253         gboolean found;
254 } UserData;
255
256 static int
257 find_code_region (void *data, int csize, int size, void *user_data)
258 {
259         UserData *ud = user_data;
260
261         if ((char*)ud->code >= (char*)data && (char*)ud->code < (char*)data + csize) {
262                 ud->region_start = data;
263                 ud->region_size = csize;
264                 ud->found = TRUE;
265                 return 1;
266         }
267         return 0;
268 }
269
270 static void
271 add_entry (EntryType type, Buffer *buf)
272 {
273         DebugEntry *entry;
274         guint8 *data;
275         int size = buffer_len (buf);
276
277         data = g_malloc (size);
278         memcpy (data, buf->buf, size);
279
280         entry = g_malloc0 (sizeof (DebugEntry));
281         entry->type = type;
282         entry->addr = (guint64)(gsize)data;
283         entry->size = size;
284
285         mono_memory_barrier ();
286
287         lldb_lock ();
288
289         /* The debugger can read the list of entries asynchronously, so this has to be async safe */
290         // FIXME: Make sure this is async safe
291         if (last_entry) {
292                 last_entry->next_addr = (guint64)(gsize) (entry);
293                 last_entry = entry;
294         } else {
295                 last_entry = entry;
296                 __mono_jit_debug_descriptor.all_entries = entry;
297         }
298
299         __mono_jit_debug_descriptor.entry = entry;
300
301         __mono_jit_debug_descriptor.type = entry->type;
302         __mono_jit_debug_descriptor.size = entry->size;
303         __mono_jit_debug_descriptor.addr = entry->addr;
304         mono_memory_barrier ();
305
306         GTimer *timer = mono_time_track_start ();
307         __mono_jit_debug_register_code ();
308         mono_time_track_end (&register_time, timer);
309         num_entries ++;
310         //printf ("%lf %d %d\n", register_time, num_entries, entry->type);
311
312         lldb_unlock ();
313 }
314
315 /*
316  * register_codegen_region:
317  *
318  * Register a codegen region with the debugger if needed.
319  * Return a region id.
320  */
321 static int
322 register_codegen_region (gpointer region_start, int region_size, gboolean dynamic)
323 {
324         CodeRegionEntry *region_entry;
325         int id;
326         Buffer tmp_buf;
327         Buffer *buf = &tmp_buf;
328
329         if (dynamic) {
330                 lldb_lock ();
331                 id = ++id_generator;
332                 lldb_unlock ();
333         } else {
334                 lldb_lock ();
335                 if (!codegen_regions)
336                         codegen_regions = g_hash_table_new (NULL, NULL);
337                 id = GPOINTER_TO_INT (g_hash_table_lookup (codegen_regions, region_start));
338                 if (id) {
339                         lldb_unlock ();
340                         return id;
341                 }
342                 id = ++id_generator;
343                 g_hash_table_insert (codegen_regions, region_start, GINT_TO_POINTER (id));
344                 lldb_unlock ();
345         }
346
347         buffer_init (buf, 128);
348
349         region_entry = (CodeRegionEntry*)buf->p;
350         buf->p += sizeof (CodeRegionEntry);
351         memset (region_entry, 0, sizeof (CodeRegionEntry));
352         strcpy (region_entry->magic, OBJFILE_MAGIC);
353         region_entry->id = id;
354         region_entry->start = (gsize)region_start;
355         region_entry->size = (gsize)region_size;
356
357         add_entry (ENTRY_CODE_REGION, buf);
358         buffer_free (buf);
359         return id;
360 }
361
362 static void
363 emit_unwind_info (GSList *unwind_ops, Buffer *buf)
364 {
365         int ret_reg;
366         int nunwind_ops;
367         GSList *l;
368
369         ret_reg = mono_unwind_get_dwarf_pc_reg ();
370         g_assert (ret_reg < 256);
371
372         /* We use the unencoded version of the unwind info to make it easier to decode */
373         nunwind_ops = 0;
374         for (l = unwind_ops; l; l = l->next) {
375                 MonoUnwindOp *op = l->data;
376
377                 /* lldb can't handle these */
378                 if (op->op == DW_CFA_mono_advance_loc)
379                         break;
380                 nunwind_ops ++;
381         }
382
383         buffer_add_byte (buf, ret_reg);
384         buffer_add_int (buf, nunwind_ops);
385         for (l = unwind_ops; l; l = l->next) {
386                 MonoUnwindOp *op = l->data;
387
388                 if (op->op == DW_CFA_mono_advance_loc)
389                         break;
390                 buffer_add_int (buf, op->op);
391                 buffer_add_int (buf, op->when);
392                 int dreg;
393 #if TARGET_X86
394                 // LLDB doesn't see to use the switched esp/ebp
395                 if (op->reg == X86_ESP)
396                         dreg = X86_ESP;
397                 else if (op->reg == X86_EBP)
398                         dreg = X86_EBP;
399                 else
400                         dreg = mono_hw_reg_to_dwarf_reg (op->reg);
401 #else
402                 dreg = mono_hw_reg_to_dwarf_reg (op->reg);
403 #endif
404                 buffer_add_int (buf, dreg);
405                 buffer_add_int (buf, op->val);
406         }
407 }
408
409 void
410 mono_lldb_init (const char *options)
411 {
412         enabled = TRUE;
413         mono_os_mutex_init_recursive (&mutex);
414
415         mono_counters_register ("Time spent in LLDB", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &register_time);
416 }
417
418 typedef struct
419 {
420         MonoSymSeqPoint sp;
421         int native_offset;
422 } FullSeqPoint;
423
424 static int
425 compare_by_addr (const void *arg1, const void *arg2)
426 {
427         const FullSeqPoint *sp1 = arg1;
428         const FullSeqPoint *sp2 = arg2;
429
430         return sp1->native_offset - sp2->native_offset;
431 }
432
433 void
434 mono_lldb_save_method_info (MonoCompile *cfg)
435 {
436         MethodEntry *entry;
437         UserData udata;
438         int region_id;
439         Buffer tmpbuf;
440         Buffer *buf = &tmpbuf;
441         MonoDebugMethodInfo *minfo;
442         int i, j, n_il_offsets;
443         int *source_files;
444         GPtrArray *source_file_list;
445         MonoSymSeqPoint *sym_seq_points;
446         FullSeqPoint *locs;
447
448         if (!enabled)
449                 return;
450
451         /* Find the codegen region which contains the code */
452         memset (&udata, 0, sizeof (udata));
453         udata.code = cfg->native_code;
454         if (cfg->method->dynamic) {
455                 mono_code_manager_foreach (cfg->dynamic_info->code_mp, find_code_region, &udata);
456                 g_assert (udata.found);
457
458                 region_id = register_codegen_region (udata.region_start, udata.region_size, TRUE);
459
460                 lldb_lock ();
461                 if (!dyn_codegen_regions)
462                         dyn_codegen_regions = g_hash_table_new (NULL, NULL);
463                 g_hash_table_insert (dyn_codegen_regions, cfg->method, GINT_TO_POINTER (region_id));
464                 lldb_unlock ();
465         } else {
466                 mono_domain_code_foreach (cfg->domain, find_code_region, &udata);
467                 g_assert (udata.found);
468
469                 region_id = register_codegen_region (udata.region_start, udata.region_size, FALSE);
470         }
471
472         buffer_init (buf, 256);
473
474         entry = (MethodEntry*)buf->p;
475         buf->p += sizeof (MethodEntry);
476         entry->id = ++id_generator;
477         entry->region_id = region_id;
478         entry->code = (gsize)cfg->native_code;
479         entry->code_size = cfg->code_size;
480
481         emit_unwind_info (cfg->unwind_ops, buf);
482
483         char *s = mono_method_full_name (cfg->method, TRUE);
484         buffer_add_string (buf, s);
485         g_free (s);
486
487         minfo = mono_debug_lookup_method (cfg->method);
488         MonoSeqPointInfo *seq_points = cfg->seq_point_info;
489         if (minfo && seq_points) {
490                 mono_debug_get_seq_points (minfo, NULL, &source_file_list, &source_files, &sym_seq_points, &n_il_offsets);
491                 buffer_add_int (buf, source_file_list->len);
492                 for (i = 0; i < source_file_list->len; ++i) {
493                         MonoDebugSourceInfo *sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, i);
494                         buffer_add_string (buf, sinfo->source_file);
495                         for (j = 0; j < 16; ++j)
496                                 buffer_add_byte (buf, sinfo->hash [j]);
497                 }
498
499                 // The sym seq points are ordered by il offset, need to order them by address
500                 int skipped = 0;
501                 locs = g_new0 (FullSeqPoint, n_il_offsets);
502                 for (i = 0; i < n_il_offsets; ++i) {
503                         locs [i].sp = sym_seq_points [i];
504
505                         // FIXME: O(n^2)
506                         SeqPoint seq_point;
507                         if (mono_seq_point_find_by_il_offset (seq_points, sym_seq_points [i].il_offset, &seq_point)) {
508                                 locs [i].native_offset = seq_point.native_offset;
509                         } else {
510                                 locs [i].native_offset = 0xffffff;
511                                 skipped ++;
512                         }
513                 }
514                 qsort (locs, n_il_offsets, sizeof (FullSeqPoint), compare_by_addr);
515
516                 n_il_offsets -= skipped;
517                 buffer_add_int (buf, n_il_offsets);
518                 for (i = 0; i < n_il_offsets; ++i) {
519                         MonoSymSeqPoint *sp = &locs [i].sp;
520                         const char *srcfile = "";
521
522                         if (source_files [i] != -1) {
523                                 MonoDebugSourceInfo *sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, source_files [i]);
524                                 srcfile = sinfo->source_file;
525                         }
526
527                         //printf ("%s %x %d %d\n", cfg->method->name, locs [i].native_offset, sp->il_offset, sp->line);
528                         buffer_add_int (buf, locs [i].native_offset);
529                         buffer_add_int (buf, sp->il_offset);
530                         buffer_add_int (buf, sp->line);
531                         buffer_add_int (buf, source_files [i]);
532                         buffer_add_int (buf, sp->column);
533                         buffer_add_int (buf, sp->end_line);
534                         buffer_add_int (buf, sp->end_column);
535                 }
536                 g_free (locs);
537                 g_free (source_files);
538                 g_free (sym_seq_points);
539                 g_ptr_array_free (source_file_list, TRUE);
540         } else {
541                 buffer_add_int (buf, 0);
542                 buffer_add_int (buf, 0);
543         }
544
545         add_entry (ENTRY_METHOD, buf);
546         buffer_free (buf);
547 }
548
549 void
550 mono_lldb_remove_method (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *info)
551 {
552         int region_id;
553         UnloadCodeRegionEntry *entry;
554         Buffer tmpbuf;
555         Buffer *buf = &tmpbuf;
556
557         if (!enabled)
558                 return;
559
560         g_assert (method->dynamic);
561
562         lldb_lock ();
563         region_id = GPOINTER_TO_INT (g_hash_table_lookup (dyn_codegen_regions, method));
564         g_hash_table_remove (dyn_codegen_regions, method);
565         lldb_unlock ();
566
567         buffer_init (buf, 256);
568
569         entry = (UnloadCodeRegionEntry*)buf->p;
570         buf->p += sizeof (UnloadCodeRegionEntry);
571         entry->id = region_id;
572
573         add_entry (ENTRY_UNLOAD_CODE_REGION, buf);
574         buffer_free (buf);
575
576         /* The method is associated with the code region, so it doesn't have to be unloaded */
577 }
578
579 void
580 mono_lldb_save_trampoline_info (MonoTrampInfo *info)
581 {
582         TrampolineEntry *entry;
583         UserData udata;
584         int region_id;
585         Buffer tmpbuf;
586         Buffer *buf = &tmpbuf;
587
588         if (!enabled)
589                 return;
590
591         /* Find the codegen region which contains the code */
592         memset (&udata, 0, sizeof (udata));
593         udata.code = info->code;
594         mono_global_codeman_foreach (find_code_region, &udata);
595         if (!udata.found)
596                 mono_domain_code_foreach (mono_get_root_domain (), find_code_region, &udata);
597         if (!udata.found)
598                 /* Can happen with AOT */
599                 return;
600
601         region_id = register_codegen_region (udata.region_start, udata.region_size, FALSE);
602
603         buffer_init (buf, 1024);
604
605         entry = (TrampolineEntry*)buf->p;
606         buf->p += sizeof (TrampolineEntry);
607         entry->id = ++id_generator;
608         entry->region_id = region_id;
609         entry->code = (gsize)info->code;
610         entry->code_size = info->code_size;
611
612         emit_unwind_info (info->unwind_ops, buf);
613
614         buffer_add_string (buf, info->name);
615
616         add_entry (ENTRY_TRAMPOLINE, buf);
617         buffer_free (buf);
618 }
619
620 void
621 mono_lldb_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len)
622 {
623         /*
624          * Avoid emitting these for now,
625          * they slow down execution too much, and they are
626          * only needed during single stepping which doesn't
627          * work anyway.
628          */
629 #if 0
630         TrampolineEntry *entry;
631         UserData udata;
632         int region_id;
633         Buffer tmpbuf;
634         Buffer *buf = &tmpbuf;
635
636         if (!enabled)
637                 return;
638
639         /* Find the codegen region which contains the code */
640         memset (&udata, 0, sizeof (udata));
641         udata.code = code;
642         mono_global_codeman_foreach (find_code_region, &udata);
643         if (!udata.found)
644                 mono_domain_code_foreach (mono_get_root_domain (), find_code_region, &udata);
645         g_assert (udata.found);
646
647         region_id = register_codegen_region (udata.region_start, udata.region_size, FALSE);
648
649         buffer_init (buf, 1024);
650
651         entry = (TrampolineEntry*)buf->p;
652         buf->p += sizeof (TrampolineEntry);
653         entry->id = ++id_generator;
654         entry->region_id = region_id;
655         entry->code = (gsize)code;
656         entry->code_size = code_len;
657
658         GSList *unwind_ops = mono_unwind_get_cie_program ();
659         emit_unwind_info (unwind_ops, buf);
660
661         buffer_add_string (buf, "");
662
663         add_entry (ENTRY_TRAMPOLINE, buf);
664         buffer_free (buf);
665 #endif
666 }
667
668 /*
669 DESIGN:
670
671 Communication:
672 Similar to the gdb jit interface. The runtime communicates with a plugin running inside lldb.
673 - The runtime allocates a data packet, points a symbol with a well known name at it.
674 - It calls a dummy function with a well known name.
675 - The plugin sets a breakpoint at this function, causing the runtime to be suspended.
676 - The plugin reads the data pointed to by the other symbol and processes it.
677
678 The data packets are kept in a list, so lldb can read all of them after attaching.
679 Lldb will associate an object file with each mono codegen region.
680
681 Packet design:
682 - use a flat byte array so the whole data can be read in one operation.
683 - use 64 bit ints for pointers.
684 */
685
686 #else
687
688 void
689 mono_lldb_init (const char *options)
690 {
691         g_error ("lldb support has been disabled at configure time.");
692 }
693
694 void
695 mono_lldb_save_method_info (MonoCompile *cfg)
696 {
697 }
698
699 void
700 mono_lldb_save_trampoline_info (MonoTrampInfo *info)
701 {
702 }
703
704 void
705 mono_lldb_remove_method (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *info)
706 {
707 }
708
709 void
710 mono_lldb_save_specific_trampoline_info (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, gpointer code, guint32 code_len)
711 {
712 }
713
714 #endif