We save space and support cross platform grep-ing across platforms with the same word size.
{
}
+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);
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
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
#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
#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; \
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; \
Makefile.in
/sgen-grep-binprot
/*.o
+/*.a
AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
+noinst_LIBRARIES = libsgen-grep-binprot.a libsgen-grep-binprotp.a
+libsgen_grep_binprot_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprot_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
+libsgen_grep_binprotp_a_SOURCES = sgen-grep-binprot.c
+libsgen_grep_binprotp_a_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) -DBINPROT_HAS_HEADER
+
sgen_grep_binprot_SOURCES = \
sgen-grep-binprot-main.c \
sgen-grep-binprot.c \
sgen-entry-stream.c
sgen_grep_binprot_LDADD = \
- $(GLIB_LIBS) $(LIBICONV)
+ $(GLIB_LIBS) $(LIBICONV) libsgen-grep-binprot.a libsgen-grep-binprotp.a
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)
{
} 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);
#include "sgen-entry-stream.h"
#include "sgen-grep-binprot.h"
+GrepEntriesFunction grepers [] = {
+ sgen_binary_protocol_grep_entriesp,
+ sgen_binary_protocol_grep_entries
+};
+
int
main (int argc, char *argv[])
{
input_file = input_path ? open (input_path, O_RDONLY) : STDIN_FILENO;
init_stream (&stream, input_file);
- sgen_binary_protocol_grep_entries (&stream, num_nums, nums, num_vtables, vtables,
- dump_all, pause_times, color_output, first_entry_to_consider);
+ 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);
#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
+
#if SIZEOF_VOID_P == 4
typedef int32_t mword;
#define MWORD_FORMAT_SPEC_D PRId32
#undef TYPE_SIZE
#undef TYPE_POINTER
-void
-sgen_binary_protocol_grep_entries (EntryStream *stream, int num_nums, long nums [], int num_vtables, long vtables [],
+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)
+ 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, 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;
long long pause_times_ts = 0;
unsigned long long entry_index;
+ if (!sgen_binary_protocol_read_header (stream))
+ return FALSE;
+
entry_index = 0;
while ((type = read_entry (stream, data)) != SGEN_PROTOCOL_EOF) {
if (entry_index < first_entry_to_consider)
++entry_index;
}
g_free (data);
+ return TRUE;
}
-void
+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_entriesp (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);