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