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