1 // Copyright 2006 The Android Open Source Project
2
3 #ifndef TRACE_READER_H
4 #define TRACE_READER_H
5
6 #include <string.h>
7 #include <inttypes.h>
8 #include <elf.h>
9 #include <assert.h>
10 #include <cxxabi.h>
11 #include "read_elf.h"
12 #include "trace_reader_base.h"
13 #include "hash_table.h"
14
15 struct TraceReaderEmptyStruct {
16 };
17
18 template <class T = TraceReaderEmptyStruct>
19 class TraceReader : public TraceReaderBase {
20 public:
21
22 struct region_entry;
23 typedef struct symbol_entry : public T {
24 typedef region_entry region_type;
25
26 // Define flag values
27 static const uint32_t kIsPlt = 0x01;
28 static const uint32_t kIsVectorStart = 0x02;
29 static const uint32_t kIsVectorTable = (kIsPlt | kIsVectorStart);
30 static const uint32_t kIsInterpreter = 0x04;
31 static const uint32_t kIsMethod = 0x08;
32
33 uint32_t addr;
34
35 // This may hold the name of the interpreted method instead of
36 // the name of the native function if the native function is a
37 // virtual machine interpreter.
38 const char *name;
39
40 // The symbol for the virtual machine interpreter, or NULL
41 symbol_entry *vm_sym;
42 region_type *region;
43 uint32_t flags;
44 } symbol_type;
45
46 typedef struct region_entry {
47 // Define flag values
48 static const uint32_t kIsKernelRegion = 0x01;
49 static const uint32_t kSharedSymbols = 0x02;
50 static const uint32_t kIsLibraryRegion = 0x04;
51 static const uint32_t kIsUserMappedRegion = 0x08;
52
region_entryregion_entry53 region_entry() : refs(0), path(NULL), vstart(0), vend(0), base_addr(0),
54 file_offset(0), flags(0), nsymbols(0), symbols(NULL) {}
55
LookupFunctionByNameregion_entry56 symbol_type *LookupFunctionByName(char *name) {
57 // Just do a linear search
58 for (int ii = 0; ii < nsymbols; ++ii) {
59 if (strcmp(symbols[ii].name, name) == 0)
60 return &symbols[ii];
61 }
62 return NULL;
63 }
64
MakePrivateCopyregion_entry65 region_entry *MakePrivateCopy(region_entry *dest) {
66 dest->refs = 0;
67 dest->path = Strdup(path);
68 dest->vstart = vstart;
69 dest->vend = vend;
70 dest->base_addr = base_addr;
71 dest->file_offset = file_offset;
72 dest->flags = flags;
73 dest->nsymbols = nsymbols;
74 dest->symbols = symbols;
75 return dest;
76 }
77
78 int refs; // reference count
79 char *path;
80 uint32_t vstart;
81 uint32_t vend;
82 uint32_t base_addr;
83 uint32_t file_offset;
84 uint32_t flags;
85 int nsymbols;
86 symbol_type *symbols;
87 } region_type;
88
89 typedef typename HashTable<region_type*>::entry_type hash_entry_type;
90
91 class ProcessState {
92 public:
93
94 // The "regions" array below is a pointer to array of pointers to
95 // regions. The size of the pointer array is kInitialNumRegions,
96 // but grows if needed. There is a separate region for each mmap
97 // call which includes shared libraries as well as .dex and .jar
98 // files. In addition, there is a region for the main executable
99 // for this process, as well as a few regions for the kernel.
100 //
101 // If a child process is a clone of a parent process, the
102 // regions array is unused. Instead, the "addr_manager" pointer is
103 // used to find the process that is the address space manager for
104 // both the parent and child processes.
105 static const int kInitialNumRegions = 10;
106
107 static const int kMaxMethodStackSize = 1000;
108
109 // Define values for the ProcessState flag bits
110 static const int kCalledExec = 0x01;
111 static const int kCalledExit = 0x02;
112 static const int kIsClone = 0x04;
113 static const int kHasKernelRegion = 0x08;
114 static const int kHasFirstMmap = 0x10;
115
116 struct methodFrame {
117 uint32_t addr;
118 bool isNative;
119 };
120
ProcessState()121 ProcessState() {
122 cpu_time = 0;
123 tgid = 0;
124 pid = 0;
125 parent_pid = 0;
126 exit_val = 0;
127 flags = 0;
128 argc = 0;
129 argv = NULL;
130 name = NULL;
131 nregions = 0;
132 max_regions = 0;
133 // Don't allocate space yet until we know if we are a clone.
134 regions = NULL;
135 parent = NULL;
136 addr_manager = this;
137 next = NULL;
138 current_method_sym = NULL;
139 method_stack_top = 0;
140 }
141
~ProcessState()142 ~ProcessState() {
143 delete[] name;
144 if ((flags & kIsClone) != 0) {
145 return;
146 }
147
148 // Free the regions. We must be careful not to free the symbols
149 // within each region because the symbols are sometimes shared
150 // between multiple regions. The TraceReader class has a hash
151 // table containing all the unique regions and it will free the
152 // region symbols in its destructor. We need to free only the
153 // regions and the array of region pointers.
154 //
155 // Each region is also reference-counted. The count is zero
156 // if no other processes are sharing this region.
157 for (int ii = 0; ii < nregions; ii++) {
158 if (regions[ii]->refs > 0) {
159 regions[ii]->refs -= 1;
160 continue;
161 }
162
163 delete regions[ii];
164 }
165
166 delete[] regions;
167
168 for (int ii = 0; ii < argc; ++ii)
169 delete[] argv[ii];
170 delete[] argv;
171 }
172
173 // Dumps the stack contents to standard output. For debugging.
174 void DumpStack(FILE *stream);
175
176 uint64_t cpu_time;
177 uint64_t start_time;
178 uint64_t end_time;
179 int tgid;
180 int pid;
181 int parent_pid;
182 int exit_val;
183 uint32_t flags;
184 int argc;
185 char **argv;
186 const char *name;
187 int nregions; // num regions in use
188 int max_regions; // max regions allocated
189 region_type **regions;
190 ProcessState *parent;
191 ProcessState *addr_manager; // the address space manager process
192 ProcessState *next;
193 int method_stack_top;
194 methodFrame method_stack[kMaxMethodStackSize];
195 symbol_type *current_method_sym;
196 };
197
198 TraceReader();
199 ~TraceReader();
200
201 void ReadKernelSymbols(const char *kernel_file);
202 void CopyKernelRegion(ProcessState *pstate);
203 void ClearRegions(ProcessState *pstate);
204 void CopyRegions(ProcessState *parent, ProcessState *child);
205 void DumpRegions(FILE *stream, ProcessState *pstate);
206 symbol_type *LookupFunction(int pid, uint32_t addr, uint64_t time);
207 symbol_type *GetSymbols(int *num_syms);
GetCurrentProcess()208 ProcessState *GetCurrentProcess() { return current_; }
209 ProcessState *GetProcesses(int *num_procs);
210 ProcessState *GetNextProcess();
211 const char *GetProcessName(int pid);
SetRoot(const char * root)212 void SetRoot(const char *root) { root_ = root; }
SetDemangle(bool demangle)213 void SetDemangle(bool demangle) { demangle_ = demangle; }
214 bool ReadMethodSymbol(MethodRec *method_record,
215 symbol_type **psym,
216 ProcessState **pproc);
217
218 protected:
219 virtual int FindCurrentPid(uint64_t time);
220
221 private:
222
223 static const int kNumPids = 32768;
224 static const uint32_t kIncludeLocalSymbols = 0x1;
225
226 void AddPredefinedRegion(region_type *region, const char *path,
227 uint32_t vstart, uint32_t vend,
228 uint32_t base);
229 void InitRegionSymbols(region_type *region, int nsymbols);
230 void AddRegionSymbol(region_type *region, int idx,
231 uint32_t addr, const char *name,
232 uint32_t flags);
233 void AddPredefinedRegions(ProcessState *pstate);
234 void demangle_names(int nfuncs, symbol_type *functions);
235 bool ReadElfSymbols(region_type *region, uint32_t flags);
236 void AddRegion(ProcessState *pstate, region_type *region);
237 region_type *FindRegion(uint32_t addr, int nregions,
238 region_type **regions);
239 int FindRegionIndex(uint32_t addr, int nregions,
240 region_type **regions);
241 void FindAndRemoveRegion(ProcessState *pstate,
242 uint32_t vstart, uint32_t vend);
243 symbol_type *FindFunction(uint32_t addr, int nsyms,
244 symbol_type *symbols, bool exact_match);
245 symbol_type *FindCurrentMethod(int pid, uint64_t time);
246 void PopulateSymbolsFromDexFile(const DexFileList *dexfile,
247 region_type *region);
248 void HandlePidEvent(PidEvent *event);
249 void HandleMethodRecord(ProcessState *pstate,
250 MethodRec *method_rec);
251
252 int cached_pid_;
253 symbol_type *cached_func_;
254 symbol_type unknown_;
255 int next_pid_;
256
257 PidEvent next_pid_event_;
258 ProcessState *processes_[kNumPids];
259 ProcessState *current_;
260 MethodRec next_method_;
261 uint64_t function_start_time_;
262 const char *root_;
263 HashTable<region_type*> *hash_;
264 bool demangle_;
265 };
266
267 template<class T>
TraceReader()268 TraceReader<T>::TraceReader()
269 {
270 static PidEvent event_no_action;
271
272 cached_pid_ = -1;
273 cached_func_ = NULL;
274
275 memset(&unknown_, 0, sizeof(symbol_type));
276 unknown_.name = "(unknown)";
277 next_pid_ = 0;
278
279 memset(&event_no_action, 0, sizeof(PidEvent));
280 event_no_action.rec_type = kPidNoAction;
281 next_pid_event_ = event_no_action;
282 for (int ii = 1; ii < kNumPids; ++ii)
283 processes_[ii] = NULL;
284 current_ = new ProcessState;
285 processes_[0] = current_;
286 next_method_.time = 0;
287 next_method_.addr = 0;
288 next_method_.flags = 0;
289 function_start_time_ = 0;
290 root_ = "";
291 hash_ = new HashTable<region_type*>(512);
292 AddPredefinedRegions(current_);
293 demangle_ = true;
294 }
295
296 template<class T>
~TraceReader()297 TraceReader<T>::~TraceReader()
298 {
299 hash_entry_type *ptr;
300 for (ptr = hash_->GetFirst(); ptr; ptr = hash_->GetNext()) {
301 region_type *region = ptr->value;
302 // If the symbols are not shared with another region, then delete them.
303 if ((region->flags & region_type::kSharedSymbols) == 0) {
304 int nsymbols = region->nsymbols;
305 for (int ii = 0; ii < nsymbols; ii++) {
306 delete[] region->symbols[ii].name;
307 }
308 delete[] region->symbols;
309 }
310 delete[] region->path;
311
312 // Do not delete the region itself here. Each region
313 // is reference-counted and deleted by the ProcessState
314 // object that owns it.
315 }
316 delete hash_;
317
318 // Delete the ProcessState objects after the region symbols in
319 // the hash table above so that we still have valid region pointers
320 // when deleting the region symbols.
321 for (int ii = 0; ii < kNumPids; ++ii) {
322 delete processes_[ii];
323 }
324 }
325
326 // This function is used by the qsort() routine to sort symbols
327 // into increasing address order.
328 template<class T>
cmp_symbol_addr(const void * a,const void * b)329 int cmp_symbol_addr(const void *a, const void *b) {
330 typedef typename TraceReader<T>::symbol_type stype;
331
332 const stype *syma = static_cast<stype const *>(a);
333 const stype *symb = static_cast<stype const *>(b);
334 uint32_t addr1 = syma->addr;
335 uint32_t addr2 = symb->addr;
336 if (addr1 < addr2)
337 return -1;
338 if (addr1 > addr2)
339 return 1;
340
341 // The addresses are the same, sort the symbols into
342 // increasing alphabetical order. But put symbols that
343 // that start with "_" last.
344 if (syma->name[0] == '_' || symb->name[0] == '_') {
345 // Count the number of leading underscores and sort the
346 // symbol with the most underscores last.
347 int aCount = 0;
348 while (syma->name[aCount] == '_')
349 aCount += 1;
350 int bCount = 0;
351 while (symb->name[bCount] == '_')
352 bCount += 1;
353 if (aCount < bCount) {
354 return -1;
355 }
356 if (aCount > bCount) {
357 return 1;
358 }
359 // If the symbols have the same number of underscores, then
360 // fall through and sort by the whole name.
361 }
362 return strcmp(syma->name, symb->name);
363 }
364
365 // This function is used by the qsort() routine to sort region entries
366 // into increasing address order.
367 template<class T>
cmp_region_addr(const void * a,const void * b)368 int cmp_region_addr(const void *a, const void *b) {
369 typedef typename TraceReader<T>::region_type rtype;
370
371 const rtype *ma = *static_cast<rtype* const *>(a);
372 const rtype *mb = *static_cast<rtype* const *>(b);
373 uint32_t addr1 = ma->vstart;
374 uint32_t addr2 = mb->vstart;
375 if (addr1 < addr2)
376 return -1;
377 if (addr1 == addr2)
378 return 0;
379 return 1;
380 }
381
382 // This routine returns a new array containing all the symbols.
383 template<class T>
384 typename TraceReader<T>::symbol_type*
GetSymbols(int * num_syms)385 TraceReader<T>::GetSymbols(int *num_syms)
386 {
387 // Count the symbols
388 int nsyms = 0;
389 for (hash_entry_type *ptr = hash_->GetFirst(); ptr; ptr = hash_->GetNext()) {
390 region_type *region = ptr->value;
391 nsyms += region->nsymbols;
392 }
393 *num_syms = nsyms;
394
395 // Allocate space
396 symbol_type *syms = new symbol_type[nsyms];
397 symbol_type *next_sym = syms;
398
399 // Copy the symbols
400 for (hash_entry_type *ptr = hash_->GetFirst(); ptr; ptr = hash_->GetNext()) {
401 region_type *region = ptr->value;
402 memcpy(next_sym, region->symbols, region->nsymbols * sizeof(symbol_type));
403 next_sym += region->nsymbols;
404 }
405
406 return syms;
407 }
408
409 // This routine returns all the valid processes.
410 template<class T>
411 typename TraceReader<T>::ProcessState*
GetProcesses(int * num_procs)412 TraceReader<T>::GetProcesses(int *num_procs)
413 {
414 // Count the valid processes
415 int nprocs = 0;
416 for (int ii = 0; ii < kNumPids; ++ii) {
417 if (processes_[ii])
418 nprocs += 1;
419 }
420
421 // Allocate a new array to hold the valid processes.
422 ProcessState *procs = new ProcessState[nprocs];
423
424 // Copy the processes to the new array.
425 ProcessState *pstate = procs;
426 for (int ii = 0; ii < kNumPids; ++ii) {
427 if (processes_[ii])
428 memcpy(pstate++, processes_[ii], sizeof(ProcessState));
429 }
430
431 *num_procs = nprocs;
432 return procs;
433 }
434
435 // This routine returns the next valid process, or NULL if there are no
436 // more valid processes.
437 template<class T>
438 typename TraceReader<T>::ProcessState*
GetNextProcess()439 TraceReader<T>::GetNextProcess()
440 {
441 while (next_pid_ < kNumPids) {
442 if (processes_[next_pid_])
443 return processes_[next_pid_++];
444 next_pid_ += 1;
445 }
446 next_pid_ = 0;
447 return NULL;
448 }
449
450 template<class T>
GetProcessName(int pid)451 const char* TraceReader<T>::GetProcessName(int pid)
452 {
453 if (pid < 0 || pid >= kNumPids || processes_[pid] == NULL)
454 return "(unknown)";
455 return processes_[pid]->name;
456 }
457
458 template<class T>
AddPredefinedRegion(region_type * region,const char * path,uint32_t vstart,uint32_t vend,uint32_t base)459 void TraceReader<T>::AddPredefinedRegion(region_type *region, const char *path,
460 uint32_t vstart, uint32_t vend,
461 uint32_t base)
462 {
463 // Copy the path to make it easy to delete later.
464 int len = strlen(path);
465 region->path = new char[len + 1];
466 strcpy(region->path, path);
467 region->vstart = vstart;
468 region->vend = vend;
469 region->base_addr = base;
470 region->flags = region_type::kIsKernelRegion;
471 }
472
473 template<class T>
InitRegionSymbols(region_type * region,int nsymbols)474 void TraceReader<T>::InitRegionSymbols(region_type *region, int nsymbols)
475 {
476 region->nsymbols = nsymbols;
477 region->symbols = new symbol_type[nsymbols];
478 memset(region->symbols, 0, nsymbols * sizeof(symbol_type));
479 }
480
481 template<class T>
AddRegionSymbol(region_type * region,int idx,uint32_t addr,const char * name,uint32_t flags)482 void TraceReader<T>::AddRegionSymbol(region_type *region, int idx,
483 uint32_t addr, const char *name,
484 uint32_t flags)
485 {
486 region->symbols[idx].addr = addr;
487 region->symbols[idx].name = Strdup(name);
488 region->symbols[idx].vm_sym = NULL;
489 region->symbols[idx].region = region;
490 region->symbols[idx].flags = flags;
491 }
492
493 template<class T>
AddPredefinedRegions(ProcessState * pstate)494 void TraceReader<T>::AddPredefinedRegions(ProcessState *pstate)
495 {
496 region_type *region = new region_type;
497 AddPredefinedRegion(region, "(bootloader)", 0, 0x14, 0);
498 InitRegionSymbols(region, 2);
499 AddRegionSymbol(region, 0, 0, "(bootloader_start)", 0);
500 AddRegionSymbol(region, 1, 0x14, "(bootloader_end)", 0);
501 AddRegion(pstate, region);
502 hash_->Update(region->path, region);
503
504 region = new region_type;
505 AddPredefinedRegion(region, "(exception vectors)", 0xffff0000, 0xffff0500,
506 0xffff0000);
507 InitRegionSymbols(region, 2);
508 AddRegionSymbol(region, 0, 0x0, "(vector_start)",
509 symbol_type::kIsVectorStart);
510 AddRegionSymbol(region, 1, 0x500, "(vector_end)", 0);
511 AddRegion(pstate, region);
512 hash_->Update(region->path, region);
513
514 region = new region_type;
515 AddPredefinedRegion(region, "(atomic ops)", 0xffff0f80, 0xffff1000,
516 0xffff0f80);
517 // Mark this region as also being mapped in user-space.
518 // This isn't used anywhere in this code but client code can test for
519 // this flag and decide whether to treat this as kernel or user code.
520 region->flags |= region_type::kIsUserMappedRegion;
521
522 InitRegionSymbols(region, 4);
523 AddRegionSymbol(region, 0, 0x0, "(kuser_atomic_inc)", 0);
524 AddRegionSymbol(region, 1, 0x20, "(kuser_atomic_dec)", 0);
525 AddRegionSymbol(region, 2, 0x40, "(kuser_cmpxchg)", 0);
526 AddRegionSymbol(region, 3, 0x80, "(kuser_end)", 0);
527 AddRegion(pstate, region);
528 hash_->Update(region->path, region);
529 }
530
531 template<class T>
ReadKernelSymbols(const char * kernel_file)532 void TraceReader<T>::ReadKernelSymbols(const char *kernel_file)
533 {
534 region_type *region = new region_type;
535 // Copy the path to make it easy to delete later.
536 int len = strlen(kernel_file);
537 region->path = new char[len + 1];
538 strcpy(region->path, kernel_file);
539 region->flags = region_type::kIsKernelRegion;
540 ReadElfSymbols(region, kIncludeLocalSymbols);
541 region->vend = 0xffff0000;
542 AddRegion(processes_[0], region);
543 processes_[0]->flags |= ProcessState::kHasKernelRegion;
544 hash_->Update(region->path, region);
545 }
546
547 template<class T>
demangle_names(int nfuncs,symbol_type * functions)548 void TraceReader<T>::demangle_names(int nfuncs, symbol_type *functions)
549 {
550 char *demangled;
551 int status;
552
553 for (int ii = 0; ii < nfuncs; ++ii) {
554 demangled = NULL;
555 int len = strlen(functions[ii].name);
556
557 // If we don't check for "len > 1" then the demangler will incorrectly
558 // expand 1-letter function names. For example, "b" becomes "bool",
559 // "c" becomes "char" and "d" becomes "double". Also check that the
560 // first character is an underscore. Otherwise, on some strings
561 // the demangler will try to read past the end of the string (because
562 // the string is not really a C++ mangled name) and valgrind will
563 // complain.
564 if (demangle_ && len > 1 && functions[ii].name[0] == '_') {
565 demangled = abi::__cxa_demangle(functions[ii].name, 0, NULL,
566 &status);
567 }
568
569 if (demangled != NULL) {
570 delete[] functions[ii].name;
571 functions[ii].name = Strdup(demangled);
572 free(demangled);
573 }
574 }
575 }
576
577 // Adds the symbols from the given ELF file to the given process.
578 // Returns false if the file was not an ELF file or if there was an
579 // error trying to read the sections of the ELF file.
580 template<class T>
ReadElfSymbols(region_type * region,uint32_t flags)581 bool TraceReader<T>::ReadElfSymbols(region_type *region, uint32_t flags)
582 {
583 static char full_path[4096];
584 Elf32_Shdr *symtab, *symstr;
585 Elf32_Ehdr *hdr;
586 Elf32_Shdr *shdr;
587
588 full_path[0] = 0;
589 if (root_ && strcmp(root_, "/")) {
590 strcpy(full_path, root_);
591 }
592 strcat(full_path, region->path);
593 FILE *fobj = fopen(full_path, "r");
594 if(fobj == NULL) {
595 EmptyRegion:
596 // we need to create an (unknown) symbol with address 0, otherwise some
597 // other parts of the trace reader will simply crash when dealing with
598 // an empty region
599 region->vstart = 0;
600 region->nsymbols = 1;
601 region->symbols = new symbol_type[1];
602 memset(region->symbols, 0, sizeof(symbol_type));
603
604 region->symbols[0].addr = 0;
605 region->symbols[0].name = Strdup("(unknown)");
606 region->symbols[0].vm_sym = NULL;
607 region->symbols[0].region = region;
608 region->symbols[0].flags = 0;
609
610 if (fobj != NULL)
611 fclose(fobj);
612 return false;
613 }
614
615 hdr = ReadElfHeader(fobj);
616 if (hdr == NULL) {
617 fprintf(stderr, "Cannot read ELF header from '%s'\n", full_path);
618 goto EmptyRegion;
619 }
620
621 shdr = ReadSectionHeaders(hdr, fobj);
622 if(shdr == NULL) {
623 fprintf(stderr, "Can't read section headers from executable\n");
624 goto EmptyRegion;
625 }
626 char *section_names = ReadStringTable(hdr, shdr, fobj);
627
628 // Get the symbol table section
629 symtab = FindSymbolTableSection(hdr, shdr, section_names);
630 if (symtab == NULL || symtab->sh_size == 0) {
631 fprintf(stderr, "Can't read symbol table from '%s'\n", full_path);
632 goto EmptyRegion;
633 }
634
635 // Get the symbol string table section
636 symstr = FindSymbolStringTableSection(hdr, shdr, section_names);
637 if (symstr == NULL || symstr->sh_size == 0) {
638 fprintf(stderr, "Can't read symbol string table from '%s'\n", full_path);
639 goto EmptyRegion;
640 }
641
642 // Load the symbol string table data
643 char *symbol_names = new char[symstr->sh_size];
644 ReadSection(symstr, symbol_names, fobj);
645
646 int num_entries = symtab->sh_size / symtab->sh_entsize;
647 Elf32_Sym *elf_symbols = new Elf32_Sym[num_entries];
648 ReadSection(symtab, elf_symbols, fobj);
649 AdjustElfSymbols(hdr, elf_symbols, num_entries);
650 #if 0
651 printf("size: %d, ent_size: %d, num_entries: %d\n",
652 symtab->sh_size, symtab->sh_entsize, num_entries);
653 #endif
654 int nfuncs = 0;
655
656 // Allocate space for all of the symbols for now. We will
657 // reallocate space for just the function symbols after we
658 // know how many there are. Also, make sure there is room
659 // for some extra symbols, including the text section names.
660 int num_alloc = num_entries + hdr->e_shnum + 1;
661 symbol_type *func_symbols = new symbol_type[num_alloc];
662 memset(func_symbols, 0, num_alloc * sizeof(symbol_type));
663
664 // If this is the shared library for a virtual machine, then
665 // set the IsInterpreter flag for all symbols in that shared library.
666 // This will allow us to replace the symbol names with the name of
667 // the currently executing method on the virtual machine.
668 int symbol_flags = 0;
669 char *cp = strrchr(region->path, '/');
670 if (cp != NULL) {
671 // Move past the '/'
672 cp += 1;
673 } else {
674 // There was no '/', so use the whole path
675 cp = region->path;
676 }
677 if (strcmp(cp, "libdvm.so") == 0) {
678 symbol_flags = symbol_type::kIsInterpreter;
679 }
680
681 bool zero_found = false;
682 for (int ii = 1; ii < num_entries; ++ii) {
683 int idx = elf_symbols[ii].st_name;
684
685 // If the symbol does not have a name, or if the name starts with a
686 // dollar sign ($), then skip it.
687 if (idx == 0 || symbol_names[idx] == 0 || symbol_names[idx] == '$')
688 continue;
689
690 // If the section index is not executable, then skip it.
691 uint32_t section = elf_symbols[ii].st_shndx;
692 if (section == 0 || section >= hdr->e_shnum)
693 continue;
694 if ((shdr[section].sh_flags & SHF_EXECINSTR) == 0)
695 continue;
696
697 uint8_t sym_type = ELF32_ST_TYPE(elf_symbols[ii].st_info);
698 uint8_t sym_bind = ELF32_ST_BIND(elf_symbols[ii].st_info);
699
700 // Allow the caller to decide if we want local non-function
701 // symbols to be included. We currently include these symbols
702 // only for the kernel, where it is useful because the kernel
703 // has lots of assembly language labels that have meaningful names.
704 if ((flags & kIncludeLocalSymbols) == 0 && sym_bind == STB_LOCAL
705 && sym_type != STT_FUNC) {
706 continue;
707 }
708 #if 0
709 printf("%08x %x %x %s\n",
710 elf_symbols[ii].st_value,
711 sym_bind,
712 sym_type,
713 &symbol_names[idx]);
714 #endif
715 if (sym_type != STT_FUNC && sym_type != STT_NOTYPE)
716 continue;
717
718 if (elf_symbols[ii].st_value == 0)
719 zero_found = true;
720
721 // The address of thumb functions seem to have the low bit set,
722 // even though the instructions are really at an even address.
723 uint32_t addr = elf_symbols[ii].st_value & ~0x1;
724 func_symbols[nfuncs].addr = addr;
725 func_symbols[nfuncs].name = Strdup(&symbol_names[idx]);
726 func_symbols[nfuncs].flags = symbol_flags;
727
728 nfuncs += 1;
729 }
730
731 // Add a [0, "(unknown)"] symbol pair if there is not already a
732 // symbol with the address zero. We don't need to reallocate space
733 // because we already have more than we need.
734 if (!zero_found) {
735 func_symbols[nfuncs].addr = 0;
736 func_symbols[nfuncs].name = Strdup("(0 unknown)");
737 nfuncs += 1;
738 }
739
740 // Add another entry at the end
741 func_symbols[nfuncs].addr = 0xffffffff;
742 func_symbols[nfuncs].name = Strdup("(end)");
743 nfuncs += 1;
744
745 // Add in the names of the text sections, but only if there
746 // are no symbols with that address already.
747 for (int section = 0; section < hdr->e_shnum; ++section) {
748 if ((shdr[section].sh_flags & SHF_EXECINSTR) == 0)
749 continue;
750
751 uint32_t addr = shdr[section].sh_addr;
752 // Search for a symbol with a matching address. The symbols aren't
753 // sorted yet so we just search the whole list.
754 int ii;
755 for (ii = 0; ii < nfuncs; ++ii) {
756 if (addr == func_symbols[ii].addr)
757 break;
758 }
759 if (ii == nfuncs) {
760 // Symbol at address "addr" does not exist, so add the text
761 // section name. This will usually add the ".plt" section
762 // (procedure linkage table).
763 int idx = shdr[section].sh_name;
764 func_symbols[nfuncs].addr = addr;
765 func_symbols[nfuncs].name = Strdup(§ion_names[idx]);
766 if (strcmp(func_symbols[nfuncs].name, ".plt") == 0) {
767 func_symbols[nfuncs].flags |= symbol_type::kIsPlt;
768 // Change the name of the symbol to include the
769 // name of the library. Otherwise we will have lots
770 // of ".plt" symbols.
771 int len = strlen(region->path);
772 len += strlen(":.plt");
773 char *name = new char[len + 1];
774 strcpy(name, region->path);
775 strcat(name, ":.plt");
776 delete[] func_symbols[nfuncs].name;
777 func_symbols[nfuncs].name = name;
778
779 // Check if this is part of the virtual machine interpreter
780 char *cp = strrchr(region->path, '/');
781 if (cp != NULL) {
782 // Move past the '/'
783 cp += 1;
784 } else {
785 // There was no '/', so use the whole path
786 cp = region->path;
787 }
788 if (strcmp(cp, "libdvm.so") == 0) {
789 func_symbols[nfuncs].flags |= symbol_type::kIsInterpreter;
790 }
791 }
792 nfuncs += 1;
793 }
794 }
795
796 // Allocate just the space we need now that we know exactly
797 // how many symbols we have.
798 symbol_type *functions = new symbol_type[nfuncs];
799
800 // Copy the symbols to the functions array
801 memcpy(functions, func_symbols, nfuncs * sizeof(symbol_type));
802 delete[] func_symbols;
803
804 // Assign the region pointers
805 for (int ii = 0; ii < nfuncs; ++ii) {
806 functions[ii].region = region;
807 }
808
809 // Sort the symbols into increasing address order
810 qsort(functions, nfuncs, sizeof(symbol_type), cmp_symbol_addr<T>);
811
812 // If there are multiple symbols with the same address, then remove
813 // the duplicates. First, count the number of duplicates.
814 uint32_t prev_addr = ~0;
815 int num_duplicates = 0;
816 for (int ii = 0; ii < nfuncs; ++ii) {
817 if (prev_addr == functions[ii].addr)
818 num_duplicates += 1;
819 prev_addr = functions[ii].addr;
820 }
821
822 if (num_duplicates > 0) {
823 int num_uniq = nfuncs - num_duplicates;
824
825 // Allocate space for the unique functions
826 symbol_type *uniq_functions = new symbol_type[num_uniq];
827
828 // Copy the unique functions
829 prev_addr = ~0;
830 int next_uniq = 0;
831 for (int ii = 0; ii < nfuncs; ++ii) {
832 if (prev_addr == functions[ii].addr) {
833 delete[] functions[ii].name;
834 continue;
835 }
836 memcpy(&uniq_functions[next_uniq++], &functions[ii],
837 sizeof(symbol_type));
838 prev_addr = functions[ii].addr;
839 }
840 assert(next_uniq == num_uniq);
841
842 delete[] functions;
843 functions = uniq_functions;
844 nfuncs = num_uniq;
845 }
846
847 // Finally, demangle all of the symbol names
848 demangle_names(nfuncs, functions);
849
850 uint32_t min_addr = 0;
851 if (!zero_found)
852 min_addr = functions[1].addr;
853 if (region->vstart == 0)
854 region->vstart = min_addr;
855 region->nsymbols = nfuncs;
856 region->symbols = functions;
857
858 #if 0
859 printf("%s num symbols: %d min_addr: 0x%x\n", region->path, nfuncs, min_addr);
860 for (int ii = 0; ii < nfuncs; ++ii) {
861 printf("0x%08x %s\n", functions[ii].addr, functions[ii].name);
862 }
863 #endif
864 delete[] elf_symbols;
865 delete[] symbol_names;
866 delete[] section_names;
867 delete[] shdr;
868 delete hdr;
869 fclose(fobj);
870
871 return true;
872 }
873
874 template<class T>
CopyKernelRegion(ProcessState * pstate)875 void TraceReader<T>::CopyKernelRegion(ProcessState *pstate)
876 {
877 ProcessState *manager = pstate->addr_manager;
878 if (manager->flags & ProcessState::kHasKernelRegion)
879 return;
880
881 int nregions = processes_[0]->nregions;
882 region_type **regions = processes_[0]->regions;
883 for (int ii = 0; ii < nregions; ii++) {
884 if (regions[ii]->flags & region_type::kIsKernelRegion) {
885 AddRegion(manager, regions[ii]);
886 regions[ii]->refs += 1;
887 }
888 }
889 manager->flags |= ProcessState::kHasKernelRegion;
890 }
891
892 template<class T>
ClearRegions(ProcessState * pstate)893 void TraceReader<T>::ClearRegions(ProcessState *pstate)
894 {
895 assert(pstate->pid != 0);
896 int nregions = pstate->nregions;
897 region_type **regions = pstate->regions;
898
899 // Decrement the reference count on all the regions
900 for (int ii = 0; ii < nregions; ii++) {
901 if (regions[ii]->refs > 0) {
902 regions[ii]->refs -= 1;
903 continue;
904 }
905
906 delete regions[ii];
907 }
908 delete[] pstate->regions;
909 pstate->regions = NULL;
910 pstate->nregions = 0;
911 pstate->max_regions = 0;
912 pstate->addr_manager = pstate;
913 pstate->flags &= ~ProcessState::kIsClone;
914 pstate->flags &= ~ProcessState::kHasKernelRegion;
915 CopyKernelRegion(pstate);
916 }
917
918 template<class T>
AddRegion(ProcessState * pstate,region_type * region)919 void TraceReader<T>::AddRegion(ProcessState *pstate, region_type *region)
920 {
921 ProcessState *manager = pstate->addr_manager;
922 if (manager->regions == NULL) {
923 manager->max_regions = ProcessState::kInitialNumRegions;
924 manager->regions = new region_type*[manager->max_regions];
925 manager->nregions = 0;
926 }
927
928 // Check if we need to grow the array
929 int nregions = manager->nregions;
930 int max_regions = manager->max_regions;
931 if (nregions >= max_regions) {
932 max_regions <<= 1;
933 manager->max_regions = max_regions;
934 region_type **regions = new region_type*[max_regions];
935 for (int ii = 0; ii < nregions; ii++) {
936 regions[ii] = manager->regions[ii];
937 }
938 delete[] manager->regions;
939 manager->regions = regions;
940 }
941
942 // Add the new region to the end of the array and resort
943 manager->regions[nregions] = region;
944 nregions += 1;
945 manager->nregions = nregions;
946
947 // Resort the regions into increasing start address
948 qsort(manager->regions, nregions, sizeof(region_type*), cmp_region_addr<T>);
949 }
950
951 template<class T>
FindAndRemoveRegion(ProcessState * pstate,uint32_t vstart,uint32_t vend)952 void TraceReader<T>::FindAndRemoveRegion(ProcessState *pstate, uint32_t vstart,
953 uint32_t vend)
954 {
955 ProcessState *manager = pstate->addr_manager;
956 int nregions = manager->nregions;
957 int index = FindRegionIndex(vstart, nregions, manager->regions);
958 region_type *region = manager->regions[index];
959
960 // If the region does not contain [vstart,vend], then return.
961 if (vstart < region->vstart || vend > region->vend)
962 return;
963
964 // If the existing region exactly matches the address range [vstart,vend]
965 // then remove the whole region.
966 if (vstart == region->vstart && vend == region->vend) {
967 // The regions are reference-counted.
968 if (region->refs == 0) {
969 // Free the region
970 hash_->Remove(region->path);
971 delete region;
972 } else {
973 region->refs -= 1;
974 }
975
976 if (nregions > 1) {
977 // Assign the region at the end of the array to this empty slot
978 manager->regions[index] = manager->regions[nregions - 1];
979
980 // Resort the regions into increasing start address
981 qsort(manager->regions, nregions - 1, sizeof(region_type*),
982 cmp_region_addr<T>);
983 }
984 manager->nregions = nregions - 1;
985 return;
986 }
987
988 // If the existing region contains the given range and ends at the
989 // end of the given range (a common case for some reason), then
990 // truncate the existing region so that it ends at vstart (because
991 // we are deleting the range [vstart,vend]).
992 if (vstart > region->vstart && vend == region->vend) {
993 region_type *truncated;
994
995 if (region->refs == 0) {
996 // This region is not shared, so truncate it directly
997 truncated = region;
998 } else {
999 // This region is shared, so make a copy that we can truncate
1000 region->refs -= 1;
1001 truncated = region->MakePrivateCopy(new region_type);
1002 }
1003 truncated->vend = vstart;
1004 manager->regions[index] = truncated;
1005 }
1006 }
1007
1008 template<class T>
CopyRegions(ProcessState * parent,ProcessState * child)1009 void TraceReader<T>::CopyRegions(ProcessState *parent, ProcessState *child)
1010 {
1011 // Copy the parent's address space
1012 ProcessState *manager = parent->addr_manager;
1013 int nregions = manager->nregions;
1014 child->nregions = nregions;
1015 child->max_regions = manager->max_regions;
1016 region_type **regions = new region_type*[manager->max_regions];
1017 child->regions = regions;
1018 memcpy(regions, manager->regions, nregions * sizeof(region_type*));
1019
1020 // Increment the reference count on all the regions
1021 for (int ii = 0; ii < nregions; ii++) {
1022 regions[ii]->refs += 1;
1023 }
1024 }
1025
1026 template<class T>
DumpRegions(FILE * stream,ProcessState * pstate)1027 void TraceReader<T>::DumpRegions(FILE *stream, ProcessState *pstate) {
1028 ProcessState *manager = pstate->addr_manager;
1029 for (int ii = 0; ii < manager->nregions; ++ii) {
1030 fprintf(stream, " %08x - %08x offset: %5x nsyms: %4d refs: %d %s\n",
1031 manager->regions[ii]->vstart,
1032 manager->regions[ii]->vend,
1033 manager->regions[ii]->file_offset,
1034 manager->regions[ii]->nsymbols,
1035 manager->regions[ii]->refs,
1036 manager->regions[ii]->path);
1037 }
1038 }
1039
1040 template<class T>
1041 typename TraceReader<T>::region_type *
FindRegion(uint32_t addr,int nregions,region_type ** regions)1042 TraceReader<T>::FindRegion(uint32_t addr, int nregions, region_type **regions)
1043 {
1044 int high = nregions;
1045 int low = -1;
1046 while (low + 1 < high) {
1047 int middle = (high + low) / 2;
1048 uint32_t middle_addr = regions[middle]->vstart;
1049 if (middle_addr == addr)
1050 return regions[middle];
1051 if (middle_addr > addr)
1052 high = middle;
1053 else
1054 low = middle;
1055 }
1056
1057 // If we get here then we did not find an exact address match. So use
1058 // the closest region address that is less than the given address.
1059 if (low < 0)
1060 low = 0;
1061 return regions[low];
1062 }
1063
1064 template<class T>
FindRegionIndex(uint32_t addr,int nregions,region_type ** regions)1065 int TraceReader<T>::FindRegionIndex(uint32_t addr, int nregions,
1066 region_type **regions)
1067 {
1068 int high = nregions;
1069 int low = -1;
1070 while (low + 1 < high) {
1071 int middle = (high + low) / 2;
1072 uint32_t middle_addr = regions[middle]->vstart;
1073 if (middle_addr == addr)
1074 return middle;
1075 if (middle_addr > addr)
1076 high = middle;
1077 else
1078 low = middle;
1079 }
1080
1081 // If we get here then we did not find an exact address match. So use
1082 // the closest region address that is less than the given address.
1083 if (low < 0)
1084 low = 0;
1085 return low;
1086 }
1087
1088 template<class T>
1089 typename TraceReader<T>::symbol_type *
FindFunction(uint32_t addr,int nsyms,symbol_type * symbols,bool exact_match)1090 TraceReader<T>::FindFunction(uint32_t addr, int nsyms, symbol_type *symbols,
1091 bool exact_match)
1092 {
1093 int high = nsyms;
1094 int low = -1;
1095 while (low + 1 < high) {
1096 int middle = (high + low) / 2;
1097 uint32_t middle_addr = symbols[middle].addr;
1098 if (middle_addr == addr)
1099 return &symbols[middle];
1100 if (middle_addr > addr)
1101 high = middle;
1102 else
1103 low = middle;
1104 }
1105
1106 // If we get here then we did not find an exact address match. So use
1107 // the closest function address that is less than the given address.
1108 // We added a symbol with address zero so if there is no known
1109 // function containing the given address, then we will return the
1110 // "(unknown)" symbol.
1111 if (low >= 0 && !exact_match)
1112 return &symbols[low];
1113 return NULL;
1114 }
1115
1116 template<class T>
1117 typename TraceReader<T>::symbol_type *
LookupFunction(int pid,uint32_t addr,uint64_t time)1118 TraceReader<T>::LookupFunction(int pid, uint32_t addr, uint64_t time)
1119 {
1120 // Check if the previous match is still a good match.
1121 if (cached_pid_ == pid) {
1122 uint32_t vstart = cached_func_->region->vstart;
1123 uint32_t vend = cached_func_->region->vend;
1124 if (addr >= vstart && addr < vend) {
1125 uint32_t sym_addr = addr - cached_func_->region->base_addr;
1126 if (sym_addr >= cached_func_->addr
1127 && sym_addr < (cached_func_ + 1)->addr) {
1128
1129 // Check if there is a Java method on the method trace.
1130 symbol_type *sym = FindCurrentMethod(pid, time);
1131 if (sym != NULL) {
1132 sym->vm_sym = cached_func_;
1133 return sym;
1134 }
1135 return cached_func_;
1136 }
1137 }
1138 }
1139
1140 ProcessState *pstate = processes_[pid];
1141 if (pstate == NULL) {
1142 // There is no process state for the specified pid.
1143 // This should never happen.
1144 cached_pid_ = -1;
1145 cached_func_ = NULL;
1146 return NULL;
1147 }
1148 ProcessState *manager = pstate->addr_manager;
1149 cached_pid_ = pid;
1150 region_type *region = FindRegion(addr, manager->nregions, manager->regions);
1151 uint32_t sym_addr = addr - region->base_addr;
1152
1153 cached_func_ = FindFunction(sym_addr, region->nsymbols, region->symbols,
1154 false /* no exact match */);
1155 if (cached_func_ != NULL) {
1156 cached_func_->region = region;
1157
1158 // Check if there is a Java method on the method trace.
1159 symbol_type *sym = FindCurrentMethod(pid, time);
1160 if (sym != NULL) {
1161 sym->vm_sym = cached_func_;
1162 return sym;
1163 }
1164 }
1165
1166 return cached_func_;
1167 }
1168
1169 template <class T>
HandlePidEvent(PidEvent * event)1170 void TraceReader<T>::HandlePidEvent(PidEvent *event)
1171 {
1172 switch (event->rec_type) {
1173 case kPidFork:
1174 case kPidClone:
1175 // event->pid is the process id of the child
1176 if (event->pid >= kNumPids) {
1177 fprintf(stderr, "Error: pid (%d) too large\n", event->pid);
1178 exit(1);
1179 }
1180 // Create a new ProcessState struct for the child
1181 // and link it in at the front of the list for that
1182 // pid.
1183 {
1184 ProcessState *child = new ProcessState;
1185 processes_[event->pid] = child;
1186 child->pid = event->pid;
1187 child->tgid = event->tgid;
1188
1189 // Link the new child at the front of the list (only needed if
1190 // pids wrap around, which will probably never happen when
1191 // tracing because it would take so long).
1192 child->next = processes_[event->pid];
1193 child->parent_pid = current_->pid;
1194 child->parent = current_;
1195 child->start_time = event->time;
1196 child->name = Strdup(current_->name);
1197 if (event->rec_type == kPidFork) {
1198 CopyRegions(current_, child);
1199 } else {
1200 // Share the parent's address space
1201 child->flags |= ProcessState::kIsClone;
1202
1203 // The address space manager for the clone is the same
1204 // as the address space manager for the parent. This works
1205 // even if the child later clones itself.
1206 child->addr_manager = current_->addr_manager;
1207 }
1208 }
1209 break;
1210 case kPidSwitch:
1211 // event->pid is the process id of the process we are
1212 // switching to.
1213 {
1214 uint64_t elapsed = event->time - function_start_time_;
1215 function_start_time_ = event->time;
1216 current_->cpu_time += elapsed;
1217 }
1218 if (current_->flags & ProcessState::kCalledExit)
1219 current_->end_time = event->time;
1220
1221 if (event->pid >= kNumPids) {
1222 fprintf(stderr, "Error: pid (%d) too large\n", event->pid);
1223 exit(1);
1224 }
1225
1226 // If the process we are switching to does not exist, then
1227 // create one. This can happen because the tracing code does
1228 // not start tracing from the very beginning of the kernel.
1229 current_ = processes_[event->pid];
1230 if (current_ == NULL) {
1231 current_ = new ProcessState;
1232 processes_[event->pid] = current_;
1233 current_->pid = event->pid;
1234 current_->start_time = event->time;
1235 CopyKernelRegion(current_);
1236 }
1237 #if 0
1238 {
1239 printf("switching to p%d\n", current_->pid);
1240 ProcessState *manager = current_->addr_manager;
1241 for (int ii = 0; ii < manager->nregions; ++ii) {
1242 printf(" %08x - %08x offset: %d nsyms: %4d %s\n",
1243 manager->regions[ii]->vstart,
1244 manager->regions[ii]->vend,
1245 manager->regions[ii]->file_offset,
1246 manager->regions[ii]->nsymbols,
1247 manager->regions[ii]->path);
1248 }
1249 }
1250 #endif
1251 break;
1252 case kPidExit:
1253 current_->exit_val = event->pid;
1254 current_->flags |= ProcessState::kCalledExit;
1255 break;
1256 case kPidMunmap:
1257 FindAndRemoveRegion(current_, event->vstart, event->vend);
1258 break;
1259 case kPidMmap:
1260 {
1261 region_type *region;
1262 region_type *existing_region = hash_->Find(event->path);
1263 if (existing_region == NULL
1264 || existing_region->vstart != event->vstart
1265 || existing_region->vend != event->vend
1266 || existing_region->file_offset != event->offset) {
1267 // Create a new region and add it to the current process'
1268 // address space.
1269 region = new region_type;
1270
1271 // The event->path is allocated by ReadPidEvent() and owned
1272 // by us.
1273 region->path = event->path;
1274 region->vstart = event->vstart;
1275 region->vend = event->vend;
1276 region->file_offset = event->offset;
1277 if (existing_region == NULL) {
1278 DexFileList *dexfile = dex_hash_->Find(event->path);
1279 if (dexfile != NULL) {
1280 PopulateSymbolsFromDexFile(dexfile, region);
1281 } else {
1282 ReadElfSymbols(region, 0);
1283 }
1284 hash_->Update(region->path, region);
1285 } else {
1286 region->nsymbols = existing_region->nsymbols;
1287 region->symbols = existing_region->symbols;
1288 region->flags |= region_type::kSharedSymbols;
1289 }
1290
1291 // The base_addr is subtracted from an address before the
1292 // symbol name lookup and is either zero or event->vstart.
1293 // HACK: Determine if base_addr is non-zero by looking at the
1294 // second symbol address (skip the first symbol because that is
1295 // the special symbol "(unknown)" with an address of zero).
1296 if (region->nsymbols > 2 && region->symbols[1].addr < event->vstart)
1297 region->base_addr = event->vstart;
1298
1299 // Treat all mmapped regions after the first as "libraries".
1300 // Profiling tools can test for this property.
1301 if (current_->flags & ProcessState::kHasFirstMmap)
1302 region->flags |= region_type::kIsLibraryRegion;
1303 else
1304 current_->flags |= ProcessState::kHasFirstMmap;
1305 #if 0
1306 printf("%s vstart: 0x%x vend: 0x%x offset: 0x%x\n",
1307 region->path, region->vstart, region->vend, region->file_offset);
1308 #endif
1309 } else {
1310 region = existing_region;
1311 region->refs += 1;
1312 delete[] event->path;
1313 }
1314 AddRegion(current_, region);
1315 }
1316 break;
1317 case kPidExec:
1318 if (current_->argc > 0) {
1319 for (int ii = 0; ii < current_->argc; ii++) {
1320 delete[] current_->argv[ii];
1321 }
1322 delete[] current_->argv;
1323 }
1324 delete[] current_->name;
1325
1326 current_->argc = event->argc;
1327 current_->argv = event->argv;
1328 current_->name = Strdup(current_->argv[0]);
1329 current_->flags |= ProcessState::kCalledExec;
1330 ClearRegions(current_);
1331 break;
1332 case kPidName:
1333 case kPidKthreadName:
1334 {
1335 ProcessState *pstate = processes_[event->pid];
1336 if (pstate == NULL) {
1337 pstate = new ProcessState;
1338 if (event->rec_type == kPidKthreadName) {
1339 pstate->tgid = event->tgid;
1340 }
1341 pstate->pid = event->pid;
1342 pstate->start_time = event->time;
1343 processes_[event->pid] = pstate;
1344 CopyKernelRegion(pstate);
1345 } else {
1346 delete[] pstate->name;
1347 }
1348 pstate->name = event->path;
1349 }
1350 break;
1351 case kPidNoAction:
1352 break;
1353 case kPidSymbolAdd:
1354 delete[] event->path;
1355 break;
1356 case kPidSymbolRemove:
1357 break;
1358 }
1359 }
1360
1361 // Finds the current pid for the given time. This routine reads the pid
1362 // trace file and assumes that the "time" parameter is monotonically
1363 // increasing.
1364 template <class T>
FindCurrentPid(uint64_t time)1365 int TraceReader<T>::FindCurrentPid(uint64_t time)
1366 {
1367 if (time < next_pid_event_.time)
1368 return current_->pid;
1369
1370 while (1) {
1371 HandlePidEvent(&next_pid_event_);
1372
1373 if (internal_pid_reader_->ReadPidEvent(&next_pid_event_)) {
1374 next_pid_event_.time = ~0ull;
1375 break;
1376 }
1377 if (next_pid_event_.time > time)
1378 break;
1379 }
1380 return current_->pid;
1381 }
1382
1383 template <class T>
DumpStack(FILE * stream)1384 void TraceReader<T>::ProcessState::DumpStack(FILE *stream)
1385 {
1386 const char *native;
1387 for (int ii = 0; ii < method_stack_top; ii++) {
1388 native = method_stack[ii].isNative ? "n" : " ";
1389 fprintf(stream, "%2d: %s 0x%08x\n", ii, native, method_stack[ii].addr);
1390 }
1391 }
1392
1393 template <class T>
HandleMethodRecord(ProcessState * pstate,MethodRec * method_rec)1394 void TraceReader<T>::HandleMethodRecord(ProcessState *pstate,
1395 MethodRec *method_rec)
1396 {
1397 uint32_t addr;
1398 int top = pstate->method_stack_top;
1399 int flags = method_rec->flags;
1400 bool isNative;
1401 if (flags == kMethodEnter || flags == kNativeEnter) {
1402 // Push this method on the stack
1403 if (top >= pstate->kMaxMethodStackSize) {
1404 fprintf(stderr, "Stack overflow at time %llu\n", method_rec->time);
1405 exit(1);
1406 }
1407 pstate->method_stack[top].addr = method_rec->addr;
1408 isNative = (flags == kNativeEnter);
1409 pstate->method_stack[top].isNative = isNative;
1410 pstate->method_stack_top = top + 1;
1411 addr = method_rec->addr;
1412 } else {
1413 if (top <= 0) {
1414 // If the stack underflows, then set the current method to NULL.
1415 pstate->current_method_sym = NULL;
1416 return;
1417 }
1418 top -= 1;
1419 addr = pstate->method_stack[top].addr;
1420
1421 // If this is a non-native method then the address we are popping should
1422 // match the top-of-stack address. Native pops don't always match the
1423 // address of the native push for some reason.
1424 if (addr != method_rec->addr && !pstate->method_stack[top].isNative) {
1425 fprintf(stderr,
1426 "Stack method (0x%x) at index %d does not match trace record (0x%x) at time %llu\n",
1427 addr, top, method_rec->addr, method_rec->time);
1428 pstate->DumpStack(stderr);
1429 exit(1);
1430 }
1431
1432 // If we are popping a native method, then the top-of-stack should also
1433 // be a native method.
1434 bool poppingNative = (flags == kNativeExit) || (flags == kNativeException);
1435 if (poppingNative != pstate->method_stack[top].isNative) {
1436 fprintf(stderr,
1437 "Popping native vs. non-native mismatch at index %d time %llu\n",
1438 top, method_rec->time);
1439 pstate->DumpStack(stderr);
1440 exit(1);
1441 }
1442
1443 pstate->method_stack_top = top;
1444 if (top == 0) {
1445 // When we empty the stack, set the current method to NULL
1446 pstate->current_method_sym = NULL;
1447 return;
1448 }
1449 addr = pstate->method_stack[top - 1].addr;
1450 isNative = pstate->method_stack[top - 1].isNative;
1451 }
1452
1453 // If the top-of-stack is a native method, then set the current method
1454 // to NULL.
1455 if (isNative) {
1456 pstate->current_method_sym = NULL;
1457 return;
1458 }
1459
1460 ProcessState *manager = pstate->addr_manager;
1461 region_type *region = FindRegion(addr, manager->nregions, manager->regions);
1462 uint32_t sym_addr = addr - region->base_addr;
1463 symbol_type *sym = FindFunction(sym_addr, region->nsymbols,
1464 region->symbols, true /* exact match */);
1465
1466 pstate->current_method_sym = sym;
1467 if (sym != NULL) {
1468 sym->region = region;
1469 }
1470 }
1471
1472 // Returns the current top-of-stack Java method, if any, for the given pid
1473 // at the given time. The "time" parameter must be monotonically increasing
1474 // across successive calls to this method.
1475 // If the Java method stack is empty or if a native JNI method is on the
1476 // top of the stack, then this method returns NULL.
1477 template <class T>
1478 typename TraceReader<T>::symbol_type*
FindCurrentMethod(int pid,uint64_t time)1479 TraceReader<T>::FindCurrentMethod(int pid, uint64_t time)
1480 {
1481 ProcessState *procState = processes_[pid];
1482
1483 if (time < next_method_.time) {
1484 return procState->current_method_sym;
1485 }
1486
1487 while (1) {
1488 if (next_method_.time != 0) {
1489 // We may have to process methods from a different pid so use
1490 // a local variable here so that we don't overwrite procState.
1491 ProcessState *pState = processes_[next_method_.pid];
1492 HandleMethodRecord(pState, &next_method_);
1493 }
1494
1495 if (internal_method_reader_->ReadMethod(&next_method_)) {
1496 next_method_.time = ~0ull;
1497 break;
1498 }
1499 if (next_method_.time > time)
1500 break;
1501 }
1502 return procState->current_method_sym;
1503 }
1504
1505 template <class T>
PopulateSymbolsFromDexFile(const DexFileList * dexfile,region_type * region)1506 void TraceReader<T>::PopulateSymbolsFromDexFile(const DexFileList *dexfile,
1507 region_type *region)
1508
1509 {
1510 int nsymbols = dexfile->nsymbols;
1511 DexSym *dexsyms = dexfile->symbols;
1512 region->nsymbols = nsymbols + 1;
1513 symbol_type *symbols = new symbol_type[nsymbols + 1];
1514 memset(symbols, 0, (nsymbols + 1) * sizeof(symbol_type));
1515 region->symbols = symbols;
1516 for (int ii = 0; ii < nsymbols; ii++) {
1517 symbols[ii].addr = dexsyms[ii].addr;
1518 symbols[ii].name = Strdup(dexsyms[ii].name);
1519 symbols[ii].vm_sym = NULL;
1520 symbols[ii].region = region;
1521 symbols[ii].flags = symbol_type::kIsMethod;
1522 }
1523
1524 // Add an entry at the end with an address of 0xffffffff. This
1525 // is required for LookupFunction() to work.
1526 symbol_type *symbol = &symbols[nsymbols];
1527 symbol->addr = 0xffffffff;
1528 symbol->name = Strdup("(end)");
1529 symbol->vm_sym = NULL;
1530 symbol->region = region;
1531 symbol->flags = symbol_type::kIsMethod;
1532 }
1533
1534 template <class T>
ReadMethodSymbol(MethodRec * method_record,symbol_type ** psym,ProcessState ** pproc)1535 bool TraceReader<T>::ReadMethodSymbol(MethodRec *method_record,
1536 symbol_type **psym,
1537 ProcessState **pproc)
1538 {
1539 if (internal_method_reader_->ReadMethod(&next_method_)) {
1540 return true;
1541 }
1542
1543 // Copy the whole MethodRec struct
1544 *method_record = next_method_;
1545
1546 uint64_t time = next_method_.time;
1547
1548 // Read the pid trace file up to this point to make sure the
1549 // process state is valid.
1550 FindCurrentPid(time);
1551
1552 ProcessState *pstate = processes_[next_method_.pid];
1553 *pproc = pstate;
1554 HandleMethodRecord(pstate, &next_method_);
1555 *psym = pstate->current_method_sym;
1556 return false;
1557 }
1558
1559 #endif /* TRACE_READER_H */
1560