2010-06-05 Mark Probst <mark.probst@gmail.com>
[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 #include <mono/metadata/sgen-protocol.h>
7
8 #define SGEN_PROTOCOL_EOF       255
9
10 static int
11 read_entry (FILE *in, void **data)
12 {
13         unsigned char type;
14         int size;
15
16         if (fread (&type, 1, 1, in) != 1)
17                 return SGEN_PROTOCOL_EOF;
18         switch (type) {
19         case SGEN_PROTOCOL_COLLECTION: size = sizeof (SGenProtocolCollection); break;
20         case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break;
21         case SGEN_PROTOCOL_ALLOC_PINNED: size = sizeof (SGenProtocolAlloc); break;
22         case SGEN_PROTOCOL_ALLOC_DEGRADED: size = sizeof (SGenProtocolAlloc); break;
23         case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break;
24         case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break;
25         case SGEN_PROTOCOL_MARK: size = sizeof (SGenProtocolMark); break;
26         case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break;
27         case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break;
28         case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break;
29         case SGEN_PROTOCOL_CLEANUP: size = sizeof (SGenProtocolCleanup); break;
30         case SGEN_PROTOCOL_EMPTY: size = sizeof (SGenProtocolEmpty); break;
31         case SGEN_PROTOCOL_THREAD_RESTART: size = sizeof (SGenProtocolThreadRestart); break;
32         case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break;
33         case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break;
34         case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break;
35         default: assert (0);
36         }
37
38         *data = malloc (size);
39         if (fread (*data, size, 1, in) != 1)
40                 assert (0);
41
42         return (int)type;
43 }
44
45 static void
46 print_entry (int type, void *data)
47 {
48         switch (type) {
49         case SGEN_PROTOCOL_COLLECTION: {
50                 SGenProtocolCollection *entry = data;
51                 printf ("collection generation %d\n", entry->generation);
52                 break;
53         }
54         case SGEN_PROTOCOL_ALLOC: {
55                 SGenProtocolAlloc *entry = data;
56                 printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
57                 break;
58         }
59         case SGEN_PROTOCOL_ALLOC_PINNED: {
60                 SGenProtocolAlloc *entry = data;
61                 printf ("alloc pinned obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
62                 break;
63         }
64         case SGEN_PROTOCOL_ALLOC_DEGRADED: {
65                 SGenProtocolAlloc *entry = data;
66                 printf ("alloc degraded obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
67                 break;
68         }
69         case SGEN_PROTOCOL_COPY: {
70                 SGenProtocolCopy *entry = data;
71                 printf ("copy from %p to %p vtable %p size %d\n", entry->from, entry->to, entry->vtable, entry->size);
72                 break;
73         }
74         case SGEN_PROTOCOL_PIN: {
75                 SGenProtocolPin *entry = data;
76                 printf ("pin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
77                 break;
78         }
79         case SGEN_PROTOCOL_MARK: {
80                 SGenProtocolMark *entry = data;
81                 printf ("mark obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
82                 break;
83         }
84         case SGEN_PROTOCOL_WBARRIER: {
85                 SGenProtocolWBarrier *entry = data;
86                 printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
87                 break;
88         }
89         case SGEN_PROTOCOL_GLOBAL_REMSET: {
90                 SGenProtocolGlobalRemset *entry = data;
91                 printf ("global_remset ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
92                 break;
93         }
94         case SGEN_PROTOCOL_PTR_UPDATE: {
95                 SGenProtocolPtrUpdate *entry = data;
96                 printf ("ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n",
97                                 entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size);
98                 break;
99         }
100         case SGEN_PROTOCOL_CLEANUP: {
101                 SGenProtocolCleanup *entry = data;
102                 printf ("cleanup ptr %p vtable %p size %d\n", entry->ptr, entry->vtable, entry->size);
103                 break;
104         }
105         case SGEN_PROTOCOL_EMPTY: {
106                 SGenProtocolEmpty *entry = data;
107                 printf ("empty start %p size %d\n", entry->start, entry->size);
108                 break;
109         }
110         case SGEN_PROTOCOL_THREAD_RESTART: {
111                 SGenProtocolThreadRestart *entry = data;
112                 printf ("thread_restart thread %p\n", entry->thread);
113                 break;
114         }
115         case SGEN_PROTOCOL_THREAD_REGISTER: {
116                 SGenProtocolThreadRegister *entry = data;
117                 printf ("thread_register thread %p\n", entry->thread);
118                 break;
119         }
120         case SGEN_PROTOCOL_THREAD_UNREGISTER: {
121                 SGenProtocolThreadUnregister *entry = data;
122                 printf ("thread_unregister thread %p\n", entry->thread);
123                 break;
124         }
125         case SGEN_PROTOCOL_MISSING_REMSET: {
126                 SGenProtocolMissingRemset *entry = data;
127                 printf ("missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n",
128                                 entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
129                 break;
130         }
131         default:
132                 assert (0);
133         }
134 }
135
136 static gboolean
137 matches_interval (gpointer ptr, gpointer start, int size)
138 {
139         return ptr >= start && (char*)ptr < (char*)start + size;
140 }
141
142 static gboolean
143 is_match (gpointer ptr, int type, void *data)
144 {
145         switch (type) {
146         case SGEN_PROTOCOL_COLLECTION:
147         case SGEN_PROTOCOL_THREAD_RESTART:
148         case SGEN_PROTOCOL_THREAD_REGISTER:
149         case SGEN_PROTOCOL_THREAD_UNREGISTER:
150                 return TRUE;
151         case SGEN_PROTOCOL_ALLOC:
152         case SGEN_PROTOCOL_ALLOC_PINNED:
153         case SGEN_PROTOCOL_ALLOC_DEGRADED: {
154                 SGenProtocolAlloc *entry = data;
155                 return matches_interval (ptr, entry->obj, entry->size);
156         }
157         case SGEN_PROTOCOL_COPY: {
158                 SGenProtocolCopy *entry = data;
159                 return matches_interval (ptr, entry->from, entry->size) || matches_interval (ptr, entry->to, entry->size);
160         }
161         case SGEN_PROTOCOL_PIN: {
162                 SGenProtocolPin *entry = data;
163                 return matches_interval (ptr, entry->obj, entry->size);
164         }
165         case SGEN_PROTOCOL_MARK: {
166                 SGenProtocolMark *entry = data;
167                 return matches_interval (ptr, entry->obj, entry->size);
168         }
169         case SGEN_PROTOCOL_WBARRIER: {
170                 SGenProtocolWBarrier *entry = data;
171                 return ptr == entry->ptr || ptr == entry->value;
172         }
173         case SGEN_PROTOCOL_GLOBAL_REMSET: {
174                 SGenProtocolGlobalRemset *entry = data;
175                 return ptr == entry->ptr || ptr == entry->value;
176         }
177         case SGEN_PROTOCOL_PTR_UPDATE: {
178                 SGenProtocolPtrUpdate *entry = data;
179                 return ptr == entry->ptr ||
180                         matches_interval (ptr, entry->old_value, entry->size) ||
181                         matches_interval (ptr, entry->new_value, entry->size);
182         }
183         case SGEN_PROTOCOL_CLEANUP: {
184                 SGenProtocolCleanup *entry = data;
185                 return matches_interval (ptr, entry->ptr, entry->size);
186         }
187         case SGEN_PROTOCOL_EMPTY: {
188                 SGenProtocolEmpty *entry = data;
189                 return matches_interval (ptr, entry->start, entry->size);
190         }
191         case SGEN_PROTOCOL_MISSING_REMSET: {
192                 SGenProtocolMissingRemset *entry = data;
193                 return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset;
194         }
195         default:
196                 assert (0);
197         }
198 }
199
200 int
201 main (int argc, char *argv[])
202 {
203         int type;
204         void *data;
205         int num_nums = argc - 1;
206         int i;
207         long nums [num_nums];
208
209         for (i = 0; i < num_nums; ++i)
210                 nums [i] = strtoul (argv [i + 1], NULL, 16);
211
212         while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
213                 gboolean match = FALSE;
214                 for (i = 0; i < num_nums; ++i) {
215                         if (is_match ((gpointer) nums [i], type, data)) {
216                                 match = TRUE;
217                                 break;
218                         }
219                 }
220                 if (match)
221                         print_entry (type, data);
222                 free (data);
223         }
224
225         return 0;
226 }