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