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 57 const char* XRaySymbolGetName(struct XRaySymbol* symbol) { 58 return (NULL == symbol) ? "(null)" : symbol->name; 59 } 60 61 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 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 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 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 110 int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) { 111 return XRayHashTableGetCount(symtab->hash_table); 112 } 113 114 115 struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab, 116 int i) { 117 return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i); 118 } 119 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 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 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. */ 174 int XRaySymbolCount(struct XRaySymbolTable* symtab) { 175 return symtab->num_symbols; 176 } 177 178 179 /* Creates and inializes a symbol table. */ 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. */ 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