security/sandbox/chromium/base/debug/profiler.cc

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "base/debug/profiler.h"
michael@0 6
michael@0 7 #include <string>
michael@0 8
michael@0 9 #include "base/process/process_handle.h"
michael@0 10 #include "base/strings/string_util.h"
michael@0 11 #include "base/strings/stringprintf.h"
michael@0 12
michael@0 13 #if defined(OS_WIN)
michael@0 14 #include "base/win/pe_image.h"
michael@0 15 #endif // defined(OS_WIN)
michael@0 16
michael@0 17 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
michael@0 18 #include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
michael@0 19 #endif
michael@0 20
michael@0 21 namespace base {
michael@0 22 namespace debug {
michael@0 23
michael@0 24 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
michael@0 25
michael@0 26 static int profile_count = 0;
michael@0 27
michael@0 28 void StartProfiling(const std::string& name) {
michael@0 29 ++profile_count;
michael@0 30 std::string full_name(name);
michael@0 31 std::string pid = StringPrintf("%d", GetCurrentProcId());
michael@0 32 std::string count = StringPrintf("%d", profile_count);
michael@0 33 ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
michael@0 34 ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
michael@0 35 ProfilerStart(full_name.c_str());
michael@0 36 }
michael@0 37
michael@0 38 void StopProfiling() {
michael@0 39 ProfilerFlush();
michael@0 40 ProfilerStop();
michael@0 41 }
michael@0 42
michael@0 43 void FlushProfiling() {
michael@0 44 ProfilerFlush();
michael@0 45 }
michael@0 46
michael@0 47 bool BeingProfiled() {
michael@0 48 return ProfilingIsEnabledForAllThreads();
michael@0 49 }
michael@0 50
michael@0 51 void RestartProfilingAfterFork() {
michael@0 52 ProfilerRegisterThread();
michael@0 53 }
michael@0 54
michael@0 55 #else
michael@0 56
michael@0 57 void StartProfiling(const std::string& name) {
michael@0 58 }
michael@0 59
michael@0 60 void StopProfiling() {
michael@0 61 }
michael@0 62
michael@0 63 void FlushProfiling() {
michael@0 64 }
michael@0 65
michael@0 66 bool BeingProfiled() {
michael@0 67 return false;
michael@0 68 }
michael@0 69
michael@0 70 void RestartProfilingAfterFork() {
michael@0 71 }
michael@0 72
michael@0 73 #endif
michael@0 74
michael@0 75 #if !defined(OS_WIN)
michael@0 76
michael@0 77 bool IsBinaryInstrumented() {
michael@0 78 return false;
michael@0 79 }
michael@0 80
michael@0 81 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
michael@0 82 return NULL;
michael@0 83 }
michael@0 84
michael@0 85 DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
michael@0 86 return NULL;
michael@0 87 }
michael@0 88
michael@0 89 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
michael@0 90 return NULL;
michael@0 91 }
michael@0 92
michael@0 93 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
michael@0 94 return NULL;
michael@0 95 }
michael@0 96
michael@0 97 #else // defined(OS_WIN)
michael@0 98
michael@0 99 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
michael@0 100 extern "C" IMAGE_DOS_HEADER __ImageBase;
michael@0 101
michael@0 102 bool IsBinaryInstrumented() {
michael@0 103 enum InstrumentationCheckState {
michael@0 104 UNINITIALIZED,
michael@0 105 INSTRUMENTED_IMAGE,
michael@0 106 NON_INSTRUMENTED_IMAGE,
michael@0 107 };
michael@0 108
michael@0 109 static InstrumentationCheckState state = UNINITIALIZED;
michael@0 110
michael@0 111 if (state == UNINITIALIZED) {
michael@0 112 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
michael@0 113 base::win::PEImage image(this_module);
michael@0 114
michael@0 115 // Check to be sure our image is structured as we'd expect.
michael@0 116 DCHECK(image.VerifyMagic());
michael@0 117
michael@0 118 // Syzygy-instrumented binaries contain a PE image section named ".thunks",
michael@0 119 // and all Syzygy-modified binaries contain the ".syzygy" image section.
michael@0 120 // This is a very fast check, as it only looks at the image header.
michael@0 121 if ((image.GetImageSectionHeaderByName(".thunks") != NULL) &&
michael@0 122 (image.GetImageSectionHeaderByName(".syzygy") != NULL)) {
michael@0 123 state = INSTRUMENTED_IMAGE;
michael@0 124 } else {
michael@0 125 state = NON_INSTRUMENTED_IMAGE;
michael@0 126 }
michael@0 127 }
michael@0 128 DCHECK(state != UNINITIALIZED);
michael@0 129
michael@0 130 return state == INSTRUMENTED_IMAGE;
michael@0 131 }
michael@0 132
michael@0 133 namespace {
michael@0 134
michael@0 135 struct FunctionSearchContext {
michael@0 136 const char* name;
michael@0 137 FARPROC function;
michael@0 138 };
michael@0 139
michael@0 140 // Callback function to PEImage::EnumImportChunks.
michael@0 141 bool FindResolutionFunctionInImports(
michael@0 142 const base::win::PEImage &image, const char* module_name,
michael@0 143 PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table,
michael@0 144 PVOID cookie) {
michael@0 145 FunctionSearchContext* context =
michael@0 146 reinterpret_cast<FunctionSearchContext*>(cookie);
michael@0 147
michael@0 148 DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context);
michael@0 149 DCHECK_EQ(static_cast<FARPROC>(NULL), context->function);
michael@0 150
michael@0 151 // Our import address table contains pointers to the functions we import
michael@0 152 // at this point. Let's retrieve the first such function and use it to
michael@0 153 // find the module this import was resolved to by the loader.
michael@0 154 const wchar_t* function_in_module =
michael@0 155 reinterpret_cast<const wchar_t*>(import_address_table->u1.Function);
michael@0 156
michael@0 157 // Retrieve the module by a function in the module.
michael@0 158 const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
michael@0 159 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
michael@0 160 HMODULE module = NULL;
michael@0 161 if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) {
michael@0 162 // This can happen if someone IAT patches us to a thunk.
michael@0 163 return true;
michael@0 164 }
michael@0 165
michael@0 166 // See whether this module exports the function we're looking for.
michael@0 167 FARPROC exported_func = ::GetProcAddress(module, context->name);
michael@0 168 if (exported_func != NULL) {
michael@0 169 // We found it, return the function and terminate the enumeration.
michael@0 170 context->function = exported_func;
michael@0 171 return false;
michael@0 172 }
michael@0 173
michael@0 174 // Keep going.
michael@0 175 return true;
michael@0 176 }
michael@0 177
michael@0 178 template <typename FunctionType>
michael@0 179 FunctionType FindFunctionInImports(const char* function_name) {
michael@0 180 if (!IsBinaryInstrumented())
michael@0 181 return NULL;
michael@0 182
michael@0 183 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
michael@0 184 base::win::PEImage image(this_module);
michael@0 185
michael@0 186 FunctionSearchContext ctx = { function_name, NULL };
michael@0 187 image.EnumImportChunks(FindResolutionFunctionInImports, &ctx);
michael@0 188
michael@0 189 return reinterpret_cast<FunctionType>(ctx.function);
michael@0 190 }
michael@0 191
michael@0 192 } // namespace
michael@0 193
michael@0 194 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
michael@0 195 return FindFunctionInImports<ReturnAddressLocationResolver>(
michael@0 196 "ResolveReturnAddressLocation");
michael@0 197 }
michael@0 198
michael@0 199 DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
michael@0 200 return FindFunctionInImports<DynamicFunctionEntryHook>(
michael@0 201 "OnDynamicFunctionEntry");
michael@0 202 }
michael@0 203
michael@0 204 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
michael@0 205 return FindFunctionInImports<AddDynamicSymbol>(
michael@0 206 "AddDynamicSymbol");
michael@0 207 }
michael@0 208
michael@0 209 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
michael@0 210 return FindFunctionInImports<MoveDynamicSymbol>(
michael@0 211 "MoveDynamicSymbol");
michael@0 212 }
michael@0 213
michael@0 214 #endif // defined(OS_WIN)
michael@0 215
michael@0 216 } // namespace debug
michael@0 217 } // namespace base

mercurial