#include "sgen-entry-stream.h"
#include "sgen-grep-binprot.h"
-#if SIZEOF_VOID_P == 4
+static int file_version = 0;
+
+#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
#define MAX_ENTRY_SIZE (1 << 10)
static int
-read_entry (EntryStream *stream, void *data)
+read_entry (EntryStream *stream, void *data, unsigned char *windex)
{
unsigned char type;
ssize_t size;
if (read_stream (stream, &type, 1) <= 0)
return SGEN_PROTOCOL_EOF;
+
+ if (windex) {
+ if (file_version >= 2) {
+ if (read_stream (stream, windex, 1) <= 0)
+ return SGEN_PROTOCOL_EOF;
+ } else {
+ *windex = !!(WORKER (type));
+ }
+ }
+
switch (TYPE (type)) {
#define BEGIN_PROTOCOL_ENTRY0(method) \
}
}
-#define WORKER_PREFIX(t) (WORKER ((t)) ? "w" : " ")
-
enum { NO_COLOR = -1 };
typedef struct {
}
static void
-print_entry (int type, void *data, int num_nums, int *match_indices, gboolean color_output)
+print_entry (int type, void *data, int num_nums, int *match_indices, gboolean color_output, unsigned char worker_index)
{
const char *always_prefix = is_always_match (type) ? " " : "";
- printf ("%s%s ", WORKER_PREFIX (type), always_prefix);
+ if (worker_index)
+ printf ("w%-2d%s ", worker_index, always_prefix);
+ else
+ printf (" %s ", always_prefix);
switch (TYPE (type)) {
#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, NULL);
+ 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) {
+ if (str->version > PROTOCOL_HEADER_VERSION) {
+ fprintf (stderr, "The file contains a newer version %d. We support up to %d. Please update.\n", str->version, PROTOCOL_HEADER_VERSION);
+ exit (1);
+ }
+ file_version = str->version;
+ 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;
+ unsigned char worker_index;
void *data = g_malloc0 (MAX_ENTRY_SIZE);
int i;
gboolean pause_times_stopped = FALSE;
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) {
+ while ((type = read_entry (stream, data, &worker_index)) != SGEN_PROTOCOL_EOF) {
if (entry_index < first_entry_to_consider)
goto next_entry;
if (pause_times) {
if (dump_all)
printf (match ? "* " : " ");
if (match || dump_all)
- print_entry (type, data, num_nums, match_indices, color_output);
+ print_entry (type, data, num_nums, match_indices, color_output, worker_index);
}
next_entry:
++entry_index;
}
g_free (data);
+ return TRUE;
}