tools/profiler/LulDwarfSummariser.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "LulDwarfSummariser.h"
     9 #include "mozilla/Assertions.h"
    11 // Set this to 1 for verbose logging
    12 #define DEBUG_SUMMARISER 0
    14 namespace lul {
    16 Summariser::Summariser(SecMap* aSecMap, uintptr_t aTextBias,
    17                        void(*aLog)(const char*))
    18   : mSecMap(aSecMap)
    19   , mTextBias(aTextBias)
    20   , mLog(aLog)
    21 {
    22   mCurrAddr = 0;
    23   mMax1Addr = 0; // Gives an empty range.
    25   // Initialise the running RuleSet to "haven't got a clue" status.
    26   new (&mCurrRules) RuleSet();
    27 }
    29 void
    30 Summariser::Entry(uintptr_t aAddress, uintptr_t aLength)
    31 {
    32   aAddress += mTextBias;
    33   if (DEBUG_SUMMARISER) {
    34     char buf[100];
    35     snprintf(buf, sizeof(buf), "LUL Entry(%llx, %llu)\n",
    36              (unsigned long long int)aAddress,
    37              (unsigned long long int)aLength);
    38     buf[sizeof(buf)-1] = 0;
    39     mLog(buf);
    40   }
    41   // This throws away any previous summary, that is, assumes
    42   // that the previous summary, if any, has been properly finished
    43   // by a call to End().
    44   mCurrAddr = aAddress;
    45   mMax1Addr = aAddress + aLength;
    46   new (&mCurrRules) RuleSet();
    47 }
    49 void
    50 Summariser::Rule(uintptr_t aAddress,
    51                  int aNewReg, int aOldReg, intptr_t aOffset, bool aDeref)
    52 {
    53   aAddress += mTextBias;
    54   if (DEBUG_SUMMARISER) {
    55     char buf[100];
    56     snprintf(buf, sizeof(buf),
    57              "LUL  0x%llx  old-r%d = %sr%d + %ld%s\n",
    58              (unsigned long long int)aAddress, aNewReg,
    59              aDeref ? "*(" : "", aOldReg, (long)aOffset, aDeref ? ")" : "");
    60     buf[sizeof(buf)-1] = 0;
    61     mLog(buf);
    62   }
    63   if (mCurrAddr < aAddress) {
    64     // Flush the existing summary first.
    65     mCurrRules.mAddr = mCurrAddr;
    66     mCurrRules.mLen  = aAddress - mCurrAddr;
    67     mSecMap->AddRuleSet(&mCurrRules);
    68     if (DEBUG_SUMMARISER) {
    69       mLog("LUL  "); mCurrRules.Print(mLog);
    70       mLog("\n");
    71     }
    72     mCurrAddr = aAddress;
    73   }
    75   // FIXME: factor out common parts of the arch-dependent summarisers.
    77 #if defined(LUL_ARCH_arm)
    79   // ----------------- arm ----------------- //
    81   // Now, can we add the rule to our summary?  This depends on whether
    82   // the registers and the overall expression are representable.  This
    83   // is the heart of the summarisation process.
    84   switch (aNewReg) {
    86     case DW_REG_CFA:
    87       // This is a rule that defines the CFA.  The only forms we
    88       // choose to represent are: r7/11/12/13 + offset.  The offset
    89       // must fit into 32 bits since 'uintptr_t' is 32 bit on ARM,
    90       // hence there is no need to check it for overflow.
    91       if (aDeref) {
    92         goto cant_summarise;
    93       }
    94       switch (aOldReg) {
    95         case DW_REG_ARM_R7:  case DW_REG_ARM_R11:
    96         case DW_REG_ARM_R12: case DW_REG_ARM_R13:
    97           break;
    98         default:
    99           goto cant_summarise;
   100       }
   101       mCurrRules.mCfaExpr = LExpr(LExpr::NODEREF, aOldReg, aOffset);
   102       break;
   104     case DW_REG_ARM_R7:  case DW_REG_ARM_R11: case DW_REG_ARM_R12:
   105     case DW_REG_ARM_R13: case DW_REG_ARM_R14: case DW_REG_ARM_R15: {
   106       // Check the aOldReg is valid.
   107       switch (aOldReg) {
   108         case DW_REG_CFA:
   109         case DW_REG_ARM_R7:  case DW_REG_ARM_R11: case DW_REG_ARM_R12:
   110         case DW_REG_ARM_R13: case DW_REG_ARM_R14: case DW_REG_ARM_R15:
   111           break;
   112         default:
   113           goto cant_summarise;
   114       }
   115       // This is a new rule for one of r{7,11,12,13,14,15} and has a
   116       // representable offset.  In particular the new value of r15 is
   117       // going to be the return address.
   118       LExpr expr = LExpr(aDeref ? LExpr::DEREF : LExpr::NODEREF,
   119                          aOldReg, aOffset);
   120       switch (aNewReg) {
   121         case DW_REG_ARM_R7:  mCurrRules.mR7expr  = expr; break;
   122         case DW_REG_ARM_R11: mCurrRules.mR11expr = expr; break;
   123         case DW_REG_ARM_R12: mCurrRules.mR12expr = expr; break;
   124         case DW_REG_ARM_R13: mCurrRules.mR13expr = expr; break;
   125         case DW_REG_ARM_R14: mCurrRules.mR14expr = expr; break;
   126         case DW_REG_ARM_R15: mCurrRules.mR15expr = expr; break;
   127         default: MOZ_ASSERT(0);
   128       }
   129       break;
   130     }
   132     default:
   133       goto cant_summarise;
   134   }
   136   // Mark callee-saved registers (r4 .. r11) as unchanged, if there is
   137   // no other information about them.  FIXME: do this just once, at
   138   // the point where the ruleset is committed.
   139   if (mCurrRules.mR7expr.mHow == LExpr::UNKNOWN) {
   140     mCurrRules.mR7expr = LExpr(LExpr::NODEREF, DW_REG_ARM_R7, 0);
   141   }
   142   if (mCurrRules.mR11expr.mHow == LExpr::UNKNOWN) {
   143     mCurrRules.mR11expr = LExpr(LExpr::NODEREF, DW_REG_ARM_R11, 0);
   144   }
   145   if (mCurrRules.mR12expr.mHow == LExpr::UNKNOWN) {
   146     mCurrRules.mR12expr = LExpr(LExpr::NODEREF, DW_REG_ARM_R12, 0);
   147   }
   149   // The old r13 (SP) value before the call is always the same as the
   150   // CFA.
   151   mCurrRules.mR13expr = LExpr(LExpr::NODEREF, DW_REG_CFA, 0);
   153   // If there's no information about R15 (the return address), say
   154   // it's a copy of R14 (the link register).
   155   if (mCurrRules.mR15expr.mHow == LExpr::UNKNOWN) {
   156     mCurrRules.mR15expr = LExpr(LExpr::NODEREF, DW_REG_ARM_R14, 0);
   157   }
   159 #elif defined(LUL_ARCH_x64) || defined(LUL_ARCH_x86)
   161   // ---------------- x64/x86 ---------------- //
   163   // Now, can we add the rule to our summary?  This depends on whether
   164   // the registers and the overall expression are representable.  This
   165   // is the heart of the summarisation process.  In the 64 bit case
   166   // we need to check that aOffset will fit into an int32_t.  In the
   167   // 32 bit case it is expected that the compiler will fold out the
   168   // test since it always succeeds.
   169   if (aNewReg == DW_REG_CFA) {
   170     // This is a rule that defines the CFA.  The only forms we can
   171     // represent are: = SP+offset or = FP+offset.
   172     if (!aDeref && aOffset == (intptr_t)(int32_t)aOffset &&
   173         (aOldReg == DW_REG_INTEL_XSP || aOldReg == DW_REG_INTEL_XBP)) {
   174       mCurrRules.mCfaExpr = LExpr(LExpr::NODEREF, aOldReg, aOffset);
   175     } else {
   176       goto cant_summarise;
   177     }
   178   }
   179   else
   180   if ((aNewReg == DW_REG_INTEL_XSP ||
   181        aNewReg == DW_REG_INTEL_XBP || aNewReg == DW_REG_INTEL_XIP) &&
   182       (aOldReg == DW_REG_CFA ||
   183        aOldReg == DW_REG_INTEL_XSP ||
   184        aOldReg == DW_REG_INTEL_XBP || aOldReg == DW_REG_INTEL_XIP) &&
   185       aOffset == (intptr_t)(int32_t)aOffset) {
   186     // This is a new rule for SP, BP or the return address
   187     // respectively, and has a representable offset.
   188     LExpr expr = LExpr(aDeref ? LExpr::DEREF : LExpr::NODEREF,
   189                        aOldReg, aOffset);
   190     switch (aNewReg) {
   191       case DW_REG_INTEL_XBP: mCurrRules.mXbpExpr = expr; break;
   192       case DW_REG_INTEL_XSP: mCurrRules.mXspExpr = expr; break;
   193       case DW_REG_INTEL_XIP: mCurrRules.mXipExpr = expr; break;
   194       default: MOZ_CRASH("impossible value for aNewReg");
   195     }
   196   }
   197   else {
   198     goto cant_summarise;
   199   }
   201   // On Intel, it seems the old SP value before the call is always the
   202   // same as the CFA.  Therefore, in the absence of any other way to
   203   // recover the SP, specify that the CFA should be copied.
   204   if (mCurrRules.mXspExpr.mHow == LExpr::UNKNOWN) {
   205     mCurrRules.mXspExpr = LExpr(LExpr::NODEREF, DW_REG_CFA, 0);
   206   }
   208   // Also, gcc says "Undef" for BP when it is unchanged.
   209   if (mCurrRules.mXbpExpr.mHow == LExpr::UNKNOWN) {
   210     mCurrRules.mXbpExpr = LExpr(LExpr::NODEREF, DW_REG_INTEL_XBP, 0);
   211   }
   213 #else
   215 # error "Unsupported arch"
   216 #endif
   218   return;
   219  cant_summarise:
   220   if (0) {
   221     mLog("LUL  can't summarise\n");
   222   }
   223 }
   225 void
   226 Summariser::End()
   227 {
   228   if (DEBUG_SUMMARISER) {
   229     mLog("LUL End\n");
   230   }
   231   if (mCurrAddr < mMax1Addr) {
   232     mCurrRules.mAddr = mCurrAddr;
   233     mCurrRules.mLen  = mMax1Addr - mCurrAddr;
   234     mSecMap->AddRuleSet(&mCurrRules);
   235     if (DEBUG_SUMMARISER) {
   236       mLog("LUL  "); mCurrRules.Print(mLog);
   237       mLog("\n");
   238     }
   239   }
   240 }
   242 } // namespace lul

mercurial