| /* Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. */ |
| |
| /* XRay symbol table */ |
| |
| #define _GNU_SOURCE |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #if defined(__GLIBC__) |
| #include <dlfcn.h> |
| #endif |
| |
| #include "xray/xray_priv.h" |
| #define PNACL_STRING_OFFSET (0x10000000) |
| |
| #if defined(XRAY) |
| |
| bool g_symtable_debug = false; |
| |
| struct XRayFrameInfo { |
| int times_called; |
| int total_ticks; |
| }; |
| |
| |
| struct XRaySymbol { |
| const char* name; |
| struct XRayFrameInfo frames[XRAY_MAX_FRAMES]; |
| }; |
| |
| |
| struct XRaySymbolPoolNode { |
| struct XRaySymbolPoolNode* next; |
| struct XRaySymbol symbols[XRAY_SYMBOL_POOL_NODE_SIZE]; |
| }; |
| |
| |
| struct XRaySymbolPool { |
| struct XRaySymbolPoolNode* head; |
| struct XRaySymbolPoolNode* current; |
| int index; |
| }; |
| |
| |
| struct XRaySymbolTable { |
| int num_symbols; |
| struct XRayHashTable* hash_table; |
| struct XRayStringPool* string_pool; |
| struct XRaySymbolPool* symbol_pool; |
| }; |
| |
| |
| const char* XRaySymbolGetName(struct XRaySymbol* symbol) { |
| return (NULL == symbol) ? "(null)" : symbol->name; |
| } |
| |
| |
| struct XRaySymbol* XRaySymbolCreate(struct XRaySymbolPool* sympool, |
| const char* name) |
| { |
| struct XRaySymbol* symbol; |
| symbol = XRaySymbolPoolAlloc(sympool); |
| symbol->name = name; |
| return symbol; |
| } |
| |
| |
| struct XRaySymbol* XRaySymbolPoolAlloc(struct XRaySymbolPool* sympool) { |
| struct XRaySymbol* symbol; |
| if (sympool->index >= XRAY_SYMBOL_POOL_NODE_SIZE) { |
| struct XRaySymbolPoolNode* new_pool; |
| new_pool = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*new_pool)); |
| sympool->current->next = new_pool; |
| sympool->current = new_pool; |
| sympool->index = 0; |
| } |
| symbol = &sympool->current->symbols[sympool->index]; |
| ++sympool->index; |
| return symbol; |
| } |
| |
| |
| struct XRaySymbolPool* XRaySymbolPoolCreate() { |
| struct XRaySymbolPool* sympool; |
| struct XRaySymbolPoolNode* node; |
| sympool = (struct XRaySymbolPool*)XRayMalloc(sizeof(*sympool)); |
| node = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*node)); |
| sympool->head = node; |
| sympool->current = node; |
| sympool->index = 0; |
| return sympool; |
| } |
| |
| |
| void XRaySymbolPoolFree(struct XRaySymbolPool* pool) { |
| struct XRaySymbolPoolNode* n = pool->head; |
| while (NULL != n) { |
| struct XRaySymbolPoolNode* c = n; |
| n = n->next; |
| XRayFree(c); |
| } |
| XRayFree(pool); |
| } |
| |
| |
| int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) { |
| return XRayHashTableGetCount(symtab->hash_table); |
| } |
| |
| |
| struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab, |
| int i) { |
| return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i); |
| } |
| |
| struct XRaySymbol* XRaySymbolTableAdd(struct XRaySymbolTable* symtab, |
| struct XRaySymbol* symbol, |
| uint32_t addr) { |
| struct XRaySymbol* sym = (struct XRaySymbol*) |
| XRayHashTableInsert(symtab->hash_table, symbol, addr); |
| symtab->num_symbols = XRayHashTableGetCount(symtab->hash_table); |
| return sym; |
| } |
| |
| struct XRaySymbol* XRaySymbolTableAddByName(struct XRaySymbolTable* symtab, |
| const char* name, uint32_t addr) { |
| char* recorded_name; |
| struct XRaySymbol* symbol; |
| char buffer[XRAY_LINE_SIZE]; |
| const char* demangled_name = XRayDemangle(buffer, XRAY_LINE_SIZE, name); |
| /* record the demangled symbol name into the string pool */ |
| recorded_name = XRayStringPoolAppend(symtab->string_pool, demangled_name); |
| if (g_symtable_debug) |
| printf("adding symbol %s\n", recorded_name); |
| /* construct a symbol and put it in the symbol table */ |
| symbol = XRaySymbolCreate(symtab->symbol_pool, recorded_name); |
| return XRaySymbolTableAdd(symtab, symbol, addr); |
| } |
| |
| struct XRaySymbol* XRaySymbolTableLookup(struct XRaySymbolTable* symtab, |
| uint32_t addr) { |
| void *x = XRayHashTableLookup(symtab->hash_table, addr); |
| struct XRaySymbol* r = (struct XRaySymbol*)x; |
| |
| #if defined(__pnacl__) |
| if (r == NULL) { |
| /* Addresses are trimed to 24 bits for internal storage, so we need to |
| * add this offset back in order to get the real address. |
| */ |
| addr |= PNACL_STRING_OFFSET; |
| const char* name = (const char*)addr; |
| struct XRaySymbol* symbol = XRaySymbolCreate(symtab->symbol_pool, name); |
| r = XRaySymbolTableAdd(symtab, symbol, addr); |
| } |
| #endif |
| |
| #if defined(__GLIBC__) |
| if (r == NULL) { |
| Dl_info info; |
| if (dladdr((const void*)addr, &info) != 0) |
| if (info.dli_sname) |
| r = XRaySymbolTableAddByName(symtab, info.dli_sname, addr); |
| } |
| #endif |
| return r; |
| } |
| |
| |
| /* Returns total number of symbols in the table. */ |
| int XRaySymbolCount(struct XRaySymbolTable* symtab) { |
| return symtab->num_symbols; |
| } |
| |
| |
| /* Creates and inializes a symbol table. */ |
| struct XRaySymbolTable* XRaySymbolTableCreate(int size) { |
| struct XRaySymbolTable* symtab; |
| symtab = (struct XRaySymbolTable*)XRayMalloc(sizeof(*symtab)); |
| symtab->num_symbols = 0; |
| symtab->string_pool = XRayStringPoolCreate(); |
| symtab->hash_table = XRayHashTableCreate(size); |
| symtab->symbol_pool = XRaySymbolPoolCreate(); |
| return symtab; |
| } |
| |
| |
| /* Frees a symbol table. */ |
| void XRaySymbolTableFree(struct XRaySymbolTable* symtab) { |
| XRayStringPoolFree(symtab->string_pool); |
| XRaySymbolPoolFree(symtab->symbol_pool); |
| XRayHashTableFree(symtab->hash_table); |
| symtab->num_symbols = 0; |
| XRayFree(symtab); |
| } |
| |
| #endif /* XRAY */ |