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_ 122