00001 #include "IgTools/IgProf/src/IgProfSymCache.h"
00002 #include "IgTools/IgHook/interface/IgHookTrace.h"
00003 #include <memory.h>
00004
00006 IgProfSymCache::IgProfSymCache(void)
00007 {
00008 memset(bintable_, 0, sizeof(bintable_));
00009 memset(symtable_, 0, sizeof(symtable_));
00010 memset(symcache_, 0, sizeof(symcache_));
00011 }
00012
00014 IgProfSymCache::~IgProfSymCache(void)
00015 {}
00016
00018 IgProfSymCache::Symbol *
00019 IgProfSymCache::symbolForAddress(void *address)
00020 {
00021 Symbol *sym = symtable_[hash((uintptr_t) address) & (SYMBOL_HASH-1)];
00022 while (sym)
00023 {
00024 if (sym->address == address)
00025 return sym;
00026 if ((char *) sym->address > (char *) address)
00027 return 0;
00028 sym = sym->next;
00029 }
00030
00031 return 0;
00032 }
00033
00034 void *
00035 IgProfSymCache::roundAddressToSymbol(void *address)
00036 {
00037
00038 void *symaddr = address;
00039 SymCache **sclink = &symcache_[hash((uintptr_t) address) & (SYMBOL_HASH-1)];
00040 SymCache *cached;
00041 while (cached = *sclink)
00042 {
00043
00044 if (cached->calladdr == address)
00045 return cached->symaddr;
00046 if ((char *) cached->calladdr > (char *) address)
00047 break;
00048 sclink = &cached->next;
00049 }
00050
00051
00052
00053
00054
00055 const char *binary;
00056 Symbol sym = { 0, address, 0, 0, 0, 0, -1 };
00057 Symbol *s;
00058 if (IgHookTrace::symbol(address, sym.name, binary, sym.symoffset, sym.binoffset))
00059 sym.address = symaddr = (void *) ((uintptr_t) address - sym.symoffset);
00060
00061
00062 SymCache *next = *sclink;
00063 cached = *sclink = allocate<SymCache>();
00064 cached->next = next;
00065 cached->calladdr = address;
00066 cached->symaddr = symaddr;
00067
00068
00069 bool found = false;
00070 Symbol **slink = &symtable_[hash((uintptr_t) symaddr) & (SYMBOL_HASH-1)];
00071 while (s = *slink)
00072 {
00073 if (s->address == sym.address)
00074 {
00075 found = true;
00076 break;
00077 }
00078 else if ((char *) s->address > (char *) sym.address)
00079 break;
00080
00081 slink = &s->next;
00082 }
00083
00084
00085 if (! found)
00086 {
00087
00088 sym.next = *slink;
00089 s = *slink = allocate<Symbol>();
00090 *s = sym;
00091
00092
00093 Binary **blink = &bintable_[hash((uintptr_t) binary) & (BINARY_HASH-1)];
00094 while (Binary *binobj = *blink)
00095 {
00096 if (binobj->name == binary)
00097 {
00098 s->binary = *blink;
00099 break;
00100 }
00101 blink = &binobj->next;
00102 }
00103
00104 if (! s->binary)
00105 {
00106 Binary *binobj = *blink = s->binary = allocate<Binary>();
00107 binobj->name = binary;
00108 binobj->next = 0;
00109 binobj->id = -1;
00110 }
00111 }
00112
00113
00114 return cached->symaddr;
00115 }
00116
00118 IgProfSymCache::Symbol *
00119 IgProfSymCache::get(void *address)
00120 {
00121 return symbolForAddress(roundAddressToSymbol(address));
00122 }