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