2016-05-18 00:24:42 +02:00
|
|
|
/* 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
|
|
|
|
|
2016-05-18 00:35:35 +02:00
|
|
|
#include "xray_priv.h"
|
2016-05-18 00:24:42 +02:00
|
|
|
#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 */
|