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