Merge pull request #2971 from BrzVlad/feature-cross-binprot
authorVlad Brezae <brezaevlad@gmail.com>
Wed, 11 May 2016 19:37:35 +0000 (22:37 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Wed, 11 May 2016 19:37:35 +0000 (22:37 +0300)
[sgen] Cross platform binary protocol grep

12 files changed:
mono/metadata/sgen-client-mono.h
mono/sgen/sgen-gc.h
mono/sgen/sgen-protocol-def.h
mono/sgen/sgen-protocol.c
mono/sgen/sgen-protocol.h
tools/sgen/.gitignore
tools/sgen/Makefile.am
tools/sgen/sgen-entry-stream.c [new file with mode: 0644]
tools/sgen/sgen-entry-stream.h [new file with mode: 0644]
tools/sgen/sgen-grep-binprot-main.c [new file with mode: 0644]
tools/sgen/sgen-grep-binprot.c
tools/sgen/sgen-grep-binprot.h [new file with mode: 0644]

index 36d6e7e968151fd47f0474fe538fd49a4d1b9bf1..02cfce160ca364ad25a6c909523cbd2785408a42 100644 (file)
@@ -689,6 +689,11 @@ sgen_client_binary_protocol_concurrent_sweep_end (long long timestamp)
 {
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_header (long long check, int version, int ptr_size, gboolean little_endian)
+{
+}
+
 int sgen_thread_handshake (BOOL suspend);
 gboolean sgen_suspend_thread (SgenThreadInfo *info);
 gboolean sgen_resume_thread (SgenThreadInfo *info);
index f3d868a541648015aba3ef73d8a88f8345a30390..565514568c5c2f688189efa417d00f133dc7b503 100644 (file)
@@ -548,7 +548,8 @@ void sgen_split_nursery_init (SgenMinorCollector *collector);
 /* Updating references */
 
 #ifdef SGEN_CHECK_UPDATE_REFERENCE
-gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread) MONO_INTERNAL;
+gboolean sgen_thread_pool_is_thread_pool_thread (MonoNativeThreadId some_thread);
+
 static inline void
 sgen_update_reference (GCObject **p, GCObject *o, gboolean allow_null)
 {
index 3ab36e3bf660f380b9b21cf554f0e659899eb520..41b8b83829183ecfcefe33f0a761c877c8b25f2c 100644 (file)
@@ -284,7 +284,7 @@ END_PROTOCOL_ENTRY
 BEGIN_PROTOCOL_ENTRY6 (binary_protocol_missing_remset, TYPE_POINTER, obj, TYPE_POINTER, obj_vtable, TYPE_INT, offset, TYPE_POINTER, value, TYPE_POINTER, value_vtable, TYPE_BOOL, value_pinned)
 DEFAULT_PRINT ()
 IS_ALWAYS_MATCH (FALSE)
-MATCH_INDEX (ptr == entry->obj ? 0 : ptr == entry->value ? 3 : ptr == (char*)entry->obj + entry->offset ? BINARY_PROTOCOL_MATCH : BINARY_PROTOCOL_NO_MATCH)
+MATCH_INDEX (ptr == entry->obj ? 0 : ptr == entry->value ? 3 : ptr == entry->obj + entry->offset ? BINARY_PROTOCOL_MATCH : BINARY_PROTOCOL_NO_MATCH)
 IS_VTABLE_MATCH (ptr == entry->obj_vtable || ptr == entry->value_vtable)
 END_PROTOCOL_ENTRY
 
@@ -331,7 +331,7 @@ IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY_HEAVY
 
 BEGIN_PROTOCOL_ENTRY_HEAVY3 (binary_protocol_dislink_update, TYPE_POINTER, link, TYPE_POINTER, obj, TYPE_BOOL, track)
-CUSTOM_PRINT(entry->obj ? printf ("link %p obj %p track %d", entry->link, entry->obj, entry->track) : printf ("link %p obj %p", entry->link, entry->obj))
+CUSTOM_PRINT(entry->obj ? printf ("link 0x%"MWORD_FORMAT_SPEC_P" obj 0x%"MWORD_FORMAT_SPEC_P" track %d", entry->link, entry->obj, entry->track) : printf ("link 0x%"MWORD_FORMAT_SPEC_P" obj 0x%"MWORD_FORMAT_SPEC_P, entry->link, entry->obj))
 IS_ALWAYS_MATCH (FALSE)
 MATCH_INDEX (ptr == entry->link ? 0 : ptr == entry->obj ? 1 : BINARY_PROTOCOL_NO_MATCH)
 IS_VTABLE_MATCH (FALSE)
@@ -442,6 +442,13 @@ MATCH_INDEX (BINARY_PROTOCOL_MATCH)
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY
 
+BEGIN_PROTOCOL_ENTRY4 (binary_protocol_header, TYPE_LONGLONG, check, TYPE_INT, version, TYPE_INT, ptr_size, TYPE_BOOL, little_endian)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (TRUE)
+MATCH_INDEX (BINARY_PROTOCOL_MATCH)
+IS_VTABLE_MATCH (FALSE)
+END_PROTOCOL_ENTRY_FLUSH
+
 #undef BEGIN_PROTOCOL_ENTRY0
 #undef BEGIN_PROTOCOL_ENTRY1
 #undef BEGIN_PROTOCOL_ENTRY2
index ffc47f248de05a2c17a3f93648118bed4e2079ea..0e77588044ccb5e57630f1bcd699bb740ac10c9c 100644 (file)
@@ -106,6 +106,8 @@ binary_protocol_init (const char *filename, long long limit)
        file_size_limit = limit;
 
        binary_protocol_open_file ();
+
+       binary_protocol_header (PROTOCOL_HEADER_CHECK, PROTOCOL_HEADER_VERSION, SIZEOF_VOID_P, G_BYTE_ORDER == G_LITTLE_ENDIAN);
 #else
        g_error ("sgen binary protocol: not supported");
 #endif
index 5ec3680fc5a58018a358eaa583afdf9613753ddf..1c10d29d5c0e367f07e8d26a0163177da59c1b41 100644 (file)
 
 #include "sgen-gc.h"
 
+#define PROTOCOL_HEADER_CHECK 0xde7ec7ab1ec0de
+#define PROTOCOL_HEADER_VERSION 1
+
 /* Special indices returned by MATCH_INDEX. */
 #define BINARY_PROTOCOL_NO_MATCH (-1)
 #define BINARY_PROTOCOL_MATCH (-2)
 
+/* We pack all protocol structs by default unless specified otherwise */
+#ifndef PROTOCOL_STRUCT_ATTR
+#ifdef __GNUC__
+#define PROTOCOL_STRUCT_ATTR __attribute__ ((packed))
+#else
+#define PROTOCOL_STRUCT_ATTR
+#endif
+#endif
+
 #define PROTOCOL_ID(method) method ## _id
 #define PROTOCOL_STRUCT(method) method ## _struct
 #define CLIENT_PROTOCOL_NAME(method) sgen_client_ ## method
 
+#ifndef TYPE_INT
 #define TYPE_INT int
+#endif
+#ifndef TYPE_LONGLONG
 #define TYPE_LONGLONG long long
+#endif
+#ifndef TYPE_SIZE
 #define TYPE_SIZE size_t
+#endif
+#ifndef TYPE_POINTER
 #define TYPE_POINTER gpointer
+#endif
+#ifndef TYPE_BOOL
 #define TYPE_BOOL gboolean
+#endif
 
 enum {
 #define BEGIN_PROTOCOL_ENTRY0(method) PROTOCOL_ID(method),
@@ -60,29 +82,29 @@ enum {
 
 #define BEGIN_PROTOCOL_ENTRY0(method)
 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
                t4 f4; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
@@ -90,7 +112,7 @@ enum {
                t5 f5; \
        } PROTOCOL_STRUCT(method);
 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
-       typedef struct { \
+       typedef struct PROTOCOL_STRUCT_ATTR { \
                t1 f1; \
                t2 f2; \
                t3 f3; \
index f5d2a72139742369c24805e39e3eb138bfc5e811..e80e90020170ca10e5e40aa65c008b9c9bd94bd8 100644 (file)
@@ -3,3 +3,4 @@ Makefile
 Makefile.in
 /sgen-grep-binprot
 /*.o
+/*.a
index 582cbae3189dbcf4356cbd2f9d737661801e4cdf..ac155b0cedfb5eb43720b5bc17a86d3250d12f46 100644 (file)
@@ -2,8 +2,17 @@ bin_PROGRAMS = sgen-grep-binprot
 
 AM_CPPFLAGS =  $(GLIB_CFLAGS) -I$(top_srcdir)
 
+noinst_LIBRARIES = libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a
+libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprot_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
+libsgen_grep_binprot32p_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprot32p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=4 -DBINPROT_HAS_HEADER
+libsgen_grep_binprot64p_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprot64p_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_SIZEOF_VOID_P=8 -DBINPROT_HAS_HEADER
+
 sgen_grep_binprot_SOURCES = \
-       sgen-grep-binprot.c
+       sgen-grep-binprot-main.c        \
+       sgen-entry-stream.c
 
 sgen_grep_binprot_LDADD = \
-       $(GLIB_LIBS) $(LIBICONV)
+       $(GLIB_LIBS) $(LIBICONV) libsgen-grep-binprot.a libsgen-grep-binprot32p.a libsgen-grep-binprot64p.a
diff --git a/tools/sgen/sgen-entry-stream.c b/tools/sgen/sgen-entry-stream.c
new file mode 100644 (file)
index 0000000..479f0c2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * sgen-entry-stream.c: EntryStream implementation
+ *
+ * Copyright (C) 2016 Xamarin Inc
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <glib.h>
+#include "sgen-entry-stream.h"
+
+#define BUFFER_SIZE (1 << 20)
+
+void
+init_stream (EntryStream *stream, int file)
+{
+       stream->file = file;
+       stream->buffer = g_malloc0 (BUFFER_SIZE);
+       stream->end = stream->buffer + BUFFER_SIZE;
+       stream->pos = stream->end;
+}
+
+void
+reset_stream (EntryStream *stream)
+{
+       stream->end = stream->buffer + BUFFER_SIZE;
+       stream->pos = stream->end;
+       lseek (stream->file, 0, SEEK_SET);
+}
+
+void
+close_stream (EntryStream *stream)
+{
+       g_free (stream->buffer);
+}
+
+gboolean
+refill_stream (EntryStream *in, size_t size)
+{
+       size_t remainder = in->end - in->pos;
+       ssize_t refilled;
+       g_assert (size > 0);
+       g_assert (in->pos >= in->buffer);
+       if (in->pos + size <= in->end)
+               return TRUE;
+       memmove (in->buffer, in->pos, remainder);
+       in->pos = in->buffer;
+       refilled = read (in->file, in->buffer + remainder, BUFFER_SIZE - remainder);
+       if (refilled < 0)
+               return FALSE;
+       g_assert (refilled + remainder <= BUFFER_SIZE);
+       in->end = in->buffer + refilled + remainder;
+       return in->end - in->buffer >= size;
+}
+
+ssize_t
+read_stream (EntryStream *stream, void *out, size_t size)
+{
+       if (refill_stream (stream, size)) {
+               memcpy (out, stream->pos, size);
+               stream->pos += size;
+               return size;
+       }
+       return 0;
+}
diff --git a/tools/sgen/sgen-entry-stream.h b/tools/sgen/sgen-entry-stream.h
new file mode 100644 (file)
index 0000000..93dd2bf
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * sgen-entry-stream.h: EntryStream definitions
+ *
+ * Copyright (C) 2016 Xamarin Inc
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+typedef struct {
+       int file;
+       char *buffer;
+       const char *end;
+       const char *pos;
+} EntryStream;
+
+void init_stream (EntryStream *stream, int file);
+void reset_stream (EntryStream *stream);
+void close_stream (EntryStream *stream);
+gboolean refill_stream (EntryStream *in, size_t size);
+ssize_t read_stream (EntryStream *stream, void *out, size_t size);
diff --git a/tools/sgen/sgen-grep-binprot-main.c b/tools/sgen/sgen-grep-binprot-main.c
new file mode 100644 (file)
index 0000000..bcfbb54
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * sgen-grep-binprot-main.c: Binary protocol entries reader 
+ *
+ * Copyright (C) 2016 Xamarin Inc
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <glib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "sgen-entry-stream.h"
+#include "sgen-grep-binprot.h"
+
+/* FIXME Add grepers for specific endianness */
+GrepEntriesFunction grepers [] = {
+       sgen_binary_protocol_grep_entries32p, /* We have header, structures are packed, 32 bit word */
+       sgen_binary_protocol_grep_entries64p, /* We have header, structures are packed, 64 bit word */
+       sgen_binary_protocol_grep_entries /* No header, uses default word size and structure layout */
+};
+
+int
+main (int argc, char *argv[])
+{
+       int num_args = argc - 1;
+       int num_nums = 0;
+       int num_vtables = 0;
+       int i;
+       long nums [num_args];
+       long vtables [num_args];
+       gboolean dump_all = FALSE;
+       gboolean color_output = FALSE;
+       gboolean pause_times = FALSE;
+       const char *input_path = NULL;
+       int input_file;
+       EntryStream stream;
+       unsigned long long first_entry_to_consider = 0;
+
+       for (i = 0; i < num_args; ++i) {
+               char *arg = argv [i + 1];
+               char *next_arg = argv [i + 2];
+               if (!strcmp (arg, "--all")) {
+                       dump_all = TRUE;
+               } else if (!strcmp (arg, "--pause-times")) {
+                       pause_times = TRUE;
+               } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
+                       vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
+                       ++i;
+               } else if (!strcmp (arg, "-s") || !strcmp (arg, "--start-at")) {
+                       first_entry_to_consider = strtoull (next_arg, NULL, 10);
+                       ++i;
+               } else if (!strcmp (arg, "-c") || !strcmp (arg, "--color")) {
+                       color_output = TRUE;
+               } else if (!strcmp (arg, "-i") || !strcmp (arg, "--input")) {
+                       input_path = next_arg;
+                       ++i;
+               } else if (!strcmp (arg, "--help")) {
+                       printf (
+                               "\n"
+                               "Usage:\n"
+                               "\n"
+                               "\tsgen-grep-binprot [options] [pointer...]\n"
+                               "\n"
+                               "Examples:\n"
+                               "\n"
+                               "\tsgen-grep-binprot --all </tmp/binprot\n"
+                               "\tsgen-grep-binprot --input /tmp/binprot --color 0xdeadbeef\n"
+                               "\n"
+                               "Options:\n"
+                               "\n"
+                               "\t--all                    Print all entries.\n"
+                               "\t--color, -c              Highlight matches in color.\n"
+                               "\t--help                   You're looking at it.\n"
+                               "\t--input FILE, -i FILE    Read input from FILE instead of standard input.\n"
+                               "\t--pause-times            Print GC pause times.\n"
+                               "\t--start-at N, -s N       Begin filtering at the Nth entry.\n"
+                               "\t--vtable PTR, -v PTR     Search for vtable pointer PTR.\n"
+                               "\n");
+                       return 0;
+               } else {
+                       nums [num_nums++] = strtoul (arg, NULL, 16);
+               }
+       }
+
+       if (dump_all)
+               assert (!pause_times);
+       if (pause_times)
+               assert (!dump_all);
+
+       input_file = input_path ? open (input_path, O_RDONLY) : STDIN_FILENO;
+       init_stream (&stream, input_file);
+       for (i = 0; i < sizeof (grepers) / sizeof (GrepEntriesFunction); i++) {
+               if (grepers [i] (&stream, num_nums, nums, num_vtables, vtables, dump_all,
+                               pause_times, color_output, first_entry_to_consider)) {
+                       /* Success */
+                       break;
+               }
+               reset_stream (&stream);
+       }
+       close_stream (&stream);
+       if (input_path)
+               close (input_file);
+
+       return 0;
+}
index 49aa9506009e61411990764a262ad454eeeca8cf..4ca309f38eb6d3d8ef67ea96e4a2290bb0395b24 100644 (file)
@@ -1,13 +1,52 @@
+/*
+ * sgen-grep-binprot.c: Platform specific binary protocol entries reader
+ *
+ * Copyright (C) 2016 Xamarin Inc
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <glib.h>
 #include <unistd.h>
 #include <fcntl.h>
-
-#define SGEN_BINARY_PROTOCOL
-#define MONO_INTERNAL
-
+#include <stdint.h>
+#include <inttypes.h>
+#include <config.h>
+#include "sgen-entry-stream.h"
+#include "sgen-grep-binprot.h"
+
+#ifdef BINPROT_HAS_HEADER
+#define PACKED_SUFFIX  p
+#else
+#define PROTOCOL_STRUCT_ATTR
+#define PACKED_SUFFIX
+#endif
+
+#ifndef BINPROT_SIZEOF_VOID_P
+#define BINPROT_SIZEOF_VOID_P SIZEOF_VOID_P
+#define ARCH_SUFFIX
+#endif
+
+#if BINPROT_SIZEOF_VOID_P == 4
+typedef int32_t mword;
+#define MWORD_FORMAT_SPEC_D PRId32
+#define MWORD_FORMAT_SPEC_P PRIx32
+#ifndef ARCH_SUFFIX
+#define ARCH_SUFFIX    32
+#endif
+#else
+typedef int64_t mword;
+#define MWORD_FORMAT_SPEC_D PRId64
+#define MWORD_FORMAT_SPEC_P PRIx64
+#ifndef ARCH_SUFFIX
+#define ARCH_SUFFIX    64
+#endif
+#endif
+#define TYPE_SIZE      mword
+#define TYPE_POINTER   mword
 #include <mono/sgen/sgen-protocol.h>
 
 #define SGEN_PROTOCOL_EOF      255
 #define WORKER(t)      ((t) & 0x80)
 
 #define MAX_ENTRY_SIZE (1 << 10)
-#define BUFFER_SIZE (1 << 20)
-
-typedef struct {
-       int file;
-       char *buffer;
-       const char *end;
-       const char *pos;
-} EntryStream;
-
-static void
-init_stream (EntryStream *stream, int file)
-{
-       stream->file = file;
-       stream->buffer = g_malloc0 (BUFFER_SIZE);
-       stream->end = stream->buffer + BUFFER_SIZE;
-       stream->pos = stream->end;
-}
-
-static void
-close_stream (EntryStream *stream)
-{
-       g_free (stream->buffer);
-}
-
-static gboolean
-refill_stream (EntryStream *in, size_t size)
-{
-       size_t remainder = in->end - in->pos;
-       ssize_t refilled;
-       g_assert (size > 0);
-       g_assert (in->pos >= in->buffer);
-       if (in->pos + size <= in->end)
-               return TRUE;
-       memmove (in->buffer, in->pos, remainder);
-       in->pos = in->buffer;
-       refilled = read (in->file, in->buffer + remainder, BUFFER_SIZE - remainder);
-       if (refilled < 0)
-               return FALSE;
-       g_assert (refilled + remainder <= BUFFER_SIZE);
-       in->end = in->buffer + refilled + remainder;
-       return in->end - in->buffer >= size;
-}
-
-static ssize_t
-read_stream (EntryStream *stream, void *out, size_t size)
-{
-       if (refill_stream (stream, size)) {
-               memcpy (out, stream->pos, size);
-               stream->pos += size;
-               return size;
-       }
-       return 0;
-}
 
 static int
 read_entry (EntryStream *stream, void *data)
@@ -224,10 +210,10 @@ print_entry_content (int entries_size, PrintEntry *entries, gboolean color_outpu
                        printf ("%lld", *(long long*) entries [i].data);
                        break;
                case TYPE_SIZE:
-                       printf ("%lu", *(size_t*) entries [i].data);
+                       printf ("%"MWORD_FORMAT_SPEC_D, *(mword*) entries [i].data);
                        break;
                case TYPE_POINTER:
-                       printf ("%p", *(gpointer*) entries [i].data);
+                       printf ("0x%"MWORD_FORMAT_SPEC_P, *(mword*) entries [i].data);
                        break;
                case TYPE_BOOL:
                        printf ("%s", *(gboolean*) entries [i].data ? "true" : "false");
@@ -431,13 +417,13 @@ print_entry (int type, void *data, int num_nums, int *match_indices, gboolean co
 
 #define TYPE_INT int
 #define TYPE_LONGLONG long long
-#define TYPE_SIZE size_t
-#define TYPE_POINTER gpointer
+#define TYPE_SIZE mword
+#define TYPE_POINTER mword
 
 static gboolean
-matches_interval (gpointer ptr, gpointer start, int size)
+matches_interval (mword ptr, mword start, int size)
 {
-       return ptr >= start && (char*)ptr < (char*)start + size;
+       return ptr >= start && ptr < start + size;
 }
 
 /* Returns the index of the field where a match was found,
@@ -445,7 +431,7 @@ matches_interval (gpointer ptr, gpointer start, int size)
  * BINARY_PROTOCOL_MATCH for a match with no index.
  */
 static int
-match_index (gpointer ptr, int type, void *data)
+match_index (mword ptr, int type, void *data)
 {
        switch (TYPE (type)) {
 
@@ -508,7 +494,7 @@ match_index (gpointer ptr, int type, void *data)
 }
 
 static gboolean
-is_vtable_match (gpointer ptr, int type, void *data)
+is_vtable_match (mword ptr, int type, void *data)
 {
        switch (TYPE (type)) {
 
@@ -575,85 +561,53 @@ is_vtable_match (gpointer ptr, int type, void *data)
 #undef TYPE_SIZE
 #undef TYPE_POINTER
 
-int
-main (int argc, char *argv[])
+static gboolean
+sgen_binary_protocol_read_header (EntryStream *stream)
+{
+#ifdef BINPROT_HAS_HEADER
+       char data [MAX_ENTRY_SIZE];
+       int type = read_entry (stream, data);
+       if (type == SGEN_PROTOCOL_EOF)
+               return FALSE;
+       if (type == PROTOCOL_ID (binary_protocol_header)) {
+               PROTOCOL_STRUCT (binary_protocol_header) * str = (PROTOCOL_STRUCT (binary_protocol_header) *) data;
+               if (str->check == PROTOCOL_HEADER_CHECK && str->ptr_size == BINPROT_SIZEOF_VOID_P)
+                       return TRUE;
+       }
+       return FALSE;
+#else
+       /*
+        * This implementation doesn't account for the presence of a header,
+        * reading all the entries with the default configuration of the host
+        * machine. It has to be used only after all other implementations
+        * fail to identify a header, for backward compatibility.
+        */
+       return TRUE;
+#endif
+}
+
+#define CONC(A, B) CONC_(A, B)
+#define CONC_(A, B) A##B
+#define GREP_ENTRIES_FUNCTION_NAME CONC(sgen_binary_protocol_grep_entries, CONC(ARCH_SUFFIX,PACKED_SUFFIX))
+
+gboolean
+GREP_ENTRIES_FUNCTION_NAME (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+                       gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider)
 {
        int type;
        void *data = g_malloc0 (MAX_ENTRY_SIZE);
-       int num_args = argc - 1;
-       int num_nums = 0;
-       int num_vtables = 0;
        int i;
-       long nums [num_args];
-       long vtables [num_args];
-       gboolean dump_all = FALSE;
-       gboolean pause_times = FALSE;
        gboolean pause_times_stopped = FALSE;
        gboolean pause_times_concurrent = FALSE;
        gboolean pause_times_finish = FALSE;
-       gboolean color_output = FALSE;
        long long pause_times_ts = 0;
-       const char *input_path = NULL;
-       int input_file;
-       EntryStream stream;
        unsigned long long entry_index;
-       unsigned long long first_entry_to_consider = 0;
-
-       for (i = 0; i < num_args; ++i) {
-               char *arg = argv [i + 1];
-               char *next_arg = argv [i + 2];
-               if (!strcmp (arg, "--all")) {
-                       dump_all = TRUE;
-               } else if (!strcmp (arg, "--pause-times")) {
-                       pause_times = TRUE;
-               } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
-                       vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
-                       ++i;
-               } else if (!strcmp (arg, "-s") || !strcmp (arg, "--start-at")) {
-                       first_entry_to_consider = strtoull (next_arg, NULL, 10);
-                       ++i;
-               } else if (!strcmp (arg, "-c") || !strcmp (arg, "--color")) {
-                       color_output = TRUE;
-               } else if (!strcmp (arg, "-i") || !strcmp (arg, "--input")) {
-                       input_path = next_arg;
-                       ++i;
-               } else if (!strcmp (arg, "--help")) {
-                       printf (
-                               "\n"
-                               "Usage:\n"
-                               "\n"
-                               "\tsgen-grep-binprot [options] [pointer...]\n"
-                               "\n"
-                               "Examples:\n"
-                               "\n"
-                               "\tsgen-grep-binprot --all </tmp/binprot\n"
-                               "\tsgen-grep-binprot --input /tmp/binprot --color 0xdeadbeef\n"
-                               "\n"
-                               "Options:\n"
-                               "\n"
-                               "\t--all                    Print all entries.\n"
-                               "\t--color, -c              Highlight matches in color.\n"
-                               "\t--help                   You're looking at it.\n"
-                               "\t--input FILE, -i FILE    Read input from FILE instead of standard input.\n"
-                               "\t--pause-times            Print GC pause times.\n"
-                               "\t--start-at N, -s N       Begin filtering at the Nth entry.\n"
-                               "\t--vtable PTR, -v PTR     Search for vtable pointer PTR.\n"
-                               "\n");
-                       return 0;
-               } else {
-                       nums [num_nums++] = strtoul (arg, NULL, 16);
-               }
-       }
 
-       if (dump_all)
-               assert (!pause_times);
-       if (pause_times)
-               assert (!dump_all);
+       if (!sgen_binary_protocol_read_header (stream))
+               return FALSE;
 
-       input_file = input_path ? open (input_path, O_RDONLY) : STDIN_FILENO;
-       init_stream (&stream, input_file);
        entry_index = 0;
-       while ((type = read_entry (&stream, data)) != SGEN_PROTOCOL_EOF) {
+       while ((type = read_entry (stream, data)) != SGEN_PROTOCOL_EOF) {
                if (entry_index < first_entry_to_consider)
                        goto next_entry;
                if (pause_times) {
@@ -689,15 +643,15 @@ main (int argc, char *argv[])
                } else {
                        int match_indices [num_nums + 1];
                        gboolean match = is_always_match (type);
-                       match_indices [num_nums] = num_nums == 0 ? match_index (NULL, type, data) : BINARY_PROTOCOL_NO_MATCH;
+                       match_indices [num_nums] = num_nums == 0 ? match_index (0, type, data) : BINARY_PROTOCOL_NO_MATCH;
                        match = match_indices [num_nums] != BINARY_PROTOCOL_NO_MATCH;
                        for (i = 0; i < num_nums; ++i) {
-                               match_indices [i] = match_index ((gpointer) nums [i], type, data);
+                               match_indices [i] = match_index ((mword) nums [i], type, data);
                                match = match || match_indices [i] != BINARY_PROTOCOL_NO_MATCH;
                        }
                        if (!match) {
                                for (i = 0; i < num_vtables; ++i) {
-                                       if (is_vtable_match ((gpointer) vtables [i], type, data)) {
+                                       if (is_vtable_match ((mword) vtables [i], type, data)) {
                                                match = TRUE;
                                                break;
                                        }
@@ -713,10 +667,6 @@ main (int argc, char *argv[])
        next_entry:
                ++entry_index;
        }
-       close_stream (&stream);
-       if (input_path)
-               close (input_file);
        g_free (data);
-
-       return 0;
+       return TRUE;
 }
diff --git a/tools/sgen/sgen-grep-binprot.h b/tools/sgen/sgen-grep-binprot.h
new file mode 100644 (file)
index 0000000..9025c9a
--- /dev/null
@@ -0,0 +1,12 @@
+typedef gboolean (*GrepEntriesFunction) (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+               gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);
+
+gboolean
+sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+                        gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);
+gboolean
+sgen_binary_protocol_grep_entries32p (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+                        gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);
+gboolean
+sgen_binary_protocol_grep_entries64p (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+                        gboolean dump_all, gboolean pause_times, gboolean color_output, unsigned long long first_entry_to_consider);