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