blob: 1c0b6ae8f153b1728d11c3cd5bc70782622a6ce9 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Simple reader for ktrace files.
// TODO: IWBN if there was a libktrace to replace this.
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <lib/zircon-internal/ktrace.h>
#include "ktrace_reader.h"
namespace debugger_utils {
int KtraceReadFile(int fd, KtraceRecordReader* reader, void* arg) {
KtraceRecord rec;
unsigned offset = 0;
while (read(fd, rec.raw, sizeof(ktrace_header_t)) == sizeof(ktrace_header_t)) {
uint32_t tag = rec.hdr.tag;
uint32_t len = KTRACE_LEN(tag);
if (tag == 0) {
fprintf(stderr, "eof: zero tag at offset %08x\n", offset);
break;
}
if (len < sizeof(ktrace_header_t)) {
fprintf(stderr, "eof: short packet at offset %08x\n", offset);
break;
}
offset += (sizeof(ktrace_header_t) + len);
len -= sizeof(ktrace_header_t);
if (read(fd, rec.raw + sizeof(ktrace_header_t), len) != len) {
fprintf(stderr, "eof: incomplete packet at offset %08x\n", offset);
break;
}
int rc = reader(&rec, arg);
if (rc)
return rc;
}
return 0;
}
const char* KtraceRecName(uint32_t tag) {
// TODO: Remove magic number
switch (tag & 0xffffff00u) {
#define KTRACE_DEF(num, type, name, group) \
case KTRACE_TAG(num, KTRACE_GRP_##group, 0): \
return #name;
#include <lib/zircon-internal/ktrace-def.h>
default:
return "UNKNOWN";
}
}
} // namespace debugger_utils
#ifdef TEST
struct TestData {
size_t count;
};
static void Dump_16B(const ktrace_rec_32b_t* rec) {
printf(" tid 0x%x, ts 0x%" PRIx64, rec->tid, rec->ts);
printf(" a 0x%x, b 0x%x", rec->a, rec->b);
}
static void Dump_32B(const ktrace_rec_32b_t* rec) {
printf(" tid 0x%x, ts 0x%" PRIx64, rec->tid, rec->ts);
printf(" a 0x%x, b 0x%x, c 0x%x, d 0x%x", rec->a, rec->b, rec->c, rec->d);
}
static void Dump_NAME(const ktrace_rec_name_t* rec) {
printf(" id 0x%x, arg 0x%x,", rec->id, rec->arg);
printf(" name %s", rec->name);
}
static void DumpRecord(const debugger_utils::KtraceRecord* rec) {
printf("%s(%x):", debugger_utils::KtraceRecName(rec->hdr.tag), rec->hdr.tag);
// TODO: Remove magic number
switch (rec->hdr.tag & 0xffffff00u) {
#define KTRACE_DEF(num, type, name, group) \
case KTRACE_TAG(num, KTRACE_GRP_##group, 0): \
Dump_##type(&rec->r_##type); \
break;
#include <lib/zircon-internal/ktrace-def.h>
default:
printf(" ???");
break;
}
printf("\n");
}
static int ProcessTest(debugger_utils::KtraceRecord* rec, void* arg) {
auto data = reinterpret_cast<TestData*>(arg);
++data->count;
DumpRecord(rec);
return 0;
}
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: ktrace-reader <file>\n");
exit(1);
}
const char* file = argv[1];
int fd = open(file, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error opening: %s: %s\n", file, strerror(errno));
exit(1);
}
TestData data = {};
int rc = debugger_utils::KtraceReadFile(fd, ProcessTest, &data);
printf("process_test returned %d\n", rc);
printf("%zu records\n", data.count);
return 0;
}
#endif