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 22bool g_symtable_debug = false; 23 24struct XRayFrameInfo { 25 int times_called; 26 int total_ticks; 27}; 28 29 30struct XRaySymbol { 31 const char* name; 32 struct XRayFrameInfo frames[XRAY_MAX_FRAMES]; 33}; 34 35 36struct XRaySymbolPoolNode { 37 struct XRaySymbolPoolNode* next; 38 struct XRaySymbol symbols[XRAY_SYMBOL_POOL_NODE_SIZE]; 39}; 40 41 42struct XRaySymbolPool { 43 struct XRaySymbolPoolNode* head; 44 struct XRaySymbolPoolNode* current; 45 int index; 46}; 47 48 49struct XRaySymbolTable { 50 int num_symbols; 51 struct XRayHashTable* hash_table; 52 struct XRayStringPool* string_pool; 53 struct XRaySymbolPool* symbol_pool; 54}; 55 56 57const char* XRaySymbolGetName(struct XRaySymbol* symbol) { 58 return (NULL == symbol) ? "(null)" : symbol->name; 59} 60 61 62struct 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 72struct 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 87struct 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 99void 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 110int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) { 111 return XRayHashTableGetCount(symtab->hash_table); 112} 113 114 115struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab, 116 int i) { 117 return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i); 118} 119 120struct 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 129struct 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 144struct 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. */ 174int XRaySymbolCount(struct XRaySymbolTable* symtab) { 175 return symtab->num_symbols; 176} 177 178 179/* Creates and inializes a symbol table. */ 180struct 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. */ 192void 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