• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file. */
4 
5 /* XRay symbol table */
6 
7 #define _GNU_SOURCE
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #if defined(__GLIBC__)
14 #include <dlfcn.h>
15 #endif
16 
17 #include "xray/xray_priv.h"
18 #define PNACL_STRING_OFFSET (0x10000000)
19 
20 #if defined(XRAY)
21 
22 bool g_symtable_debug = false;
23 
24 struct XRayFrameInfo {
25   int times_called;
26   int total_ticks;
27 };
28 
29 
30 struct XRaySymbol {
31   const char* name;
32   struct XRayFrameInfo frames[XRAY_MAX_FRAMES];
33 };
34 
35 
36 struct XRaySymbolPoolNode {
37   struct XRaySymbolPoolNode* next;
38   struct XRaySymbol symbols[XRAY_SYMBOL_POOL_NODE_SIZE];
39 };
40 
41 
42 struct XRaySymbolPool {
43   struct XRaySymbolPoolNode* head;
44   struct XRaySymbolPoolNode* current;
45   int index;
46 };
47 
48 
49 struct XRaySymbolTable {
50   int num_symbols;
51   struct XRayHashTable* hash_table;
52   struct XRayStringPool* string_pool;
53   struct XRaySymbolPool* symbol_pool;
54 };
55 
56 
XRaySymbolGetName(struct XRaySymbol * symbol)57 const char* XRaySymbolGetName(struct XRaySymbol* symbol) {
58   return (NULL == symbol) ? "(null)" : symbol->name;
59 }
60 
61 
XRaySymbolCreate(struct XRaySymbolPool * sympool,const char * name)62 struct XRaySymbol* XRaySymbolCreate(struct XRaySymbolPool* sympool,
63                                     const char* name)
64 {
65   struct XRaySymbol* symbol;
66   symbol = XRaySymbolPoolAlloc(sympool);
67   symbol->name = name;
68   return symbol;
69 }
70 
71 
XRaySymbolPoolAlloc(struct XRaySymbolPool * sympool)72 struct XRaySymbol* XRaySymbolPoolAlloc(struct XRaySymbolPool* sympool) {
73   struct XRaySymbol* symbol;
74   if (sympool->index >= XRAY_SYMBOL_POOL_NODE_SIZE) {
75     struct XRaySymbolPoolNode* new_pool;
76     new_pool = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*new_pool));
77     sympool->current->next = new_pool;
78     sympool->current = new_pool;
79     sympool->index = 0;
80   }
81   symbol = &sympool->current->symbols[sympool->index];
82   ++sympool->index;
83   return symbol;
84 }
85 
86 
XRaySymbolPoolCreate()87 struct XRaySymbolPool* XRaySymbolPoolCreate() {
88   struct XRaySymbolPool* sympool;
89   struct XRaySymbolPoolNode* node;
90   sympool = (struct XRaySymbolPool*)XRayMalloc(sizeof(*sympool));
91   node = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*node));
92   sympool->head = node;
93   sympool->current = node;
94   sympool->index = 0;
95   return sympool;
96 }
97 
98 
XRaySymbolPoolFree(struct XRaySymbolPool * pool)99 void XRaySymbolPoolFree(struct XRaySymbolPool* pool) {
100   struct XRaySymbolPoolNode* n = pool->head;
101   while (NULL != n) {
102     struct XRaySymbolPoolNode* c = n;
103     n = n->next;
104     XRayFree(c);
105   }
106   XRayFree(pool);
107 }
108 
109 
XRaySymbolTableGetCount(struct XRaySymbolTable * symtab)110 int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) {
111   return XRayHashTableGetCount(symtab->hash_table);
112 }
113 
114 
XRaySymbolTableAtIndex(struct XRaySymbolTable * symtab,int i)115 struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab,
116                                           int i) {
117   return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i);
118 }
119 
XRaySymbolTableAdd(struct XRaySymbolTable * symtab,struct XRaySymbol * symbol,uint32_t addr)120 struct XRaySymbol* XRaySymbolTableAdd(struct XRaySymbolTable* symtab,
121                                       struct XRaySymbol* symbol,
122                                       uint32_t addr) {
123   struct XRaySymbol* sym = (struct XRaySymbol*)
124       XRayHashTableInsert(symtab->hash_table, symbol, addr);
125   symtab->num_symbols = XRayHashTableGetCount(symtab->hash_table);
126   return sym;
127 }
128 
XRaySymbolTableAddByName(struct XRaySymbolTable * symtab,const char * name,uint32_t addr)129 struct XRaySymbol* XRaySymbolTableAddByName(struct XRaySymbolTable* symtab,
130                                             const char* name, uint32_t addr) {
131   char* recorded_name;
132   struct XRaySymbol* symbol;
133   char buffer[XRAY_LINE_SIZE];
134   const char* demangled_name = XRayDemangle(buffer, XRAY_LINE_SIZE, name);
135   /* record the demangled symbol name into the string pool */
136   recorded_name = XRayStringPoolAppend(symtab->string_pool, demangled_name);
137   if (g_symtable_debug)
138     printf("adding symbol %s\n", recorded_name);
139   /* construct a symbol and put it in the symbol table */
140   symbol = XRaySymbolCreate(symtab->symbol_pool, recorded_name);
141   return XRaySymbolTableAdd(symtab, symbol, addr);
142 }
143 
XRaySymbolTableLookup(struct XRaySymbolTable * symtab,uint32_t addr)144 struct XRaySymbol* XRaySymbolTableLookup(struct XRaySymbolTable* symtab,
145                                          uint32_t addr) {
146   void *x = XRayHashTableLookup(symtab->hash_table, addr);
147   struct XRaySymbol* r = (struct XRaySymbol*)x;
148 
149 #if defined(__pnacl__)
150   if (r == NULL) {
151     /* Addresses are trimed to 24 bits for internal storage, so we need to
152      * add this offset back in order to get the real address.
153      */
154     addr |= PNACL_STRING_OFFSET;
155     const char* name = (const char*)addr;
156     struct XRaySymbol* symbol = XRaySymbolCreate(symtab->symbol_pool, name);
157     r = XRaySymbolTableAdd(symtab, symbol, addr);
158   }
159 #endif
160 
161 #if defined(__GLIBC__)
162   if (r == NULL) {
163     Dl_info info;
164     if (dladdr((const void*)addr, &info) != 0)
165       if (info.dli_sname)
166         r = XRaySymbolTableAddByName(symtab, info.dli_sname, addr);
167   }
168 #endif
169   return r;
170 }
171 
172 
173 /* Returns total number of symbols in the table. */
XRaySymbolCount(struct XRaySymbolTable * symtab)174 int XRaySymbolCount(struct XRaySymbolTable* symtab) {
175   return symtab->num_symbols;
176 }
177 
178 
179 /* Creates and inializes a symbol table. */
XRaySymbolTableCreate(int size)180 struct XRaySymbolTable* XRaySymbolTableCreate(int size) {
181   struct XRaySymbolTable* symtab;
182   symtab = (struct XRaySymbolTable*)XRayMalloc(sizeof(*symtab));
183   symtab->num_symbols = 0;
184   symtab->string_pool = XRayStringPoolCreate();
185   symtab->hash_table = XRayHashTableCreate(size);
186   symtab->symbol_pool = XRaySymbolPoolCreate();
187   return symtab;
188 }
189 
190 
191 /* Frees a symbol table. */
XRaySymbolTableFree(struct XRaySymbolTable * symtab)192 void XRaySymbolTableFree(struct XRaySymbolTable* symtab) {
193   XRayStringPoolFree(symtab->string_pool);
194   XRaySymbolPoolFree(symtab->symbol_pool);
195   XRayHashTableFree(symtab->hash_table);
196   symtab->num_symbols = 0;
197   XRayFree(symtab);
198 }
199 
200 #endif  /* XRAY */
201