00001
00002
00003 #include "IgTools/IgTrace/src/IgTrace.h"
00004 #include "IgTools/IgHook/interface/IgHook.h"
00005 #include "IgTools/IgHook/interface/IgHookTrace.h"
00006 #include <typeinfo>
00007 #include <cxxabi.h>
00008 #include <cstdlib>
00009 #include <cstring>
00010 #include <cstdio>
00011 #include <cctype>
00012 #include <cstdarg>
00013 #include <pthread.h>
00014 #include <unistd.h>
00015 #include <cxxabi.h>
00016
00017
00018
00019
00020
00021 class IgTraceMMap
00022 {
00023 public:
00024 static void initialize (void);
00025 };
00026
00027
00028
00029
00030
00031
00032
00033 IGTRACE_HOOK (2, int, domunmap, _main,
00034 (void *addr, size_t len),
00035 (addr, len),
00036 "munmap")
00037 IGTRACE_HOOK (6, void *, dommap32, _main,
00038 (void *addr, size_t len, int prot, int flags, int fd, __off_t off),
00039 (addr, len, prot, flags, fd, off),
00040 "mmap")
00041 IGTRACE_HOOK (6, void *, dommap64, _main,
00042 (void *addr, size_t len, int prot, int flags, int fd, __off64_t off),
00043 (addr, len, prot, flags, fd, off),
00044 "mmap64")
00045
00046
00047 static bool s_initialized = false;
00048 static bool s_demangle = false;
00049 static char *s_demanglehere = 0;
00050 static size_t s_demanglelen = 0;
00051 static pthread_mutex_t s_demanglelock = PTHREAD_MUTEX_INITIALIZER;
00052
00053
00054
00055
00056
00059 void
00060 IgTraceMMap::initialize (void)
00061 {
00062 if (s_initialized) return;
00063
00064 s_demanglelen = 1024*1024-32;
00065 if (! (s_demanglehere = (char *) malloc (s_demanglelen)))
00066 return;
00067
00068 const char *options = IgTrace::options ();
00069 bool enable = false;
00070
00071 while (options && *options)
00072 {
00073 while (*options == ' ' || *options == ',')
00074 ++options;
00075
00076 if (! strncmp (options, "mmap", 4))
00077 {
00078 enable = true;
00079 options += 4;
00080 }
00081 else if (! strncmp (options, "demangle", 8))
00082 {
00083 s_demangle = true;
00084 options += 8;
00085 }
00086 else
00087 options++;
00088
00089 while (*options && *options != ',' && *options != ' ')
00090 options++;
00091 }
00092
00093 if (! enable)
00094 return;
00095
00096 if (! IgTrace::initialize ())
00097 return;
00098
00099 IgTrace::disable ();
00100 IgHook::hook (domunmap_hook_main.raw);
00101 IgHook::hook (dommap32_hook_main.raw);
00102 IgHook::hook (dommap64_hook_main.raw);
00103 IgTrace::debug ("Tracing memory mappings\n");
00104 s_initialized = true;
00105 IgTrace::enable ();
00106 }
00107
00109
00110
00111 static const int ZEROPAD = 1;
00112 static const int LEFT = 2;
00113 static const int SIGN = 4;
00114
00115 static int
00116 xatoi(const char **s)
00117 {
00118 int i = 0;
00119 while (isdigit (**s))
00120 i = i*10 + *((*s)++) - '0';
00121 return i;
00122 }
00123
00124 static char *
00125 xntoa(char *cur, char *end, unsigned long long num,
00126 int base, int width, int precision, int flags)
00127 {
00128 static const char digits[] = "0123456789abcdef";
00129
00130 if (flags & LEFT)
00131 flags &= ~ZEROPAD;
00132
00133 char sign = 0;
00134 if ((flags & SIGN) && (signed long long) num < 0)
00135 {
00136 num = - (signed long long) num;
00137 sign = '-';
00138 --width;
00139 }
00140
00141 int i = 0;
00142 char tmp [66];
00143 if (num == 0)
00144 tmp[i++] = '0';
00145 else
00146 do
00147 {
00148 lldiv_t x = lldiv(num, base);
00149 tmp[i++] = digits[x.rem];
00150 num = x.quot;
00151 } while (num != 0);
00152
00153 if (i > precision)
00154 precision = i;
00155
00156 width -= precision;
00157 if (! (flags & (ZEROPAD|LEFT)))
00158 for ( ; --width >= 0; ++cur)
00159 if (cur < end)
00160 *cur = ' ';
00161
00162 if (sign)
00163 {
00164 if (cur < end)
00165 *cur = sign;
00166 ++cur;
00167 }
00168
00169 if (! (flags & LEFT))
00170 {
00171 char c = (flags & ZEROPAD) ? '0' : ' ';
00172 for ( ; --width >= 0; ++cur)
00173 if (cur < end)
00174 *cur = c;
00175 }
00176
00177 for ( ; i <= --precision; ++cur)
00178 if (cur < end)
00179 *cur = '0';
00180
00181 for ( ; --i >= 0; ++cur)
00182 if (cur < end)
00183 *cur = tmp[i];
00184
00185 for ( ; --width >= 0; ++cur)
00186 if (cur < end)
00187 *cur = ' ';
00188
00189 return cur;
00190 }
00191
00192 static int
00193 xsprintf(char *buf, size_t len, const char *format, ...)
00194 {
00195 va_list args;
00196 char *cur = buf;
00197 char *end = buf + len;
00198
00199 va_start(args, format);
00200 for (; *format; ++format)
00201 {
00202 if (*format != '%')
00203 {
00204 if (cur < end)
00205 *cur = *format;
00206 ++cur;
00207 continue;
00208 }
00209
00210 int flags = 0;
00211 ++format;
00212 if (*format == '-')
00213 ++format, flags |= LEFT;
00214
00215 int width = -1;
00216 if (isdigit (*format))
00217 width = xatoi(&format);
00218
00219 int precision = -1;
00220 if (*format == '.')
00221 {
00222 ++format;
00223 precision = xatoi(&format);
00224 if (precision < 0)
00225 precision = 0;
00226 }
00227
00228 int qualifier = -1;
00229 if (*format == 'l' || *format == 'L')
00230 qualifier = *format++;
00231
00232 switch (*format)
00233 {
00234
00235 case 's':
00236 {
00237 char *s = va_arg(args, char *);
00238 if ((unsigned long) s < 4096)
00239 s = "(nil)";
00240
00241 int len = strnlen(s, precision);
00242 if (! (flags & LEFT))
00243 for ( ; len < width; ++cur, --width)
00244 if (cur < end)
00245 *cur = ' ';
00246
00247 for (int i = 0; i < len; ++cur, ++s, ++i)
00248 if (cur < end)
00249 *cur = *s;
00250
00251 for ( ; len < width; ++cur, --width)
00252 if (cur < end)
00253 *cur = ' ';
00254
00255 continue;
00256 }
00257
00258 case 'p':
00259 if (width == -1)
00260 {
00261 width = 2*sizeof(void *) + 2;
00262 flags |= ZEROPAD;
00263 }
00264
00265 width -= 2;
00266 if (cur < end)
00267 *cur = '0';
00268 ++cur;
00269 if (cur < end)
00270 *cur = 'x';
00271 ++cur;
00272
00273 cur = xntoa (cur, end, (unsigned long) va_arg(args, void *),
00274 16, width, precision, flags);
00275 continue;
00276
00277 case 'd':
00278 cur = xntoa (cur, end,
00279 qualifier == 'L' ? va_arg(args, signed long long)
00280 : qualifier == 'l' ? va_arg(args, signed long)
00281 : va_arg(args, signed int),
00282 10, width, precision, flags | SIGN);
00283 continue;
00284
00285 case 'u':
00286 cur = xntoa (cur, end,
00287 qualifier == 'L' ? va_arg(args, unsigned long long)
00288 : qualifier == 'l' ? va_arg(args, unsigned long)
00289 : va_arg(args, unsigned int),
00290 10, width, precision, flags);
00291 continue;
00292
00293 case 'x':
00294 cur = xntoa (cur, end,
00295 qualifier == 'L' ? va_arg(args, unsigned long long)
00296 : qualifier == 'l' ? va_arg(args, unsigned long)
00297 : va_arg(args, unsigned int),
00298 16, width, precision, flags);
00299 continue;
00300
00301 case '%':
00302 if (cur < end)
00303 *cur = '%';
00304 ++cur;
00305 continue;
00306
00307
00308
00309
00310
00311
00312 }
00313 }
00314 va_end(args);
00315
00316 if (len > 0)
00317 if (cur < end)
00318 *cur = 0;
00319 else
00320 end[-1] = 0;
00321
00322 return cur - buf;
00323 }
00324
00326
00327 static int
00328 domunmap(IgHook::SafeData<igtrace_domunmap_t> &hook,
00329 void *addr, size_t len)
00330 {
00331 if (s_initialized)
00332 {
00333 void *stack [800];
00334 int depth = IgHookTrace::stacktrace (stack, sizeof (stack)/sizeof(stack[0]));
00335
00336
00337 if (IgTrace::filter ("munmap", stack, depth))
00338 {
00339 char buf [2048];
00340 const char *sym = 0;
00341 const char *lib = 0;
00342 int symoff = 0;
00343 int liboff = 0;
00344
00345 write (2, buf, xsprintf (buf, sizeof (buf),
00346 "*** MUNMAP by %.500s [thread %lu pid %ld]:"
00347 " address=%p len=%lu\n",
00348 IgTrace::program(),
00349 (unsigned long) pthread_self (), (long) getpid (),
00350 addr, (unsigned long) len,
00351 addr, (char *) addr + len));
00352
00353 pthread_mutex_lock(&s_demanglelock);
00354 for (int i = 2; i < depth; ++i)
00355 {
00356 void *symaddr = stack[i];
00357 if (IgHookTrace::symbol (symaddr, sym, lib, symoff, liboff))
00358 symaddr = (void *) ((intptr_t) symaddr - symoff);
00359
00360 char hexsym [32];
00361 if (! sym || ! *sym)
00362 {
00363 sprintf(hexsym, "@?%p", symaddr);
00364 sym = hexsym;
00365 }
00366 else if (s_demangle)
00367 {
00368 int status = 0;
00369 char *demangled = abi::__cxa_demangle (sym, s_demanglehere, &s_demanglelen, &status);
00370 if (status == 0 && demangled && *demangled)
00371 sym = demangled;
00372 else sym = "demangling failed";
00373 if (demangled && demangled != s_demanglehere)
00374
00375 s_demanglehere = demangled;
00376 }
00377 if (! lib)
00378 lib = "<unknown library>";
00379
00380 write (2, buf, xsprintf (buf, sizeof (buf),
00381 " %3d: %-11p %.500s + %d [%.500s + %d]\n",
00382 i-1, stack [i], sym, symoff, lib, liboff));
00383 }
00384 pthread_mutex_unlock(&s_demanglelock);
00385 }
00386 }
00387
00388
00389 return (*hook.chain) (addr, len);
00390 }
00391
00392 static void
00393 mmapreport(const char *sz, void *addr, size_t len, int prot, int flags, int fd, __off64_t off, void *ret)
00394 {
00395 void *stack [800];
00396 int depth = IgHookTrace::stacktrace (stack, sizeof (stack)/sizeof(stack[0]));
00397
00398
00399 if (IgTrace::filter ("mmap", stack, depth))
00400 {
00401 char buf [2048];
00402 const char *sym = 0;
00403 const char *lib = 0;
00404 int symoff = 0;
00405 int liboff = 0;
00406
00407 write (2, buf, xsprintf (buf, sizeof (buf),
00408 "*** MMAP%s by %.500s [thread %lu pid %ld]:"
00409 " addr=%p len=%lu"
00410 " prot=0x%x flags=0x%x fd=%d offset=%Ld => %p\n",
00411 sz, IgTrace::program(),
00412 (unsigned long) pthread_self (), (long) getpid (),
00413 addr, (unsigned long) len,
00414
00415 prot, flags, fd, (long long) off,
00416 ret));
00417
00418 pthread_mutex_lock(&s_demanglelock);
00419 for (int i = 3; i < depth; ++i)
00420 {
00421 void *symaddr = stack[i];
00422 if (IgHookTrace::symbol (symaddr, sym, lib, symoff, liboff))
00423 symaddr = (void *) ((intptr_t) symaddr - symoff);
00424
00425 char hexsym [32];
00426 if (! sym || ! *sym)
00427 {
00428 sprintf(hexsym, "@?%p", symaddr);
00429 sym = hexsym;
00430 }
00431 else if (s_demangle)
00432 {
00433 int status = 0;
00434 char *demangled = abi::__cxa_demangle (sym, s_demanglehere, &s_demanglelen, &status);
00435 if (status == 0 && demangled && *demangled)
00436 sym = demangled;
00437 if (demangled && demangled != s_demanglehere)
00438
00439 s_demanglehere = demangled;
00440 }
00441 if (! lib)
00442 lib = "<unknown library>";
00443
00444 write (2, buf, xsprintf (buf, sizeof (buf),
00445 " %3d: %-11p %.500s + %d [%.500s + %d]\n",
00446 i-2, stack [i], sym, symoff, lib, liboff));
00447 }
00448 pthread_mutex_unlock(&s_demanglelock);
00449 }
00450 }
00451
00452 static void *
00453 dommap32(IgHook::SafeData<igtrace_dommap32_t> &hook,
00454 void *addr, size_t len, int prot, int flags, int fd, __off_t off)
00455 {
00456 void *ret = (*hook.chain) (addr, len, prot, flags, fd, off);
00457 if (s_initialized)
00458 mmapreport("32", addr, len, prot, flags, fd, off, ret);
00459 return ret;
00460 }
00461
00462 static void *
00463 dommap64(IgHook::SafeData<igtrace_dommap64_t> &hook,
00464 void *addr, size_t len, int prot, int flags, int fd, __off64_t off)
00465 {
00466 void *ret = (*hook.chain) (addr, len, prot, flags, fd, off);
00467 if (s_initialized)
00468 mmapreport("64", addr, len, prot, flags, fd, off, ret);
00469 return ret;
00470 }
00471
00473 static bool autoboot = (IgTraceMMap::initialize (), true);