aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/qtools/bb2sym.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit1506a206c0a5e3b593c4c61a62b8805b64e98daf (patch)
treee20fe3eb0f693e87649fff1ce75e3f23330f69f8 /emulator/qtools/bb2sym.cpp
downloadsdk-1506a206c0a5e3b593c4c61a62b8805b64e98daf.zip
sdk-1506a206c0a5e3b593c4c61a62b8805b64e98daf.tar.gz
sdk-1506a206c0a5e3b593c4c61a62b8805b64e98daf.tar.bz2
Initial Contribution
Diffstat (limited to 'emulator/qtools/bb2sym.cpp')
-rw-r--r--emulator/qtools/bb2sym.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/emulator/qtools/bb2sym.cpp b/emulator/qtools/bb2sym.cpp
new file mode 100644
index 0000000..8a18b67
--- /dev/null
+++ b/emulator/qtools/bb2sym.cpp
@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <assert.h>
+#include "trace_reader.h"
+#include "parse_options.h"
+
+typedef TraceReader<> TraceReaderType;
+
+#include "parse_options-inl.h"
+
+struct MyStaticRec {
+ StaticRec bb;
+ symbol_type *sym;
+ MyStaticRec *inner; // pointer to an inner basic block
+ int is_thumb;
+};
+
+MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
+
+void Usage(const char *program)
+{
+ fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
+ OptionsUsage();
+}
+
+// This function is called from quicksort to compare addresses of basic
+// blocks.
+int cmp_inc_addr(const void *a, const void *b) {
+ MyStaticRec *bb1, *bb2;
+
+ bb1 = *(MyStaticRec**)a;
+ bb2 = *(MyStaticRec**)b;
+ if (bb1->bb.bb_addr < bb2->bb.bb_addr)
+ return -1;
+ if (bb1->bb.bb_addr > bb2->bb.bb_addr)
+ return 1;
+ return bb1->bb.bb_num - bb2->bb.bb_num;
+}
+
+int main(int argc, char **argv) {
+ uint32_t insns[kMaxInsnPerBB];
+
+ // Parse the options
+ ParseOptions(argc, argv);
+ if (argc - optind != 2) {
+ Usage(argv[0]);
+ exit(1);
+ }
+
+ char *trace_filename = argv[optind++];
+ char *elf_file = argv[optind++];
+ TraceReader<> *trace = new TraceReader<>;
+ trace->Open(trace_filename);
+ trace->ReadKernelSymbols(elf_file);
+ trace->SetRoot(root);
+
+ TraceHeader *header = trace->GetHeader();
+ uint32_t num_static_bb = header->num_static_bb;
+
+ // Allocate space for all of the static blocks
+ MyStaticRec *blocks = new MyStaticRec[num_static_bb];
+
+ // Read in all the static blocks
+ for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
+ trace->ReadStatic(&blocks[ii].bb);
+ blocks[ii].is_thumb = blocks[ii].bb.bb_addr & 1;
+ blocks[ii].bb.bb_addr &= ~1;
+ blocks[ii].sym = NULL;
+ blocks[ii].inner = NULL;
+ trace->ReadStaticInsns(blocks[ii].bb.num_insns, insns);
+ }
+
+ MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
+
+ while (1) {
+ symbol_type *sym;
+ BBEvent event;
+ BBEvent ignored;
+
+ if (GetNextValidEvent(trace, &event, &ignored, &sym))
+ break;
+
+ uint64_t bb_num = event.bb_num;
+ blocks[bb_num].sym = sym;
+ }
+
+ printf("# bb num_insns bb_addr file symbol\n");
+ for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
+ if (sorted[ii]->bb.bb_addr == 0 || sorted[ii]->bb.num_insns == 0
+ || sorted[ii]->sym == NULL)
+ continue;
+
+ printf("%8lld %3d 0x%08x %s %s\n",
+ sorted[ii]->bb.bb_num, sorted[ii]->bb.num_insns,
+ sorted[ii]->bb.bb_addr, sorted[ii]->sym->region->path,
+ sorted[ii]->sym->name);
+ }
+ return 0;
+}
+
+// Find the basic blocks that are subsets of other basic blocks.
+MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
+{
+ int ii;
+ uint32_t addr_end, addr_diff;
+
+ // Create a list of pointers to the basic blocks that we can sort.
+ MyStaticRec **sorted = new MyStaticRec*[num_blocks];
+ for (ii = 0; ii < num_blocks; ++ii) {
+ sorted[ii] = &blocks[ii];
+ }
+
+ // Sort the basic blocks into increasing address order
+ qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
+
+ // Create pointers to inner blocks and break up the enclosing block
+ // so that there is no overlap.
+ for (ii = 0; ii < num_blocks - 1; ++ii) {
+ int num_bytes;
+ if (sorted[ii]->is_thumb)
+ num_bytes = sorted[ii]->bb.num_insns << 1;
+ else
+ num_bytes = sorted[ii]->bb.num_insns << 2;
+ addr_end = sorted[ii]->bb.bb_addr + num_bytes;
+ if (addr_end > sorted[ii + 1]->bb.bb_addr) {
+ sorted[ii]->inner = sorted[ii + 1];
+ addr_diff = sorted[ii + 1]->bb.bb_addr - sorted[ii]->bb.bb_addr;
+ uint32_t num_insns;
+ if (sorted[ii]->is_thumb)
+ num_insns = addr_diff >> 1;
+ else
+ num_insns = addr_diff >> 2;
+ sorted[ii]->bb.num_insns = num_insns;
+ }
+ }
+
+ return sorted;
+}