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 53 region_entry() : refs(0), path(NULL), vstart(0), vend(0), base_addr(0), 54 file_offset(0), flags(0), nsymbols(0), symbols(NULL) {} 55 56 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 65 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 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 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); 208 ProcessState *GetCurrentProcess() { return current_; } 209 ProcessState *GetProcesses(int *num_procs); 210 ProcessState *GetNextProcess(); 211 const char *GetProcessName(int pid); 212 void SetRoot(const char *root) { root_ = root; } 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> 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> 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> 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> 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* 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* 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* 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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 * 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> 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 * 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 * 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> 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> 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> 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> 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* 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> 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> 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