6 #include "trace_reader.h"
7 #include "parse_options.h"
9 typedef TraceReader<> TraceReaderType;
11 #include "parse_options-inl.h"
16 MyStaticRec *inner; // pointer to an inner basic block
20 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
22 void Usage(const char *program)
24 fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
28 // This function is called from quicksort to compare addresses of basic
30 int cmp_inc_addr(const void *a, const void *b) {
31 MyStaticRec *bb1, *bb2;
33 bb1 = *(MyStaticRec**)a;
34 bb2 = *(MyStaticRec**)b;
35 if (bb1->bb.bb_addr < bb2->bb.bb_addr)
37 if (bb1->bb.bb_addr > bb2->bb.bb_addr)
39 return bb1->bb.bb_num - bb2->bb.bb_num;
42 int main(int argc, char **argv) {
43 uint32_t insns[kMaxInsnPerBB];
46 ParseOptions(argc, argv);
47 if (argc - optind != 2) {
52 char *trace_filename = argv[optind++];
53 char *elf_file = argv[optind++];
54 TraceReader<> *trace = new TraceReader<>;
55 trace->Open(trace_filename);
56 trace->ReadKernelSymbols(elf_file);
59 TraceHeader *header = trace->GetHeader();
60 uint32_t num_static_bb = header->num_static_bb;
62 // Allocate space for all of the static blocks
63 MyStaticRec *blocks = new MyStaticRec[num_static_bb];
65 // Read in all the static blocks
66 for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
67 trace->ReadStatic(&blocks[ii].bb);
68 blocks[ii].is_thumb = blocks[ii].bb.bb_addr & 1;
69 blocks[ii].bb.bb_addr &= ~1;
70 blocks[ii].sym = NULL;
71 blocks[ii].inner = NULL;
72 trace->ReadStaticInsns(blocks[ii].bb.num_insns, insns);
75 MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
82 if (GetNextValidEvent(trace, &event, &ignored, &sym))
85 uint64_t bb_num = event.bb_num;
86 blocks[bb_num].sym = sym;
89 printf("# bb num_insns bb_addr file symbol\n");
90 for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
91 if (sorted[ii]->bb.bb_addr == 0 || sorted[ii]->bb.num_insns == 0
92 || sorted[ii]->sym == NULL)
95 printf("%8lld %3d 0x%08x %s %s\n",
96 sorted[ii]->bb.bb_num, sorted[ii]->bb.num_insns,
97 sorted[ii]->bb.bb_addr, sorted[ii]->sym->region->path,
98 sorted[ii]->sym->name);
103 // Find the basic blocks that are subsets of other basic blocks.
104 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
107 uint32_t addr_end, addr_diff;
109 // Create a list of pointers to the basic blocks that we can sort.
110 MyStaticRec **sorted = new MyStaticRec*[num_blocks];
111 for (ii = 0; ii < num_blocks; ++ii) {
112 sorted[ii] = &blocks[ii];
115 // Sort the basic blocks into increasing address order
116 qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
118 // Create pointers to inner blocks and break up the enclosing block
119 // so that there is no overlap.
120 for (ii = 0; ii < num_blocks - 1; ++ii) {
122 if (sorted[ii]->is_thumb)
123 num_bytes = sorted[ii]->bb.num_insns << 1;
125 num_bytes = sorted[ii]->bb.num_insns << 2;
126 addr_end = sorted[ii]->bb.bb_addr + num_bytes;
127 if (addr_end > sorted[ii + 1]->bb.bb_addr) {
128 sorted[ii]->inner = sorted[ii + 1];
129 addr_diff = sorted[ii + 1]->bb.bb_addr - sorted[ii]->bb.bb_addr;
131 if (sorted[ii]->is_thumb)
132 num_insns = addr_diff >> 1;
134 num_insns = addr_diff >> 2;
135 sorted[ii]->bb.num_insns = num_insns;