SqlBulkCopy Implementation
[mono.git] / tools / sgen / sgen-grep-binprot.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <glib.h>
5
6 #define SGEN_BINARY_PROTOCOL
7 #define MONO_INTERNAL
8
9 #include <mono/metadata/sgen-protocol.h>
10
11 #define SGEN_PROTOCOL_EOF       255
12
13 static int
14 read_entry (FILE *in, void **data)
15 {
16         unsigned char type;
17         int size;
18
19         if (fread (&type, 1, 1, in) != 1)
20                 return SGEN_PROTOCOL_EOF;
21         switch (type) {
22         case SGEN_PROTOCOL_COLLECTION_FORCE: size = sizeof (SGenProtocolCollectionForce); break;
23         case SGEN_PROTOCOL_COLLECTION_BEGIN: size = sizeof (SGenProtocolCollection); break;
24         case SGEN_PROTOCOL_COLLECTION_END: size = sizeof (SGenProtocolCollection); break;
25         case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break;
26         case SGEN_PROTOCOL_ALLOC_PINNED: size = sizeof (SGenProtocolAlloc); break;
27         case SGEN_PROTOCOL_ALLOC_DEGRADED: size = sizeof (SGenProtocolAlloc); break;
28         case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break;
29         case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break;
30         case SGEN_PROTOCOL_MARK: size = sizeof (SGenProtocolMark); break;
31         case SGEN_PROTOCOL_SCAN_BEGIN: size = sizeof (SGenProtocolScanBegin); break;
32         case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: size = sizeof (SGenProtocolScanVTypeBegin); break;
33         case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break;
34         case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break;
35         case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break;
36         case SGEN_PROTOCOL_CLEANUP: size = sizeof (SGenProtocolCleanup); break;
37         case SGEN_PROTOCOL_EMPTY: size = sizeof (SGenProtocolEmpty); break;
38         case SGEN_PROTOCOL_THREAD_SUSPEND: size = sizeof (SGenProtocolThreadSuspend); break;
39         case SGEN_PROTOCOL_THREAD_RESTART: size = sizeof (SGenProtocolThreadRestart); break;
40         case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break;
41         case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break;
42         case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break;
43         case SGEN_PROTOCOL_CARD_SCAN: size = sizeof (SGenProtocolCardScan); break;
44         case SGEN_PROTOCOL_CEMENT: size = sizeof (SGenProtocolCement); break;
45         case SGEN_PROTOCOL_CEMENT_RESET: size = 0; break;
46         case SGEN_PROTOCOL_DISLINK_UPDATE: size = sizeof (SGenProtocolDislinkUpdate); break;
47         case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: size = sizeof (SGenProtocolDislinkUpdateStaged); break;
48         case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: size = sizeof (SGenProtocolDislinkProcessStaged); break;
49         case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: size = sizeof (SGenProtocolDomainUnload); break;
50         case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: size = sizeof (SGenProtocolDomainUnload); break;
51         default: assert (0);
52         }
53
54         if (size) {
55                 *data = malloc (size);
56                 if (fread (*data, size, 1, in) != 1)
57                         assert (0);
58         } else {
59                 *data = NULL;
60         }
61
62         return (int)type;
63 }
64
65 static void
66 print_entry (int type, void *data)
67 {
68         switch (type) {
69         case SGEN_PROTOCOL_COLLECTION_FORCE: {
70                 SGenProtocolCollectionForce *entry = data;
71                 printf ("collection force generation %d\n", entry->generation);
72                 break;
73         }
74         case SGEN_PROTOCOL_COLLECTION_BEGIN: {
75                 SGenProtocolCollection *entry = data;
76                 printf ("collection begin %d generation %d\n", entry->index, entry->generation);
77                 break;
78         }
79         case SGEN_PROTOCOL_COLLECTION_END: {
80                 SGenProtocolCollection *entry = data;
81                 printf ("collection end %d generation %d\n", entry->index, entry->generation);
82                 break;
83         }
84         case SGEN_PROTOCOL_ALLOC: {
85                 SGenProtocolAlloc *entry = data;
86                 printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
87                 break;
88         }
89         case SGEN_PROTOCOL_ALLOC_PINNED: {
90                 SGenProtocolAlloc *entry = data;
91                 printf ("alloc pinned obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
92                 break;
93         }
94         case SGEN_PROTOCOL_ALLOC_DEGRADED: {
95                 SGenProtocolAlloc *entry = data;
96                 printf ("alloc degraded obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
97                 break;
98         }
99         case SGEN_PROTOCOL_COPY: {
100                 SGenProtocolCopy *entry = data;
101                 printf ("copy from %p to %p vtable %p size %d\n", entry->from, entry->to, entry->vtable, entry->size);
102                 break;
103         }
104         case SGEN_PROTOCOL_PIN: {
105                 SGenProtocolPin *entry = data;
106                 printf ("pin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
107                 break;
108         }
109         case SGEN_PROTOCOL_MARK: {
110                 SGenProtocolMark *entry = data;
111                 printf ("mark obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
112                 break;
113         }
114         case SGEN_PROTOCOL_SCAN_BEGIN: {
115                 SGenProtocolScanBegin *entry = data;
116                 printf ("scan_begin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
117                 break;
118         }
119         case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
120                 SGenProtocolScanVTypeBegin *entry = data;
121                 printf ("scan_vtype_begin obj %p size %d\n", entry->obj, entry->size);
122                 break;
123         }
124         case SGEN_PROTOCOL_WBARRIER: {
125                 SGenProtocolWBarrier *entry = data;
126                 printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
127                 break;
128         }
129         case SGEN_PROTOCOL_GLOBAL_REMSET: {
130                 SGenProtocolGlobalRemset *entry = data;
131                 printf ("global_remset ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
132                 break;
133         }
134         case SGEN_PROTOCOL_PTR_UPDATE: {
135                 SGenProtocolPtrUpdate *entry = data;
136                 printf ("ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n",
137                                 entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size);
138                 break;
139         }
140         case SGEN_PROTOCOL_CLEANUP: {
141                 SGenProtocolCleanup *entry = data;
142                 printf ("cleanup ptr %p vtable %p size %d\n", entry->ptr, entry->vtable, entry->size);
143                 break;
144         }
145         case SGEN_PROTOCOL_EMPTY: {
146                 SGenProtocolEmpty *entry = data;
147                 printf ("empty start %p size %d\n", entry->start, entry->size);
148                 break;
149         }
150         case SGEN_PROTOCOL_THREAD_SUSPEND: {
151                 SGenProtocolThreadSuspend *entry = data;
152                 printf ("thread_suspend thread %p ip %p\n", entry->thread, entry->stopped_ip);
153                 break;
154         }
155         case SGEN_PROTOCOL_THREAD_RESTART: {
156                 SGenProtocolThreadRestart *entry = data;
157                 printf ("thread_restart thread %p\n", entry->thread);
158                 break;
159         }
160         case SGEN_PROTOCOL_THREAD_REGISTER: {
161                 SGenProtocolThreadRegister *entry = data;
162                 printf ("thread_register thread %p\n", entry->thread);
163                 break;
164         }
165         case SGEN_PROTOCOL_THREAD_UNREGISTER: {
166                 SGenProtocolThreadUnregister *entry = data;
167                 printf ("thread_unregister thread %p\n", entry->thread);
168                 break;
169         }
170         case SGEN_PROTOCOL_MISSING_REMSET: {
171                 SGenProtocolMissingRemset *entry = data;
172                 printf ("missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n",
173                                 entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
174                 break;
175         }
176         case SGEN_PROTOCOL_CARD_SCAN: {
177                 SGenProtocolCardScan *entry = data;
178                 printf ("card_scan start %p size %d\n", entry->start, entry->size);
179                 break;
180         }
181         case SGEN_PROTOCOL_CEMENT: {
182                 SGenProtocolCement *entry = data;
183                 printf ("cement obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
184                 break;
185         }
186         case SGEN_PROTOCOL_CEMENT_RESET: {
187                 printf ("cement_reset\n");
188                 break;
189         }
190         case SGEN_PROTOCOL_DISLINK_UPDATE: {
191                 SGenProtocolDislinkUpdate *entry = data;
192                 printf ("dislink_update link %p obj %p staged %d", entry->link, entry->obj, entry->staged);
193                 if (entry->obj)
194                         printf (" track %d\n", entry->track);
195                 else
196                         printf ("\n");
197                 break;
198         }
199         case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
200                 SGenProtocolDislinkUpdateStaged *entry = data;
201                 printf ("dislink_update_staged link %p obj %p index %d", entry->link, entry->obj, entry->index);
202                 if (entry->obj)
203                         printf (" track %d\n", entry->track);
204                 else
205                         printf ("\n");
206                 break;
207         }
208         case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
209                 SGenProtocolDislinkProcessStaged *entry = data;
210                 printf ("dislink_process_staged link %p obj %p index %d\n", entry->link, entry->obj, entry->index);
211                 break;
212         }
213         case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: {
214                 SGenProtocolDomainUnload *entry = data;
215                 printf ("dislink_unload_begin domain %p\n", entry->domain);
216                 break;
217         }
218         case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: {
219                 SGenProtocolDomainUnload *entry = data;
220                 printf ("dislink_unload_end domain %p\n", entry->domain);
221                 break;
222         }
223         default:
224                 assert (0);
225         }
226 }
227
228 static gboolean
229 matches_interval (gpointer ptr, gpointer start, int size)
230 {
231         return ptr >= start && (char*)ptr < (char*)start + size;
232 }
233
234 static gboolean
235 is_match (gpointer ptr, int type, void *data)
236 {
237         switch (type) {
238         case SGEN_PROTOCOL_COLLECTION_FORCE:
239         case SGEN_PROTOCOL_COLLECTION_BEGIN:
240         case SGEN_PROTOCOL_COLLECTION_END:
241         case SGEN_PROTOCOL_THREAD_SUSPEND:
242         case SGEN_PROTOCOL_THREAD_RESTART:
243         case SGEN_PROTOCOL_THREAD_REGISTER:
244         case SGEN_PROTOCOL_THREAD_UNREGISTER:
245         case SGEN_PROTOCOL_CEMENT_RESET:
246         case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN:
247         case SGEN_PROTOCOL_DOMAIN_UNLOAD_END:
248                 return TRUE;
249         case SGEN_PROTOCOL_ALLOC:
250         case SGEN_PROTOCOL_ALLOC_PINNED:
251         case SGEN_PROTOCOL_ALLOC_DEGRADED: {
252                 SGenProtocolAlloc *entry = data;
253                 return matches_interval (ptr, entry->obj, entry->size);
254         }
255         case SGEN_PROTOCOL_COPY: {
256                 SGenProtocolCopy *entry = data;
257                 return matches_interval (ptr, entry->from, entry->size) || matches_interval (ptr, entry->to, entry->size);
258         }
259         case SGEN_PROTOCOL_PIN: {
260                 SGenProtocolPin *entry = data;
261                 return matches_interval (ptr, entry->obj, entry->size);
262         }
263         case SGEN_PROTOCOL_MARK: {
264                 SGenProtocolMark *entry = data;
265                 return matches_interval (ptr, entry->obj, entry->size);
266         }
267         case SGEN_PROTOCOL_SCAN_BEGIN: {
268                 SGenProtocolScanBegin *entry = data;
269                 return matches_interval (ptr, entry->obj, entry->size);
270         }
271         case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
272                 SGenProtocolScanVTypeBegin *entry = data;
273                 return matches_interval (ptr, entry->obj, entry->size);
274         }
275         case SGEN_PROTOCOL_WBARRIER: {
276                 SGenProtocolWBarrier *entry = data;
277                 return ptr == entry->ptr || ptr == entry->value;
278         }
279         case SGEN_PROTOCOL_GLOBAL_REMSET: {
280                 SGenProtocolGlobalRemset *entry = data;
281                 return ptr == entry->ptr || ptr == entry->value;
282         }
283         case SGEN_PROTOCOL_PTR_UPDATE: {
284                 SGenProtocolPtrUpdate *entry = data;
285                 return ptr == entry->ptr ||
286                         matches_interval (ptr, entry->old_value, entry->size) ||
287                         matches_interval (ptr, entry->new_value, entry->size);
288         }
289         case SGEN_PROTOCOL_CLEANUP: {
290                 SGenProtocolCleanup *entry = data;
291                 return matches_interval (ptr, entry->ptr, entry->size);
292         }
293         case SGEN_PROTOCOL_EMPTY: {
294                 SGenProtocolEmpty *entry = data;
295                 return matches_interval (ptr, entry->start, entry->size);
296         }
297         case SGEN_PROTOCOL_MISSING_REMSET: {
298                 SGenProtocolMissingRemset *entry = data;
299                 return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset;
300         }
301         case SGEN_PROTOCOL_CARD_SCAN: {
302                 SGenProtocolCardScan *entry = data;
303                 return matches_interval (ptr, entry->start, entry->size);
304         }
305         case SGEN_PROTOCOL_CEMENT: {
306                 SGenProtocolCement *entry = data;
307                 return matches_interval (ptr, entry->obj, entry->size);
308         }
309         case SGEN_PROTOCOL_DISLINK_UPDATE: {
310                 SGenProtocolDislinkUpdate *entry = data;
311                 return ptr == entry->obj || ptr == entry->link;
312         }
313         case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
314                 SGenProtocolDislinkUpdateStaged *entry = data;
315                 return ptr == entry->obj || ptr == entry->link;
316         }
317         case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
318                 SGenProtocolDislinkProcessStaged *entry = data;
319                 return ptr == entry->obj || ptr == entry->link;
320         }
321         default:
322                 assert (0);
323         }
324 }
325
326 static gboolean
327 is_vtable_match (gpointer ptr, int type, void *data)
328 {
329         switch (type) {
330         case SGEN_PROTOCOL_ALLOC:
331         case SGEN_PROTOCOL_ALLOC_PINNED:
332         case SGEN_PROTOCOL_ALLOC_DEGRADED: {
333                 SGenProtocolAlloc *entry = data;
334                 return ptr == entry->vtable;
335         }
336         case SGEN_PROTOCOL_COPY: {
337                 SGenProtocolCopy *entry = data;
338                 return ptr == entry->vtable;
339         }
340         case SGEN_PROTOCOL_PIN: {
341                 SGenProtocolPin *entry = data;
342                 return ptr == entry->vtable;
343         }
344         case SGEN_PROTOCOL_SCAN_BEGIN: {
345                 SGenProtocolScanBegin *entry = data;
346                 return ptr == entry->vtable;
347         }
348         case SGEN_PROTOCOL_WBARRIER: {
349                 SGenProtocolWBarrier *entry = data;
350                 return ptr == entry->value_vtable;
351         }
352         case SGEN_PROTOCOL_GLOBAL_REMSET: {
353                 SGenProtocolGlobalRemset *entry = data;
354                 return ptr == entry->value_vtable;
355         }
356         case SGEN_PROTOCOL_PTR_UPDATE: {
357                 SGenProtocolPtrUpdate *entry = data;
358                 return ptr == entry->vtable;
359         }
360         case SGEN_PROTOCOL_CLEANUP: {
361                 SGenProtocolCleanup *entry = data;
362                 return ptr == entry->vtable;
363         }
364         case SGEN_PROTOCOL_MISSING_REMSET: {
365                 SGenProtocolMissingRemset *entry = data;
366                 return ptr == entry->obj_vtable || ptr == entry->value_vtable;
367         }
368         case SGEN_PROTOCOL_CEMENT: {
369                 SGenProtocolCement *entry = data;
370                 return ptr == entry->vtable;
371         }
372         default:
373                 return FALSE;
374         }
375 }
376
377 static gboolean dump_all = FALSE;
378
379 int
380 main (int argc, char *argv[])
381 {
382         int type;
383         void *data;
384         int num_args = argc - 1;
385         int num_nums = 0;
386         int num_vtables = 0;
387         int i;
388         long nums [num_args];
389         long vtables [num_args];
390
391         for (i = 0; i < num_args; ++i) {
392                 char *arg = argv [i + 1];
393                 char *next_arg = argv [i + 2];
394                 if (!strcmp (arg, "--all")) {
395                         dump_all = TRUE;
396                 } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
397                         vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
398                         ++i;
399                 } else {
400                         nums [num_nums++] = strtoul (arg, NULL, 16);
401                 }
402         }
403
404         while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
405                 gboolean match = FALSE;
406                 for (i = 0; i < num_nums; ++i) {
407                         if (is_match ((gpointer) nums [i], type, data)) {
408                                 match = TRUE;
409                                 break;
410                         }
411                 }
412                 if (!match) {
413                         for (i = 0; i < num_vtables; ++i) {
414                                 if (is_vtable_match ((gpointer) vtables [i], type, data)) {
415                                         match = TRUE;
416                                         break;
417                                 }
418                         }
419                 }
420                 if (dump_all)
421                         printf (match ? "* " : "  ");
422                 if (match || dump_all)
423                         print_entry (type, data);
424                 free (data);
425         }
426
427         return 0;
428 }