6 #define SGEN_BINARY_PROTOCOL
9 #include <mono/metadata/sgen-protocol.h>
11 #define SGEN_PROTOCOL_EOF 255
13 #define TYPE(t) ((t) & 0x7f)
14 #define WORKER(t) ((t) & 0x80)
17 read_entry (FILE *in, void **data)
22 if (fread (&type, 1, 1, in) != 1)
23 return SGEN_PROTOCOL_EOF;
24 switch (TYPE (type)) {
25 case SGEN_PROTOCOL_COLLECTION_FORCE: size = sizeof (SGenProtocolCollectionForce); break;
26 case SGEN_PROTOCOL_COLLECTION_BEGIN: size = sizeof (SGenProtocolCollection); break;
27 case SGEN_PROTOCOL_COLLECTION_END: size = sizeof (SGenProtocolCollection); break;
28 case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break;
29 case SGEN_PROTOCOL_ALLOC_PINNED: size = sizeof (SGenProtocolAlloc); break;
30 case SGEN_PROTOCOL_ALLOC_DEGRADED: size = sizeof (SGenProtocolAlloc); break;
31 case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break;
32 case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break;
33 case SGEN_PROTOCOL_MARK: size = sizeof (SGenProtocolMark); break;
34 case SGEN_PROTOCOL_SCAN_BEGIN: size = sizeof (SGenProtocolScanBegin); break;
35 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: size = sizeof (SGenProtocolScanVTypeBegin); break;
36 case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break;
37 case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break;
38 case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break;
39 case SGEN_PROTOCOL_CLEANUP: size = sizeof (SGenProtocolCleanup); break;
40 case SGEN_PROTOCOL_EMPTY: size = sizeof (SGenProtocolEmpty); break;
41 case SGEN_PROTOCOL_THREAD_SUSPEND: size = sizeof (SGenProtocolThreadSuspend); break;
42 case SGEN_PROTOCOL_THREAD_RESTART: size = sizeof (SGenProtocolThreadRestart); break;
43 case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break;
44 case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break;
45 case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break;
46 case SGEN_PROTOCOL_CARD_SCAN: size = sizeof (SGenProtocolCardScan); break;
47 case SGEN_PROTOCOL_CEMENT: size = sizeof (SGenProtocolCement); break;
48 case SGEN_PROTOCOL_CEMENT_RESET: size = 0; break;
49 case SGEN_PROTOCOL_DISLINK_UPDATE: size = sizeof (SGenProtocolDislinkUpdate); break;
50 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: size = sizeof (SGenProtocolDislinkUpdateStaged); break;
51 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: size = sizeof (SGenProtocolDislinkProcessStaged); break;
52 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: size = sizeof (SGenProtocolDomainUnload); break;
53 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: size = sizeof (SGenProtocolDomainUnload); break;
58 *data = malloc (size);
59 if (fread (*data, size, 1, in) != 1)
68 #define WORKER_PREFIX(t) (WORKER ((t)) ? "w" : " ")
71 print_entry (int type, void *data)
73 switch (TYPE (type)) {
74 case SGEN_PROTOCOL_COLLECTION_FORCE: {
75 SGenProtocolCollectionForce *entry = data;
76 printf ("%s collection force generation %d\n", WORKER_PREFIX (type), entry->generation);
79 case SGEN_PROTOCOL_COLLECTION_BEGIN: {
80 SGenProtocolCollection *entry = data;
81 printf ("%s collection begin %d generation %d\n", WORKER_PREFIX (type), entry->index, entry->generation);
84 case SGEN_PROTOCOL_COLLECTION_END: {
85 SGenProtocolCollection *entry = data;
86 printf ("%s collection end %d generation %d\n", WORKER_PREFIX (type), entry->index, entry->generation);
89 case SGEN_PROTOCOL_ALLOC: {
90 SGenProtocolAlloc *entry = data;
91 printf ("%s alloc obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
94 case SGEN_PROTOCOL_ALLOC_PINNED: {
95 SGenProtocolAlloc *entry = data;
96 printf ("%s alloc pinned obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
99 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
100 SGenProtocolAlloc *entry = data;
101 printf ("%s alloc degraded obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
104 case SGEN_PROTOCOL_COPY: {
105 SGenProtocolCopy *entry = data;
106 printf ("%s copy from %p to %p vtable %p size %d\n", WORKER_PREFIX (type), entry->from, entry->to, entry->vtable, entry->size);
109 case SGEN_PROTOCOL_PIN: {
110 SGenProtocolPin *entry = data;
111 printf ("%s pin obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
114 case SGEN_PROTOCOL_MARK: {
115 SGenProtocolMark *entry = data;
116 printf ("%s mark obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
119 case SGEN_PROTOCOL_SCAN_BEGIN: {
120 SGenProtocolScanBegin *entry = data;
121 printf ("%s scan_begin obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
124 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
125 SGenProtocolScanVTypeBegin *entry = data;
126 printf ("%s scan_vtype_begin obj %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->size);
129 case SGEN_PROTOCOL_WBARRIER: {
130 SGenProtocolWBarrier *entry = data;
131 printf ("%s wbarrier ptr %p value %p value_vtable %p\n", WORKER_PREFIX (type), entry->ptr, entry->value, entry->value_vtable);
134 case SGEN_PROTOCOL_GLOBAL_REMSET: {
135 SGenProtocolGlobalRemset *entry = data;
136 printf ("%s global_remset ptr %p value %p value_vtable %p\n", WORKER_PREFIX (type), entry->ptr, entry->value, entry->value_vtable);
139 case SGEN_PROTOCOL_PTR_UPDATE: {
140 SGenProtocolPtrUpdate *entry = data;
141 printf ("%s ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n", WORKER_PREFIX (type),
142 entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size);
145 case SGEN_PROTOCOL_CLEANUP: {
146 SGenProtocolCleanup *entry = data;
147 printf ("%s cleanup ptr %p vtable %p size %d\n", WORKER_PREFIX (type), entry->ptr, entry->vtable, entry->size);
150 case SGEN_PROTOCOL_EMPTY: {
151 SGenProtocolEmpty *entry = data;
152 printf ("%s empty start %p size %d\n", WORKER_PREFIX (type), entry->start, entry->size);
155 case SGEN_PROTOCOL_THREAD_SUSPEND: {
156 SGenProtocolThreadSuspend *entry = data;
157 printf ("%s thread_suspend thread %p ip %p\n", WORKER_PREFIX (type), entry->thread, entry->stopped_ip);
160 case SGEN_PROTOCOL_THREAD_RESTART: {
161 SGenProtocolThreadRestart *entry = data;
162 printf ("%s thread_restart thread %p\n", WORKER_PREFIX (type), entry->thread);
165 case SGEN_PROTOCOL_THREAD_REGISTER: {
166 SGenProtocolThreadRegister *entry = data;
167 printf ("%s thread_register thread %p\n", WORKER_PREFIX (type), entry->thread);
170 case SGEN_PROTOCOL_THREAD_UNREGISTER: {
171 SGenProtocolThreadUnregister *entry = data;
172 printf ("%s thread_unregister thread %p\n", WORKER_PREFIX (type), entry->thread);
175 case SGEN_PROTOCOL_MISSING_REMSET: {
176 SGenProtocolMissingRemset *entry = data;
177 printf ("%s missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n", WORKER_PREFIX (type),
178 entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
181 case SGEN_PROTOCOL_CARD_SCAN: {
182 SGenProtocolCardScan *entry = data;
183 printf ("%s card_scan start %p size %d\n", WORKER_PREFIX (type), entry->start, entry->size);
186 case SGEN_PROTOCOL_CEMENT: {
187 SGenProtocolCement *entry = data;
188 printf ("%s cement obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
191 case SGEN_PROTOCOL_CEMENT_RESET: {
192 printf ("%s cement_reset\n", WORKER_PREFIX (type));
195 case SGEN_PROTOCOL_DISLINK_UPDATE: {
196 SGenProtocolDislinkUpdate *entry = data;
197 printf ("%s dislink_update link %p obj %p staged %d", WORKER_PREFIX (type), entry->link, entry->obj, entry->staged);
199 printf (" track %d\n", entry->track);
204 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
205 SGenProtocolDislinkUpdateStaged *entry = data;
206 printf ("%s dislink_update_staged link %p obj %p index %d", WORKER_PREFIX (type), entry->link, entry->obj, entry->index);
208 printf (" track %d\n", entry->track);
213 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
214 SGenProtocolDislinkProcessStaged *entry = data;
215 printf ("%s dislink_process_staged link %p obj %p index %d\n", WORKER_PREFIX (type), entry->link, entry->obj, entry->index);
218 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: {
219 SGenProtocolDomainUnload *entry = data;
220 printf ("%s dislink_unload_begin domain %p\n", WORKER_PREFIX (type), entry->domain);
223 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: {
224 SGenProtocolDomainUnload *entry = data;
225 printf ("%s dislink_unload_end domain %p\n", WORKER_PREFIX (type), entry->domain);
234 matches_interval (gpointer ptr, gpointer start, int size)
236 return ptr >= start && (char*)ptr < (char*)start + size;
240 is_match (gpointer ptr, int type, void *data)
242 switch (TYPE (type)) {
243 case SGEN_PROTOCOL_COLLECTION_FORCE:
244 case SGEN_PROTOCOL_COLLECTION_BEGIN:
245 case SGEN_PROTOCOL_COLLECTION_END:
246 case SGEN_PROTOCOL_THREAD_SUSPEND:
247 case SGEN_PROTOCOL_THREAD_RESTART:
248 case SGEN_PROTOCOL_THREAD_REGISTER:
249 case SGEN_PROTOCOL_THREAD_UNREGISTER:
250 case SGEN_PROTOCOL_CEMENT_RESET:
251 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN:
252 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END:
254 case SGEN_PROTOCOL_ALLOC:
255 case SGEN_PROTOCOL_ALLOC_PINNED:
256 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
257 SGenProtocolAlloc *entry = data;
258 return matches_interval (ptr, entry->obj, entry->size);
260 case SGEN_PROTOCOL_COPY: {
261 SGenProtocolCopy *entry = data;
262 return matches_interval (ptr, entry->from, entry->size) || matches_interval (ptr, entry->to, entry->size);
264 case SGEN_PROTOCOL_PIN: {
265 SGenProtocolPin *entry = data;
266 return matches_interval (ptr, entry->obj, entry->size);
268 case SGEN_PROTOCOL_MARK: {
269 SGenProtocolMark *entry = data;
270 return matches_interval (ptr, entry->obj, entry->size);
272 case SGEN_PROTOCOL_SCAN_BEGIN: {
273 SGenProtocolScanBegin *entry = data;
274 return matches_interval (ptr, entry->obj, entry->size);
276 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
277 SGenProtocolScanVTypeBegin *entry = data;
278 return matches_interval (ptr, entry->obj, entry->size);
280 case SGEN_PROTOCOL_WBARRIER: {
281 SGenProtocolWBarrier *entry = data;
282 return ptr == entry->ptr || ptr == entry->value;
284 case SGEN_PROTOCOL_GLOBAL_REMSET: {
285 SGenProtocolGlobalRemset *entry = data;
286 return ptr == entry->ptr || ptr == entry->value;
288 case SGEN_PROTOCOL_PTR_UPDATE: {
289 SGenProtocolPtrUpdate *entry = data;
290 return ptr == entry->ptr ||
291 matches_interval (ptr, entry->old_value, entry->size) ||
292 matches_interval (ptr, entry->new_value, entry->size);
294 case SGEN_PROTOCOL_CLEANUP: {
295 SGenProtocolCleanup *entry = data;
296 return matches_interval (ptr, entry->ptr, entry->size);
298 case SGEN_PROTOCOL_EMPTY: {
299 SGenProtocolEmpty *entry = data;
300 return matches_interval (ptr, entry->start, entry->size);
302 case SGEN_PROTOCOL_MISSING_REMSET: {
303 SGenProtocolMissingRemset *entry = data;
304 return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset;
306 case SGEN_PROTOCOL_CARD_SCAN: {
307 SGenProtocolCardScan *entry = data;
308 return matches_interval (ptr, entry->start, entry->size);
310 case SGEN_PROTOCOL_CEMENT: {
311 SGenProtocolCement *entry = data;
312 return matches_interval (ptr, entry->obj, entry->size);
314 case SGEN_PROTOCOL_DISLINK_UPDATE: {
315 SGenProtocolDislinkUpdate *entry = data;
316 return ptr == entry->obj || ptr == entry->link;
318 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
319 SGenProtocolDislinkUpdateStaged *entry = data;
320 return ptr == entry->obj || ptr == entry->link;
322 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
323 SGenProtocolDislinkProcessStaged *entry = data;
324 return ptr == entry->obj || ptr == entry->link;
332 is_vtable_match (gpointer ptr, int type, void *data)
334 switch (TYPE (type)) {
335 case SGEN_PROTOCOL_ALLOC:
336 case SGEN_PROTOCOL_ALLOC_PINNED:
337 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
338 SGenProtocolAlloc *entry = data;
339 return ptr == entry->vtable;
341 case SGEN_PROTOCOL_COPY: {
342 SGenProtocolCopy *entry = data;
343 return ptr == entry->vtable;
345 case SGEN_PROTOCOL_PIN: {
346 SGenProtocolPin *entry = data;
347 return ptr == entry->vtable;
349 case SGEN_PROTOCOL_SCAN_BEGIN: {
350 SGenProtocolScanBegin *entry = data;
351 return ptr == entry->vtable;
353 case SGEN_PROTOCOL_WBARRIER: {
354 SGenProtocolWBarrier *entry = data;
355 return ptr == entry->value_vtable;
357 case SGEN_PROTOCOL_GLOBAL_REMSET: {
358 SGenProtocolGlobalRemset *entry = data;
359 return ptr == entry->value_vtable;
361 case SGEN_PROTOCOL_PTR_UPDATE: {
362 SGenProtocolPtrUpdate *entry = data;
363 return ptr == entry->vtable;
365 case SGEN_PROTOCOL_CLEANUP: {
366 SGenProtocolCleanup *entry = data;
367 return ptr == entry->vtable;
369 case SGEN_PROTOCOL_MISSING_REMSET: {
370 SGenProtocolMissingRemset *entry = data;
371 return ptr == entry->obj_vtable || ptr == entry->value_vtable;
373 case SGEN_PROTOCOL_CEMENT: {
374 SGenProtocolCement *entry = data;
375 return ptr == entry->vtable;
382 static gboolean dump_all = FALSE;
385 main (int argc, char *argv[])
389 int num_args = argc - 1;
393 long nums [num_args];
394 long vtables [num_args];
396 for (i = 0; i < num_args; ++i) {
397 char *arg = argv [i + 1];
398 char *next_arg = argv [i + 2];
399 if (!strcmp (arg, "--all")) {
401 } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
402 vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
405 nums [num_nums++] = strtoul (arg, NULL, 16);
409 while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
410 gboolean match = FALSE;
411 for (i = 0; i < num_nums; ++i) {
412 if (is_match ((gpointer) nums [i], type, data)) {
418 for (i = 0; i < num_vtables; ++i) {
419 if (is_vtable_match ((gpointer) vtables [i], type, data)) {
426 printf (match ? "* " : " ");
427 if (match || dump_all)
428 print_entry (type, data);