Home | History | Annotate | Download | only in xray
      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