155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdio.h>
255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <unistd.h>
355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdlib.h>
455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <inttypes.h>
555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h"
655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options.h"
755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef TraceReader<> TraceReaderType;
955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options-inl.h"
1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
12921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrastruct frame {
13921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    uint64_t    time;
14921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    uint32_t    addr;
15921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    const char  *name;
16c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra    bool        isNative;
17921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
18c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra    frame(uint64_t time, uint32_t addr, const char *name, bool isNative) {
19921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        this->time = time;
20921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        this->addr = addr;
21921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        this->name = name;
22c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra        this->isNative = isNative;
23921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    }
24921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra};
25921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
26921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstraclass Stack {
27921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    static const int kMaxFrames = 1000;
28921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    int top;
29921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    frame *frames[kMaxFrames];
30921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
31921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrapublic:
32921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    Stack() {
33921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        top = 0;
34921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    }
35921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
36921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    void        push(frame *pframe);
37921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    frame*      pop();
38921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    void        dump();
39921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra};
40921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
41921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstravoid Stack::push(frame *pframe) {
42921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    if (top == kMaxFrames) {
43921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        fprintf(stderr, "Error: stack overflow\n");
44921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        exit(1);
45921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    }
46921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    frames[top] = pframe;
47921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    top += 1;
48921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra}
49921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
50921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstraframe *Stack::pop() {
51921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    if (top <= 0)
52921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        return NULL;
53921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    top -= 1;
54921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    return frames[top];
55921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra}
56921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
57921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstravoid Stack::dump() {
58921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    frame *pframe;
59921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
60921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    for (int ii = 0; ii < top; ii++) {
61921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        pframe = frames[ii];
62c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra        const char *native = pframe->isNative ? "n" : " ";
63c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra        printf(" %s %d: %llu 0x%x %s\n",
64c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra               native, ii, pframe->time, pframe->addr,
65921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra               pframe->name == NULL ? "" : pframe->name);
66921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra    }
67921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra}
68921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
69921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstrastatic const int kMaxThreads = (32 * 1024);
70921168fdb0cee8ae041df6308b49765b2a98ed74Jack VeenstraStack *stacks[kMaxThreads];
71921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectvoid Usage(const char *program)
7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{
7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    fprintf(stderr, "Usage: %s [options] trace_name elf_file\n",
7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            program);
7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    OptionsUsage();
7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
7955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) {
8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    ParseOptions(argc, argv);
8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (argc - optind != 2) {
8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        Usage(argv[0]);
8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        exit(1);
8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    char *qemu_trace_file = argv[optind++];
8755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    char *elf_file = argv[optind++];
8855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    TraceReaderType *trace = new TraceReaderType;
8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    trace->Open(qemu_trace_file);
9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    trace->ReadKernelSymbols(elf_file);
9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    trace->SetRoot(root);
9255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    while (1) {
9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        MethodRec method_record;
9555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        symbol_type *sym;
9655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        TraceReaderType::ProcessState *proc;
97921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        frame *pframe;
9855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
9955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        if (trace->ReadMethodSymbol(&method_record, &sym, &proc))
10055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            break;
101921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
102921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        if (!IsValidPid(proc->pid))
103921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            continue;
104921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
10555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        if (sym != NULL) {
10655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            printf("%lld p %d 0x%x %d %s\n",
10755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                   method_record.time, proc->pid, method_record.addr,
10855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                   method_record.flags, sym->name);
10955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        } else {
11055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            printf("%lld p %d 0x%x %d\n",
11155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                   method_record.time, proc->pid, method_record.addr,
11255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                   method_record.flags);
11355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        }
114921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
115921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        // Get the stack for the current thread
116921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        Stack *pStack = stacks[proc->pid];
117921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
118921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        // If the stack does not exist, then allocate a new one.
119921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        if (pStack == NULL) {
120921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            pStack = new Stack();
121921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            stacks[proc->pid] = pStack;
122921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        }
123921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra
124c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra        int flags = method_record.flags;
125c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra        if (flags == kMethodEnter || flags == kNativeEnter) {
126921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            pframe = new frame(method_record.time, method_record.addr,
127c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra                               sym == NULL ? NULL: sym->name,
128c627baa5fe13370895cb36cbff1300bad8bc96deJack Veenstra                               method_record.flags == kNativeEnter);
129921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            pStack->push(pframe);
130921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        } else {
131921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            pframe = pStack->pop();
132921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra            delete pframe;
133921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        }
134921168fdb0cee8ae041df6308b49765b2a98ed74Jack Veenstra        pStack->dump();
13555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
13655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    return 0;
13755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
138