1 // Copyright 2006 The Android Open Source Project 2 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <stdlib.h> 6 #include <inttypes.h> 7 #include <assert.h> 8 #include "trace_reader.h" 9 #include "gtrace.h" 10 #include "bitvector.h" 11 #include "parse_options.h" 12 13 struct symbol { 14 int filenum; // the file number (for gtrace) 15 int procnum; // the procedure number (for gtrace) 16 }; 17 18 typedef TraceReader<symbol> TraceReaderType; 19 20 #include "parse_options-inl.h" 21 22 const int kMaxProcNum = 4095; 23 int next_filenum = 1; 24 int next_procnum = 1; 25 26 void Usage(const char *program) 27 { 28 fprintf(stderr, "Usage: %s [options] trace_file elf_file gtrace_file\n", 29 program); 30 OptionsUsage(); 31 } 32 33 int main(int argc, char **argv) 34 { 35 ParseOptions(argc, argv); 36 if (argc - optind != 3) { 37 Usage(argv[0]); 38 exit(1); 39 } 40 41 char *qemu_trace_file = argv[optind++]; 42 char *elf_file = argv[optind++]; 43 char *gtrace_file = argv[optind++]; 44 TraceReader<symbol> *trace = new TraceReader<symbol>; 45 trace->Open(qemu_trace_file); 46 trace->ReadKernelSymbols(elf_file); 47 trace->SetRoot(root); 48 TraceHeader *qheader = trace->GetHeader(); 49 50 // Get the first valid event to get the process id for the gtrace header. 51 BBEvent event; 52 BBEvent ignored; 53 symbol_type *sym; 54 if (GetNextValidEvent(trace, &event, &ignored, &sym)) 55 return 0; 56 57 Gtrace *gtrace = new Gtrace; 58 gtrace->Open(gtrace_file, qheader->pdate, qheader->ptime); 59 gtrace->WriteFirstHeader(qheader->start_sec, event.pid); 60 61 symbol_type *prev_sym = NULL; 62 bool eof = false; 63 while (!eof) { 64 if (sym != prev_sym) { 65 // This procedure is different from the previous procedure. 66 67 // If we have never seen this symbol before, then add it to the 68 // list of known procedures. 69 if (sym->filenum == 0) { 70 sym->filenum = next_filenum; 71 sym->procnum = next_procnum; 72 gtrace->AddProcedure(sym->filenum, sym->procnum, sym->name); 73 next_procnum += 1; 74 if (next_procnum > kMaxProcNum) { 75 next_filenum += 1; 76 next_procnum = 1; 77 } 78 } 79 80 // If we haven't yet recorded the procedure exit for the previous 81 // procedure, then do it now. 82 if (prev_sym) { 83 gtrace->AddProcExit(prev_sym->filenum, prev_sym->procnum, event.time, 84 event.pid); 85 } 86 87 // If this is not the terminating record, then record a procedure 88 // entry. 89 if (event.bb_num != 0) { 90 gtrace->AddProcEntry(sym->filenum, sym->procnum, event.time, event.pid); 91 prev_sym = sym; 92 } 93 } 94 95 eof = GetNextValidEvent(trace, &event, &ignored, &sym); 96 if (ignored.time != 0 && prev_sym) { 97 // We read an event that we are ignoring. 98 // If we haven't already recorded a procedure exit, then do so. 99 gtrace->AddProcExit(prev_sym->filenum, prev_sym->procnum, ignored.time, 100 ignored.pid); 101 prev_sym = NULL; 102 } 103 } 104 105 delete gtrace; 106 delete trace; 107 return 0; 108 } 109