tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

alias.h (5434B)


      1 // Copyright 2011 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_DEBUG_ALIAS_H_
      6 #define BASE_DEBUG_ALIAS_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include "base/base_export.h"
     11 
     12 namespace base {
     13 namespace debug {
     14 
     15 // Make the optimizer think that |var| is aliased. This can be used to inhibit
     16 // three different kinds of optimizations:
     17 //
     18 // Case #1: Prevent a local variable from being optimized out if it would not
     19 // otherwise be live at the point of a potential crash. This can only be done
     20 // with local variables, not globals, object members, or function return values
     21 // - these must be copied to locals if you want to ensure they are recorded in
     22 // crash dumps. Function arguments are fine to use since the
     23 // base::debug::Alias() call on them will make sure they are copied to the stack
     24 // even if they were passed in a register. Note that if the local variable is a
     25 // pointer then its value will be retained but the memory that it points to will
     26 // probably not be saved in the crash dump - by default only stack memory is
     27 // saved. Therefore the aliasing technique is usually only worthwhile with
     28 // non-pointer variables. If you have a pointer to an object and you want to
     29 // retain the object's state you need to copy the object or its fields to local
     30 // variables.
     31 //
     32 // Example usage:
     33 //   int last_error = err_;
     34 //   base::debug::Alias(&last_error);
     35 //   DEBUG_ALIAS_FOR_CSTR(name_copy, p->name, 16);
     36 //   CHECK(false);
     37 //
     38 // Case #2: Prevent a tail call into a function. This is useful to make sure the
     39 // function containing the call to base::debug::Alias() will be present in the
     40 // call stack. In this case there is no memory that needs to be on
     41 // the stack so we can use nullptr. The call to base::debug::Alias() needs to
     42 // happen after the call that is suspected to be tail called. Note: This
     43 // technique will prevent tail calls at the specific call site only. To prevent
     44 // them for all invocations of a function look at NOT_TAIL_CALLED.
     45 //
     46 // Example usage:
     47 //   NOINLINE void Foo(){
     48 //     ... code ...
     49 //
     50 //     Bar();
     51 //     base::debug::Alias(nullptr);
     52 //   }
     53 //
     54 // Case #3: Prevent code folding of a non-unique function. Code folding can
     55 // cause the same address to be assigned to different functions if they are
     56 // identical. If finding the precise signature of a function in the call-stack
     57 // is important and it's suspected the function is identical to other functions
     58 // it can be made unique using NO_CODE_FOLDING which is a wrapper around
     59 // base::debug::Alias();
     60 //
     61 // Example usage:
     62 //   NOINLINE void Foo(){
     63 //     NO_CODE_FOLDING();
     64 //     Bar();
     65 //   }
     66 //
     67 // Finally please note that these effects compound. This means that saving a
     68 // stack variable (case #1) using base::debug::Alias() will also inhibit
     69 // tail calls for calls in earlier lines and prevent code folding.
     70 
     71 void BASE_EXPORT Alias(const void* var);
     72 
     73 }  // namespace debug
     74 
     75 // The canonical definitions/declarations for `strlcpy()`, `u16cstrlcpy()`,
     76 // and `wcslcpy()` are in //base/strings/string_util.{cc,h}. These prototypes
     77 // are forward declared here to avoid having to include string_utils.h and its
     78 // transitive tree of headers in an otherwise small header (which is itself
     79 // included in some very popular headers).
     80 BASE_EXPORT size_t strlcpy(char* dst, const char* src, size_t dst_size);
     81 BASE_EXPORT size_t u16cstrlcpy(char16_t* dst,
     82                               const char16_t* src,
     83                               size_t dst_size);
     84 BASE_EXPORT size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size);
     85 
     86 }  // namespace base
     87 
     88 // Convenience macro that copies the null-terminated string from `c_str` into a
     89 // stack-allocated char array named `var_name` that holds up to `array_size - 1`
     90 // characters and should be preserved in memory dumps.
     91 #define DEBUG_ALIAS_FOR_CSTR(var_name, c_str, array_size)  \
     92  char var_name[array_size] = {};                          \
     93  ::base::strlcpy(var_name, (c_str), std::size(var_name)); \
     94  ::base::debug::Alias(var_name)
     95 
     96 #define DEBUG_ALIAS_FOR_U16CSTR(var_name, c_str, array_size)   \
     97  char16_t var_name[array_size] = {};                          \
     98  ::base::u16cstrlcpy(var_name, (c_str), std::size(var_name)); \
     99  ::base::debug::Alias(var_name)
    100 
    101 #define DEBUG_ALIAS_FOR_WCHARCSTR(var_name, c_str, array_size) \
    102  wchar_t var_name[array_size] = {};                           \
    103  ::base::wcslcpy(var_name, (c_str), std::size(var_name));     \
    104  ::base::debug::Alias(var_name)
    105 
    106 // Code folding is a linker optimization whereby the linker identifies functions
    107 // that are bit-identical and overlays them. This saves space but it leads to
    108 // confusing call stacks because multiple symbols are at the same address and
    109 // it is unpredictable which one will be displayed. Disabling of code folding is
    110 // particularly useful when function names are used as signatures in crashes.
    111 // This macro doesn't guarantee that code folding will be prevented but it
    112 // greatly reduces the odds and always prevents it within one source file.
    113 // If using in a function that terminates the process it is safest to put the
    114 // NO_CODE_FOLDING macro at the top of the function.
    115 // Use like:
    116 //   void FooBarFailure(size_t size) { NO_CODE_FOLDING(); OOM_CRASH(size); }
    117 #define NO_CODE_FOLDING()           \
    118  const int line_number = __LINE__; \
    119  base::debug::Alias(&line_number)
    120 
    121 #endif  // BASE_DEBUG_ALIAS_H_