2 * sgen-grep-binprot.c: Platform specific binary protocol entries reader
4 * Copyright (C) 2016 Xamarin Inc
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
18 #include "sgen-entry-stream.h"
19 #include "sgen-grep-binprot.h"
21 #ifdef BINPROT_HAS_HEADER
22 #define PACKED_SUFFIX p
24 #define PROTOCOL_STRUCT_ATTR
28 #ifndef BINPROT_SIZEOF_VOID_P
29 #define BINPROT_SIZEOF_VOID_P SIZEOF_VOID_P
33 #if BINPROT_SIZEOF_VOID_P == 4
34 typedef int32_t mword;
35 #define MWORD_FORMAT_SPEC_D PRId32
36 #define MWORD_FORMAT_SPEC_P PRIx32
38 #define ARCH_SUFFIX 32
41 typedef int64_t mword;
42 #define MWORD_FORMAT_SPEC_D PRId64
43 #define MWORD_FORMAT_SPEC_P PRIx64
45 #define ARCH_SUFFIX 64
48 #define TYPE_SIZE mword
49 #define TYPE_POINTER mword
50 #include <mono/sgen/sgen-protocol.h>
52 #define SGEN_PROTOCOL_EOF 255
54 #define TYPE(t) ((t) & 0x7f)
55 #define WORKER(t) ((t) & 0x80)
57 #define MAX_ENTRY_SIZE (1 << 10)
60 read_entry (EntryStream *stream, void *data)
65 if (read_stream (stream, &type, 1) <= 0)
66 return SGEN_PROTOCOL_EOF;
67 switch (TYPE (type)) {
69 #define BEGIN_PROTOCOL_ENTRY0(method) \
70 case PROTOCOL_ID(method): size = 0; break;
71 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
72 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
73 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
74 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
75 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
76 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
77 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
78 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
79 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
80 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
81 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
82 case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
84 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
85 BEGIN_PROTOCOL_ENTRY0 (method)
86 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
87 BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
88 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
89 BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
90 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
91 BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
92 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
93 BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
94 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
95 BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
96 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
97 BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
99 #define DEFAULT_PRINT()
100 #define CUSTOM_PRINT(_)
102 #define IS_ALWAYS_MATCH(_)
103 #define MATCH_INDEX(_)
104 #define IS_VTABLE_MATCH(_)
106 #define END_PROTOCOL_ENTRY
107 #define END_PROTOCOL_ENTRY_FLUSH
108 #define END_PROTOCOL_ENTRY_HEAVY
110 #include <mono/sgen/sgen-protocol-def.h>
116 size_t size_read = read_stream (stream, data, size);
117 g_assert (size_read == size);
124 is_always_match (int type)
126 switch (TYPE (type)) {
127 #define BEGIN_PROTOCOL_ENTRY0(method) \
128 case PROTOCOL_ID(method):
129 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
130 case PROTOCOL_ID(method):
131 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
132 case PROTOCOL_ID(method):
133 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
134 case PROTOCOL_ID(method):
135 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
136 case PROTOCOL_ID(method):
137 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
138 case PROTOCOL_ID(method):
139 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
140 case PROTOCOL_ID(method):
142 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
143 BEGIN_PROTOCOL_ENTRY0 (method)
144 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
145 BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
146 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
147 BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
148 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
149 BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
150 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
151 BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
152 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
153 BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
154 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
155 BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
157 #define DEFAULT_PRINT()
158 #define CUSTOM_PRINT(_)
160 #define IS_ALWAYS_MATCH(is_always_match) \
161 return is_always_match;
162 #define MATCH_INDEX(_)
163 #define IS_VTABLE_MATCH(_)
165 #define END_PROTOCOL_ENTRY
166 #define END_PROTOCOL_ENTRY_FLUSH
167 #define END_PROTOCOL_ENTRY_HEAVY
169 #include <mono/sgen/sgen-protocol-def.h>
175 #define WORKER_PREFIX(t) (WORKER ((t)) ? "w" : " ")
177 enum { NO_COLOR = -1 };
183 /* The index of the ANSI color with which to highlight
184 * this entry, or NO_COLOR for no highlighting.
191 #define TYPE_LONGLONG 1
193 #define TYPE_POINTER 3
197 print_entry_content (int entries_size, PrintEntry *entries, gboolean color_output)
200 for (i = 0; i < entries_size; ++i) {
201 printf ("%s%s ", i == 0 ? "" : " ", entries [i].name);
202 if (color_output && entries [i].color != NO_COLOR)
203 /* Set foreground color, excluding black & white. */
204 printf ("\x1B[%dm", 31 + (entries [i].color % 6));
205 switch (entries [i].type) {
207 printf ("%d", *(int*) entries [i].data);
210 printf ("%lld", *(long long*) entries [i].data);
213 printf ("%"MWORD_FORMAT_SPEC_D, *(mword*) entries [i].data);
216 printf ("0x%"MWORD_FORMAT_SPEC_P, *(mword*) entries [i].data);
219 printf ("%s", *(gboolean*) entries [i].data ? "true" : "false");
224 if (color_output && entries [i].color != NO_COLOR)
225 /* Reset foreground color to default. */
231 index_color (int index, int num_nums, int *match_indices)
234 for (result = 0; result < num_nums + 1; ++result)
235 if (index == match_indices [result])
241 print_entry (int type, void *data, int num_nums, int *match_indices, gboolean color_output)
243 const char *always_prefix = is_always_match (type) ? " " : "";
244 printf ("%s%s ", WORKER_PREFIX (type), always_prefix);
246 switch (TYPE (type)) {
248 #define BEGIN_PROTOCOL_ENTRY0(method) \
249 case PROTOCOL_ID(method): { \
250 const int pes_size G_GNUC_UNUSED = 0; \
251 PrintEntry pes [1] G_GNUC_UNUSED; \
252 printf ("%s", #method + strlen ("binary_protocol_"));
253 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
254 case PROTOCOL_ID(method): { \
255 PROTOCOL_STRUCT (method) *entry = data; \
256 const int pes_size G_GNUC_UNUSED = 1; \
257 PrintEntry pes [1] G_GNUC_UNUSED; \
259 pes [0].name = #f1; \
260 pes [0].data = &entry->f1; \
261 pes [0].color = index_color(0, num_nums, match_indices); \
262 printf ("%s ", #method + strlen ("binary_protocol_"));
263 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
264 case PROTOCOL_ID(method): { \
265 PROTOCOL_STRUCT (method) *entry = data; \
266 const int pes_size G_GNUC_UNUSED = 2; \
267 PrintEntry pes [2] G_GNUC_UNUSED; \
269 pes [0].name = #f1; \
270 pes [0].data = &entry->f1; \
271 pes [0].color = index_color(0, num_nums, match_indices); \
273 pes [1].name = #f2; \
274 pes [1].data = &entry->f2; \
275 pes [1].color = index_color(1, num_nums, match_indices); \
276 printf ("%s ", #method + strlen ("binary_protocol_"));
277 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
278 case PROTOCOL_ID(method): { \
279 PROTOCOL_STRUCT (method) *entry = data; \
280 const int pes_size G_GNUC_UNUSED = 3; \
281 PrintEntry pes [3] G_GNUC_UNUSED; \
283 pes [0].name = #f1; \
284 pes [0].data = &entry->f1; \
285 pes [0].color = index_color(0, num_nums, match_indices); \
287 pes [1].name = #f2; \
288 pes [1].data = &entry->f2; \
289 pes [1].color = index_color(1, num_nums, match_indices); \
291 pes [2].name = #f3; \
292 pes [2].data = &entry->f3; \
293 pes [2].color = index_color(2, num_nums, match_indices); \
294 printf ("%s ", #method + strlen ("binary_protocol_"));
295 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
296 case PROTOCOL_ID(method): { \
297 PROTOCOL_STRUCT (method) *entry = data; \
298 const int pes_size G_GNUC_UNUSED = 4; \
299 PrintEntry pes [4] G_GNUC_UNUSED; \
301 pes [0].name = #f1; \
302 pes [0].data = &entry->f1; \
303 pes [0].color = index_color(0, num_nums, match_indices); \
305 pes [1].name = #f2; \
306 pes [1].data = &entry->f2; \
307 pes [1].color = index_color(1, num_nums, match_indices); \
309 pes [2].name = #f3; \
310 pes [2].data = &entry->f3; \
311 pes [2].color = index_color(2, num_nums, match_indices); \
313 pes [3].name = #f4; \
314 pes [3].data = &entry->f4; \
315 pes [3].color = index_color(3, num_nums, match_indices); \
316 printf ("%s ", #method + strlen ("binary_protocol_"));
317 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
318 case PROTOCOL_ID(method): { \
319 PROTOCOL_STRUCT (method) *entry = data; \
320 const int pes_size G_GNUC_UNUSED = 5; \
321 PrintEntry pes [5] G_GNUC_UNUSED; \
323 pes [0].name = #f1; \
324 pes [0].data = &entry->f1; \
325 pes [0].color = index_color(0, num_nums, match_indices); \
327 pes [1].name = #f2; \
328 pes [1].data = &entry->f2; \
329 pes [1].color = index_color(1, num_nums, match_indices); \
331 pes [2].name = #f3; \
332 pes [2].data = &entry->f3; \
333 pes [2].color = index_color(2, num_nums, match_indices); \
335 pes [3].name = #f4; \
336 pes [3].data = &entry->f4; \
337 pes [3].color = index_color(3, num_nums, match_indices); \
339 pes [4].name = #f5; \
340 pes [4].data = &entry->f5; \
341 pes [4].color = index_color(4, num_nums, match_indices); \
342 printf ("%s ", #method + strlen ("binary_protocol_"));
343 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
344 case PROTOCOL_ID(method): { \
345 PROTOCOL_STRUCT (method) *entry = data; \
346 const int pes_size G_GNUC_UNUSED = 6; \
347 PrintEntry pes [6] G_GNUC_UNUSED; \
349 pes [0].name = #f1; \
350 pes [0].data = &entry->f1; \
351 pes [0].color = index_color(0, num_nums, match_indices); \
353 pes [1].name = #f2; \
354 pes [1].data = &entry->f2; \
355 pes [1].color = index_color(1, num_nums, match_indices); \
357 pes [2].name = #f3; \
358 pes [2].data = &entry->f3; \
359 pes [2].color = index_color(2, num_nums, match_indices); \
361 pes [3].name = #f4; \
362 pes [3].data = &entry->f4; \
363 pes [3].color = index_color(3, num_nums, match_indices); \
365 pes [4].name = #f5; \
366 pes [4].data = &entry->f5; \
367 pes [4].color = index_color(4, num_nums, match_indices); \
369 pes [5].name = #f6; \
370 pes [5].data = &entry->f6; \
371 pes [5].color = index_color(5, num_nums, match_indices); \
372 printf ("%s ", #method + strlen ("binary_protocol_"));
374 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
375 BEGIN_PROTOCOL_ENTRY0 (method)
376 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
377 BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
378 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
379 BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
380 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
381 BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
382 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
383 BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
384 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
385 BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
386 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
387 BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
389 #define DEFAULT_PRINT() \
390 print_entry_content (pes_size, pes, color_output);
391 #define CUSTOM_PRINT(print) \
394 #define IS_ALWAYS_MATCH(_)
395 #define MATCH_INDEX(_)
396 #define IS_VTABLE_MATCH(_)
398 #define END_PROTOCOL_ENTRY \
402 #define END_PROTOCOL_ENTRY_FLUSH \
404 #define END_PROTOCOL_ENTRY_HEAVY \
407 #include <mono/sgen/sgen-protocol-def.h>
419 #define TYPE_LONGLONG long long
420 #define TYPE_SIZE mword
421 #define TYPE_POINTER mword
424 matches_interval (mword ptr, mword start, int size)
426 return ptr >= start && ptr < start + size;
429 /* Returns the index of the field where a match was found,
430 * BINARY_PROTOCOL_NO_MATCH for no match, or
431 * BINARY_PROTOCOL_MATCH for a match with no index.
434 match_index (mword ptr, int type, void *data)
436 switch (TYPE (type)) {
438 #define BEGIN_PROTOCOL_ENTRY0(method) \
439 case PROTOCOL_ID (method): {
440 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
441 case PROTOCOL_ID (method): { \
442 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
443 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
444 case PROTOCOL_ID (method): { \
445 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
446 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
447 case PROTOCOL_ID (method): { \
448 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
449 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
450 case PROTOCOL_ID (method): { \
451 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
452 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
453 case PROTOCOL_ID (method): { \
454 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
455 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
456 case PROTOCOL_ID (method): { \
457 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
459 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
460 BEGIN_PROTOCOL_ENTRY0 (method)
461 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
462 BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
463 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
464 BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
465 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
466 BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
467 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
468 BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
469 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
470 BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
471 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
472 BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
474 #define DEFAULT_PRINT()
475 #define CUSTOM_PRINT(_)
477 #define IS_ALWAYS_MATCH(_)
478 #define MATCH_INDEX(block) \
480 #define IS_VTABLE_MATCH(_)
482 #define END_PROTOCOL_ENTRY \
485 #define END_PROTOCOL_ENTRY_FLUSH \
487 #define END_PROTOCOL_ENTRY_HEAVY \
490 #include <mono/sgen/sgen-protocol-def.h>
497 is_vtable_match (mword ptr, int type, void *data)
499 switch (TYPE (type)) {
501 #define BEGIN_PROTOCOL_ENTRY0(method) \
502 case PROTOCOL_ID (method): {
503 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
504 case PROTOCOL_ID (method): { \
505 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
506 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
507 case PROTOCOL_ID (method): { \
508 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
509 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
510 case PROTOCOL_ID (method): { \
511 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
512 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
513 case PROTOCOL_ID (method): { \
514 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
515 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
516 case PROTOCOL_ID (method): { \
517 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
518 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
519 case PROTOCOL_ID (method): { \
520 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
522 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
523 BEGIN_PROTOCOL_ENTRY0 (method)
524 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
525 BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
526 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
527 BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
528 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
529 BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
530 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
531 BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
532 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
533 BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
534 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
535 BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
537 #define DEFAULT_PRINT()
538 #define CUSTOM_PRINT(_)
540 #define IS_ALWAYS_MATCH(_)
541 #define MATCH_INDEX(block) \
543 #define IS_VTABLE_MATCH(_)
545 #define END_PROTOCOL_ENTRY \
548 #define END_PROTOCOL_ENTRY_FLUSH \
550 #define END_PROTOCOL_ENTRY_HEAVY \
553 #include <mono/sgen/sgen-protocol-def.h>
565 sgen_binary_protocol_read_header (EntryStream *stream)
567 #ifdef BINPROT_HAS_HEADER
568 char data [MAX_ENTRY_SIZE];
569 int type = read_entry (stream, data);
570 if (type == SGEN_PROTOCOL_EOF)
572 if (type == PROTOCOL_ID (binary_protocol_header)) {
573 PROTOCOL_STRUCT (binary_protocol_header) * str = (PROTOCOL_STRUCT (binary_protocol_header) *) data;
574 if (str->check == PROTOCOL_HEADER_CHECK && str->ptr_size == BINPROT_SIZEOF_VOID_P)
580 * This implementation doesn't account for the presence of a header,
581 * reading all the entries with the default configuration of the host
582 * machine. It has to be used only after all other implementations
583 * fail to identify a header, for backward compatibility.
589 #define CONC(A, B) CONC_(A, B)
590 #define CONC_(A, B) A##B
591 #define GREP_ENTRIES_FUNCTION_NAME CONC(sgen_binary_protocol_grep_entries, CONC(ARCH_SUFFIX,PACKED_SUFFIX))
594 GREP_ENTRIES_FUNCTION_NAME (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
595 gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider)
598 void *data = g_malloc0 (MAX_ENTRY_SIZE);
600 gboolean pause_times_stopped = FALSE;
601 gboolean pause_times_concurrent = FALSE;
602 gboolean pause_times_finish = FALSE;
603 long long pause_times_ts = 0;
604 unsigned long long entry_index;
606 if (!sgen_binary_protocol_read_header (stream))
610 while ((type = read_entry (stream, data)) != SGEN_PROTOCOL_EOF) {
611 if (entry_index < first_entry_to_consider)
615 case PROTOCOL_ID (binary_protocol_world_stopping): {
616 PROTOCOL_STRUCT (binary_protocol_world_stopping) *entry = data;
617 assert (!pause_times_stopped);
618 pause_times_concurrent = FALSE;
619 pause_times_finish = FALSE;
620 pause_times_ts = entry->timestamp;
621 pause_times_stopped = TRUE;
624 case PROTOCOL_ID (binary_protocol_concurrent_finish):
625 pause_times_finish = TRUE;
626 case PROTOCOL_ID (binary_protocol_concurrent_start):
627 case PROTOCOL_ID (binary_protocol_concurrent_update):
628 pause_times_concurrent = TRUE;
630 case PROTOCOL_ID (binary_protocol_world_restarted): {
631 PROTOCOL_STRUCT (binary_protocol_world_restarted) *entry = data;
632 assert (pause_times_stopped);
633 printf ("pause-time %d %d %d %lld %lld\n",
635 pause_times_concurrent,
637 entry->timestamp - pause_times_ts,
639 pause_times_stopped = FALSE;
644 int match_indices [num_nums + 1];
645 gboolean match = is_always_match (type);
646 match_indices [num_nums] = num_nums == 0 ? match_index (0, type, data) : BINARY_PROTOCOL_NO_MATCH;
647 match = match_indices [num_nums] != BINARY_PROTOCOL_NO_MATCH;
648 for (i = 0; i < num_nums; ++i) {
649 match_indices [i] = match_index ((mword) nums [i], type, data);
650 match = match || match_indices [i] != BINARY_PROTOCOL_NO_MATCH;
653 for (i = 0; i < num_vtables; ++i) {
654 if (is_vtable_match ((mword) vtables [i], type, data)) {
660 if (match || dump_all)
661 printf ("%12lld ", entry_index);
663 printf (match ? "* " : " ");
664 if (match || dump_all)
665 print_entry (type, data, num_nums, match_indices, color_output);