IgHook_IgHookTrace.cpp
Go to the documentation of this file.00001
00002
00003 #include "IgHook_IgHookTrace.h"
00004 #include <cstdlib>
00005 #include <cstdio>
00006 #include <dlfcn.h>
00007 #include <unistd.h>
00008 #include <sys/mman.h>
00009 #if __linux
00010 # include <execinfo.h>
00011 # include <ucontext.h>
00012 # include <sys/syscall.h>
00013 # if __x86_64__
00014 # define UNW_LOCAL_ONLY
00015 # include <libunwind.h>
00016 # endif
00017 #endif
00018 #if __APPLE__
00019 extern "C" void _sigtramp (void);
00020 #endif
00021
00022
00023
00024 #if !defined MAP_ANONYMOUS && defined MAP_ANON
00025 # define MAP_ANONYMOUS MAP_ANON
00026 #endif
00027
00028
00029
00030
00031
00032
00033
00034
00035 #if 0 && __x86_64__ && __linux
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 struct IgHookTraceArgs
00065 {
00066 struct
00067 {
00068 void **pc;
00069 int **frame;
00070 } cache;
00071 struct
00072 {
00073 void **addresses;
00074 int top;
00075 int size;
00076 } stack;
00077 void **prevframe;
00078 };
00079
00080 static _Unwind_Reason_Code
00081 GCCBackTrace (_Unwind_Context *context, void *arg)
00082 {
00083 IgHookTraceArgs *args = (IgHookTraceArgs *) arg;
00084 if (args->stack.top < 0 || args->stack.top >= args->stack.size)
00085 return _URC_END_OF_STACK;
00086
00087 args->stack.addresses [args->stack.top++] = (void *) _Unwind_GetIP (context);
00088 args->prevframe = (void **) _Unwind_GetCFA (context);
00089 return _URC_NO_REASON;
00090 }
00091 #endif
00092
00093
00094
00095
00099 IgHookTraceAlloc::IgHookTraceAlloc (void)
00100 : m_pool (0),
00101 m_left (0)
00102 {}
00103
00104 void *
00105 IgHookTraceAlloc::allocate (size_t bytes)
00106 {
00107
00108
00109
00110
00111
00112
00113
00114 if (m_left < bytes)
00115 {
00116 size_t psize = getpagesize ();
00117 size_t hunk = psize * 20;
00118 if (hunk < bytes) hunk = (hunk + psize - 1) & ~(psize-1);
00119 void *addr = mmap (0, hunk, PROT_READ | PROT_WRITE,
00120 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
00121 if (addr == MAP_FAILED)
00122 return 0;
00123
00124 m_pool = addr;
00125 m_left = hunk;
00126 }
00127
00128 void *ptr = m_pool;
00129 m_pool = (char *) m_pool + bytes;
00130 m_left -= bytes;
00131 return ptr;
00132 }
00133
00137 void *
00138 IgHookTrace::CounterValue::operator new (size_t n, IgHookTraceAlloc *alloc )
00139 { return alloc ? alloc->allocate (n) : ::operator new (n); }
00140
00141 IgHookTrace::CounterValue::CounterValue (Counter *counter,
00142 CounterValue *next ,
00143 unsigned long long value )
00144 : m_counter (counter),
00145 m_next (next),
00146 m_value (value),
00147 m_count (0)
00148 {}
00149
00150 IgHookTrace::Counter *
00151 IgHookTrace::CounterValue::counter (void)
00152 { return m_counter; }
00153
00154 IgHookTrace::CounterValue *
00155 IgHookTrace::CounterValue::next (void)
00156 { return m_next; }
00157
00158 unsigned long long
00159 IgHookTrace::CounterValue::value (void)
00160 { return m_value; }
00161
00162 unsigned long long
00163 IgHookTrace::CounterValue::count (void)
00164 { return m_count; }
00165
00166 unsigned long long
00167 IgHookTrace::CounterValue::tick (void)
00168 { ++m_count; return ++m_value; }
00169
00170 unsigned long long
00171 IgHookTrace::CounterValue::untick (void)
00172 { --m_count; return --m_value; }
00173
00174 unsigned long long
00175 IgHookTrace::CounterValue::add (unsigned long long value)
00176 { ++m_count; return m_value += value; }
00177
00178 unsigned long long
00179 IgHookTrace::CounterValue::sub (unsigned long long value)
00180 { --m_count; return m_value -= value; }
00181
00182 unsigned long long
00183 IgHookTrace::CounterValue::max (unsigned long long value)
00184 { ++m_count; if (m_value < value) m_value = value; return m_value; }
00185
00186 unsigned long long
00187 IgHookTrace::CounterValue::add (CounterValue &x)
00188 { m_count += x.m_count; m_value += x.m_value; return m_value; }
00189
00190 unsigned long long
00191 IgHookTrace::CounterValue::sub (CounterValue &x)
00192 { m_count -= x.m_count; m_value -= x.m_value; return m_value; }
00193
00194 unsigned long long
00195 IgHookTrace::CounterValue::max (CounterValue &x)
00196 { m_count += x.m_count; if (m_value < x.m_value) m_value = x.m_value; return m_value; }
00197
00201 void *
00202 IgHookTrace::operator new (size_t n, IgHookTraceAlloc *alloc )
00203 { return alloc ? alloc->allocate (n) : ::operator new (n); }
00204
00205 IgHookTrace::IgHookTrace (IgHookTrace *parent , void *address )
00206 : m_alloc (parent ? parent->m_alloc : new IgHookTraceAlloc),
00207 m_parent (parent),
00208 m_next (parent ? parent->m_children : 0),
00209 m_children (0),
00210 m_address (address),
00211 m_counters (0)
00212 { if (m_parent) m_parent->m_children = this; }
00213
00214 IgHookTrace *
00215 IgHookTrace::parent (void)
00216 { return m_parent; }
00217
00218 IgHookTrace *
00219 IgHookTrace::next (void)
00220 { return m_next; }
00221
00222 void *
00223 IgHookTrace::address (void)
00224 { return m_address; }
00225
00226 bool
00227 IgHookTrace::symbol (void *address,
00228 const char *&sym,
00229 const char *&lib,
00230 int &offset,
00231 int &liboffset)
00232 {
00233 sym = lib = 0;
00234 offset = 0;
00235 liboffset = (unsigned long) address;
00236
00237 Dl_info info;
00238 if (dladdr (address, &info))
00239 {
00240 if (info.dli_fname && info.dli_fname [0])
00241 lib = info.dli_fname;
00242
00243 if (info.dli_fbase)
00244 liboffset = (unsigned long) address - (unsigned long) info.dli_fbase;
00245
00246 if (info.dli_saddr)
00247 offset = (unsigned long) address - (unsigned long) info.dli_saddr;
00248
00249 if (info.dli_sname && info.dli_sname [0])
00250 sym = info.dli_sname;
00251
00252 return true;
00253 }
00254
00255 return false;
00256 }
00257
00258 bool
00259 IgHookTrace::symbol (const char *&sym, const char *&lib, int &offset, int &liboffset)
00260 { return symbol (m_address, sym, lib, offset, liboffset); }
00261
00262 void *
00263 IgHookTrace::tosymbol (void *address)
00264 {
00265 Dl_info info;
00266 return (dladdr (address, &info)
00267 && info.dli_fname
00268 && info.dli_fname [0]
00269 && info.dli_saddr)
00270 ? info.dli_saddr : address;
00271 }