OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / sdk / emulator / qtools / bb2sym.cpp
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include <assert.h>
6 #include "trace_reader.h"
7 #include "parse_options.h"
8
9 typedef TraceReader<> TraceReaderType;
10
11 #include "parse_options-inl.h"
12
13 struct MyStaticRec {
14     StaticRec   bb;
15     symbol_type *sym;
16     MyStaticRec *inner;    // pointer to an inner basic block
17     int         is_thumb;
18 };
19
20 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
21
22 void Usage(const char *program)
23 {
24     fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
25     OptionsUsage();
26 }
27
28 // This function is called from quicksort to compare addresses of basic
29 // blocks.
30 int cmp_inc_addr(const void *a, const void *b) {
31     MyStaticRec *bb1, *bb2;
32
33     bb1 = *(MyStaticRec**)a;
34     bb2 = *(MyStaticRec**)b;
35     if (bb1->bb.bb_addr < bb2->bb.bb_addr)
36         return -1;
37     if (bb1->bb.bb_addr > bb2->bb.bb_addr)
38         return 1;
39     return bb1->bb.bb_num - bb2->bb.bb_num;
40 }
41
42 int main(int argc, char **argv) {
43     uint32_t insns[kMaxInsnPerBB];
44
45     // Parse the options
46     ParseOptions(argc, argv);
47     if (argc - optind != 2) {
48         Usage(argv[0]);
49         exit(1);
50     }
51
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);
57     trace->SetRoot(root);
58
59     TraceHeader *header = trace->GetHeader();
60     uint32_t num_static_bb = header->num_static_bb;
61
62     // Allocate space for all of the static blocks
63     MyStaticRec *blocks = new MyStaticRec[num_static_bb];
64
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);
73     }
74
75     MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
76
77     while (1) {
78         symbol_type *sym;
79         BBEvent event;
80         BBEvent ignored;
81
82         if (GetNextValidEvent(trace, &event, &ignored, &sym))
83             break;
84
85         uint64_t bb_num = event.bb_num;
86         blocks[bb_num].sym = sym;
87     }
88         
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)
93             continue;
94
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);
99     }
100     return 0;
101 }
102
103 // Find the basic blocks that are subsets of other basic blocks.
104 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
105 {
106     int ii;
107     uint32_t addr_end, addr_diff;
108
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];
113     }
114
115     // Sort the basic blocks into increasing address order
116     qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
117
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) {
121         int num_bytes;
122         if (sorted[ii]->is_thumb)
123             num_bytes = sorted[ii]->bb.num_insns << 1;
124         else
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;
130             uint32_t num_insns;
131             if (sorted[ii]->is_thumb)
132                 num_insns = addr_diff >> 1;
133             else
134                 num_insns = addr_diff >> 2;
135             sorted[ii]->bb.num_insns = num_insns;
136         }
137     }
138
139     return sorted;
140 }