/* 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 #include #include #include #if defined(__GLIBC__) #include #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 */