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 <assert.h> 655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h" 755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "armdis.h" 855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options.h" 955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef TraceReader<> TraceReaderType; 1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "parse_options-inl.h" 1355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectstatic const uint32_t kOffsetThreshold = 0x100000; 1555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectstatic uint64_t startTime = 0; 1655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 1755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectvoid Usage(const char *program) 1855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{ 1955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project fprintf(stderr, 2055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project "Usage: %s [options] [-- -s start_time] trace_file elf_file\n", 2155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project program); 2255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project OptionsUsage(); 2355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 2455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 2555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 2655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectbool localParseOptions(int argc, char **argv) 2755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project{ 2855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bool err = false; 2955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project while (!err) { 3055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project int opt = getopt(argc, argv, "+s:"); 3155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (opt == -1) 3255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 3355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project switch (opt) { 3455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project case 's': 3555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project startTime = strtoull(optarg, NULL, 0); 3655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 3755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project default: 3855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project err = true; 3955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 4055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 4155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 4255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return err; 4355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 4455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 4555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) { 4655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // Parse the options 4755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ParseOptions(argc, argv); 4855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project localParseOptions(argc, argv); 4955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (argc - optind != 2) { 5055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project Usage(argv[0]); 5155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project exit(1); 5255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 5355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 5455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *trace_filename = argv[optind++]; 5555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *elf_file = argv[optind++]; 5655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project TraceReader<> *trace = new TraceReader<>; 5755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->Open(trace_filename); 5855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->SetDemangle(demangle); 5955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->ReadKernelSymbols(elf_file); 6055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project trace->SetRoot(root); 6155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 6255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project while (1) { 6355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *sym; 6455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char buf[1024]; 6555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project BBEvent event; 6655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project BBEvent ignored; 6755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 6855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (GetNextValidEvent(trace, &event, &ignored, &sym)) 6955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project break; 7055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#if 0 7155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project fprintf(stderr, "t%llu bb %lld %d\n", 7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project event.time, event.bb_num, event.num_insns); 7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#endif 7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint32_t *insns = event.insns; 7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint32_t addr = event.bb_addr; 7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint32_t offset = addr - sym->addr - sym->region->base_addr; 7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project symbol_type *vm_sym = sym->vm_sym; 7955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project const char *vm_name = NULL; 8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (vm_sym != NULL) { 8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project vm_name = vm_sym->name; 8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project offset = addr - vm_sym->addr - vm_sym->region->base_addr; 8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#if 0 8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (strcmp(sym->name, "(unknown)") == 0 || offset > kOffsetThreshold) { 8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ProcessState *process = trace->GetCurrentProcess(); 8755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ProcessState *manager = process->addr_manager; 8855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project for (int ii = 0; ii < manager->nregions; ++ii) { 8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf(" %2d: %08x - %08x base: %08x offset: %u nsyms: %4d flags: 0x%x %s\n", 9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ii, 9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->vstart, 9255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->vend, 9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->base_addr, 9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->file_offset, 9555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->nsymbols, 9655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->flags, 9755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->path); 9855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project int nsymbols = manager->regions[ii]->nsymbols; 9955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project for (int jj = 0; jj < 10 && jj < nsymbols; ++jj) { 10055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf(" %08x %s\n", 10155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->symbols[jj].addr, 10255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project manager->regions[ii]->symbols[jj].name); 10355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 10455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 10555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 10655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#endif 10755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#if 1 10855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project for (int ii = 0; ii < event.num_insns; ++ii) { 10955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint64_t sim_time = trace->ReadInsnTime(event.time); 11055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (sim_time < startTime) 11155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project continue; 11255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 11355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint32_t insn = insns[ii]; 11455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project char *disasm; 11555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project int bytes; 11655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (vm_name != NULL) { 11755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sprintf(buf, "%s+%02x: %s", vm_name, offset, sym->name); 11855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } else { 11955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sprintf(buf, "%s+%02x", sym->name, offset); 12055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 12155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 12255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (insn_is_thumb(insn)) { 12355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bytes = 2; 12455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project insn = insn_unwrap_thumb(insn); 12555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 12655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // thumb_pair is true if this is the first of a pair of 12755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // thumb instructions (BL or BLX). 12855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bool thumb_pair = ((insn & 0xf800) == 0xf000); 12955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 13055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // Get the next thumb instruction (if any) because we may need 13155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project // it for the case where insn is BL or BLX. 13255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project uint32_t insn2 = 0; 13355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (thumb_pair && (ii + 1 < event.num_insns)) { 13455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project insn2 = insns[ii + 1]; 13555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project insn2 = insn_unwrap_thumb(insn2); 13655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bytes = 4; 13755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project ii += 1; 13855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 13955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project disasm = disasm_insn_thumb(addr, insn, insn2, NULL); 14055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project if (thumb_pair) { 14155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%llu p%-4d %08x %04x %04x %-30s %s\n", 14255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sim_time, event.pid, addr, insn, insn2, buf, disasm); 14355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } else { 14455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%llu p%-4d %08x %04x %-30s %s\n", 14555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sim_time, event.pid, addr, insn, buf, disasm); 14655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 14755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } else { 14855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project bytes = 4; 14955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project disasm = Arm::disasm(addr, insn, NULL); 15055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project printf("%llu p%-4d %08x %08x %-30s %s\n", 15155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project sim_time, event.pid, addr, insn, buf, disasm); 15255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 15355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project //printf("t%llu \t%08x\n", sim_time, addr); 15455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project addr += bytes; 15555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project offset += bytes; 15655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 15755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#endif 15855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#if 0 15955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project assert(offset < kOffsetThreshold); 16055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#endif 16155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project } 16255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project 16355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project delete trace; 16455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project return 0; 16555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} 166