diff options
author | Mark Probst <mark.probst@gmail.com> | 2010-03-02 21:06:15 +0300 |
---|---|---|
committer | Mark Probst <mark.probst@gmail.com> | 2010-03-02 21:06:15 +0300 |
commit | 0672c30e8b556b5dc107489bdbd537f637947f20 (patch) | |
tree | ddfd2f0996b4b457937e3ef1d3caf89a9ab68a37 /tools | |
parent | c45790b4695bd2169c997bd2e8cf88b1902c9fe1 (diff) |
2010-03-02 Mark Probst <mark.probst@gmail.com>
* sgen-gc.c, sgen-protocol.c, sgen-protocol.h: New facility for
writing binary log files (can be enabled by #define'ing
BINARY_PROTOCOL) for better debugging of timing-dependent bugs or
bugs in longer running programs.
2010-03-02 Mark Probst <mark.probst@gmail.com>
* tools/sgen-grep-binprot.c: Tool for searching through the binary
protocol files generated by SGen.
svn path=/trunk/mono/; revision=152864
Diffstat (limited to 'tools')
-rw-r--r-- | tools/sgen-grep-binprot.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/tools/sgen-grep-binprot.c b/tools/sgen-grep-binprot.c new file mode 100644 index 00000000000..849433ddc9e --- /dev/null +++ b/tools/sgen-grep-binprot.c @@ -0,0 +1,202 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <glib.h> + +#include "../mono/metadata/sgen-protocol.h" + +#define SGEN_PROTOCOL_EOF 255 + +static int +read_entry (FILE *in, void **data) +{ + unsigned char type; + int size; + + if (fread (&type, 1, 1, in) != 1) + return SGEN_PROTOCOL_EOF; + switch (type) { + case SGEN_PROTOCOL_COLLECTION: size = sizeof (SGenProtocolCollection); break; + case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break; + case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break; + case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break; + case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break; + case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break; + case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break; + case SGEN_PROTOCOL_CLEANUP: size = sizeof (SGenProtocolCleanup); break; + case SGEN_PROTOCOL_EMPTY: size = sizeof (SGenProtocolEmpty); break; + case SGEN_PROTOCOL_THREAD_RESTART: size = sizeof (SGenProtocolThreadRestart); break; + case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break; + case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break; + case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break; + default: assert (0); + } + + *data = malloc (size); + if (fread (*data, size, 1, in) != 1) + assert (0); + + return (int)type; +} + +static void +print_entry (int type, void *data) +{ + switch (type) { + case SGEN_PROTOCOL_COLLECTION: { + SGenProtocolCollection *entry = data; + printf ("collection generation %d\n", entry->generation); + break; + } + case SGEN_PROTOCOL_ALLOC: { + SGenProtocolAlloc *entry = data; + printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size); + break; + } + case SGEN_PROTOCOL_COPY: { + SGenProtocolCopy *entry = data; + printf ("copy from %p to %p vtable %p size %d\n", entry->from, entry->to, entry->vtable, entry->size); + break; + } + case SGEN_PROTOCOL_PIN: { + SGenProtocolPin *entry = data; + printf ("pin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size); + break; + } + case SGEN_PROTOCOL_WBARRIER: { + SGenProtocolWBarrier *entry = data; + printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable); + break; + } + case SGEN_PROTOCOL_GLOBAL_REMSET: { + SGenProtocolGlobalRemset *entry = data; + printf ("global_remset ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable); + break; + } + case SGEN_PROTOCOL_PTR_UPDATE: { + SGenProtocolPtrUpdate *entry = data; + printf ("ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n", + entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size); + break; + } + case SGEN_PROTOCOL_CLEANUP: { + SGenProtocolCleanup *entry = data; + printf ("cleanup ptr %p vtable %p size %d\n", entry->ptr, entry->vtable, entry->size); + break; + } + case SGEN_PROTOCOL_EMPTY: { + SGenProtocolEmpty *entry = data; + printf ("empty start %p size %d\n", entry->start, entry->size); + break; + } + case SGEN_PROTOCOL_THREAD_RESTART: { + SGenProtocolThreadRestart *entry = data; + printf ("thread_restart thread %p\n", entry->thread); + break; + } + case SGEN_PROTOCOL_THREAD_REGISTER: { + SGenProtocolThreadRegister *entry = data; + printf ("thread_register thread %p\n", entry->thread); + break; + } + case SGEN_PROTOCOL_THREAD_UNREGISTER: { + SGenProtocolThreadUnregister *entry = data; + printf ("thread_unregister thread %p\n", entry->thread); + break; + } + case SGEN_PROTOCOL_MISSING_REMSET: { + SGenProtocolMissingRemset *entry = data; + printf ("missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n", + entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned); + break; + } + default: + assert (0); + } +} + +static gboolean +matches_interval (gpointer ptr, gpointer start, int size) +{ + return ptr >= start && (char*)ptr < (char*)start + size; +} + +static gboolean +is_match (gpointer ptr, int type, void *data) +{ + switch (type) { + case SGEN_PROTOCOL_COLLECTION: + case SGEN_PROTOCOL_THREAD_RESTART: + case SGEN_PROTOCOL_THREAD_REGISTER: + case SGEN_PROTOCOL_THREAD_UNREGISTER: + return TRUE; + case SGEN_PROTOCOL_ALLOC: { + SGenProtocolAlloc *entry = data; + return matches_interval (ptr, entry->obj, entry->size); + } + case SGEN_PROTOCOL_COPY: { + SGenProtocolCopy *entry = data; + return matches_interval (ptr, entry->from, entry->size) || matches_interval (ptr, entry->to, entry->size); + } + case SGEN_PROTOCOL_PIN: { + SGenProtocolPin *entry = data; + return matches_interval (ptr, entry->obj, entry->size); + } + case SGEN_PROTOCOL_WBARRIER: { + SGenProtocolWBarrier *entry = data; + return ptr == entry->ptr || ptr == entry->value; + } + case SGEN_PROTOCOL_GLOBAL_REMSET: { + SGenProtocolGlobalRemset *entry = data; + return ptr == entry->ptr || ptr == entry->value; + } + case SGEN_PROTOCOL_PTR_UPDATE: { + SGenProtocolPtrUpdate *entry = data; + return ptr == entry->ptr || + matches_interval (ptr, entry->old_value, entry->size) || + matches_interval (ptr, entry->new_value, entry->size); + } + case SGEN_PROTOCOL_CLEANUP: { + SGenProtocolCleanup *entry = data; + return matches_interval (ptr, entry->ptr, entry->size); + } + case SGEN_PROTOCOL_EMPTY: { + SGenProtocolEmpty *entry = data; + return matches_interval (ptr, entry->start, entry->size); + } + case SGEN_PROTOCOL_MISSING_REMSET: { + SGenProtocolMissingRemset *entry = data; + return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset; + } + default: + assert (0); + } +} + +int +main (int argc, char *argv[]) +{ + int type; + void *data; + int num_nums = argc - 1; + int i; + long nums [num_nums]; + + for (i = 0; i < num_nums; ++i) + nums [i] = strtol (argv [i + 1], NULL, 16); + + while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) { + gboolean match = FALSE; + for (i = 0; i < num_nums; ++i) { + if (is_match ((gpointer) nums [i], type, data)) { + match = TRUE; + break; + } + } + if (match) + print_entry (type, data); + free (data); + } + + return 0; +} |