CMS 3D CMS Logo

IgTraceMMap.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
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 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00018 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00019 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00020 
00021 class IgTraceMMap
00022 {
00023 public:
00024     static void initialize (void);
00025 };
00026 
00027 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00028 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00029 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00030 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00031 
00032 // Traps for this profiler module
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 // Data for this trace module
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 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00055 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
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 // Mini-sprintf that does not deadlock.  Don't ask :-/
00110 // Snatched from Linux kernel.
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         // case 'c':
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         // case 'n':
00308         // case 'i':
00309         // case 'o':
00310         // case 'X':
00311         // default:
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 // Traps for this trace module.
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       // If it passes filters, walk the stack to print out information.
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                         // oops, this shouldn't happen, we might hose ourselves.
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     // Call the actual munmap.
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     // If it passes filters, walk the stack to print out information.
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                                  // addr, (addr ? (char *) addr + len : addr),
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                     // oops, this shouldn't happen, we might hose ourselves.
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);

Generated on Tue Jun 9 17:38:10 2009 for CMSSW by  doxygen 1.5.4