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