diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /security/sandbox/chromium/base/debug | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | security/sandbox/chromium/base/debug/alias.cc | 16 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/alias.h | 44 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/crash_logging.h | 104 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/debugger.h | 50 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/leak_annotations.h | 46 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/profiler.cc | 180 | ||||
-rw-r--r-- | security/sandbox/chromium/base/debug/profiler.h | 76 |
7 files changed, 516 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/debug/alias.cc b/security/sandbox/chromium/base/debug/alias.cc new file mode 100644 index 0000000000..f808c50345 --- /dev/null +++ b/security/sandbox/chromium/base/debug/alias.cc @@ -0,0 +1,16 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/alias.h" +#include "build/build_config.h" + +namespace base { +namespace debug { + +// This file/function should be excluded from LTO/LTCG to ensure that the +// compiler can't see this function's implementation when compiling calls to it. +NOINLINE void Alias(const void* var) {} + +} // namespace debug +} // namespace base diff --git a/security/sandbox/chromium/base/debug/alias.h b/security/sandbox/chromium/base/debug/alias.h new file mode 100644 index 0000000000..35af2c23bf --- /dev/null +++ b/security/sandbox/chromium/base/debug/alias.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_ALIAS_H_ +#define BASE_DEBUG_ALIAS_H_ + +#include "base/base_export.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" + +namespace base { +namespace debug { + +// Make the optimizer think that var is aliased. This is to prevent it from +// optimizing out local variables that would not otherwise be live at the point +// of a potential crash. +// base::debug::Alias should only be used for local variables, not globals, +// object members, or function return values - these must be copied to locals if +// you want to ensure they are recorded in crash dumps. +// Note that if the local variable is a pointer then its value will be retained +// but the memory that it points to will probably not be saved in the crash +// dump - by default only stack memory is saved. Therefore the aliasing +// technique is usually only worthwhile with non-pointer variables. If you have +// a pointer to an object and you want to retain the object's state you need to +// copy the object or its fields to local variables. Example usage: +// int last_error = err_; +// base::debug::Alias(&last_error); +// DEBUG_ALIAS_FOR_CSTR(name_copy, p->name, 16); +// CHECK(false); +void BASE_EXPORT Alias(const void* var); + +} // namespace debug +} // namespace base + +// Convenience macro that copies the null-terminated string from |c_str| into a +// stack-allocated char array named |var_name| that holds up to |char_count| +// characters and should be preserved in memory dumps. +#define DEBUG_ALIAS_FOR_CSTR(var_name, c_str, char_count) \ + char var_name[char_count]; \ + ::base::strlcpy(var_name, (c_str), base::size(var_name)); \ + ::base::debug::Alias(var_name); + +#endif // BASE_DEBUG_ALIAS_H_ diff --git a/security/sandbox/chromium/base/debug/crash_logging.h b/security/sandbox/chromium/base/debug/crash_logging.h new file mode 100644 index 0000000000..9c6cd758da --- /dev/null +++ b/security/sandbox/chromium/base/debug/crash_logging.h @@ -0,0 +1,104 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_CRASH_LOGGING_H_ +#define BASE_DEBUG_CRASH_LOGGING_H_ + +#include <stddef.h> + +#include <memory> + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/strings/string_piece.h" + +namespace base { +namespace debug { + +// A crash key is an annotation that is carried along with a crash report, to +// provide additional debugging information beyond a stack trace. Crash keys +// have a name and a string value. +// +// The preferred API is //components/crash/core/common:crash_key, however not +// all clients can hold a direct dependency on that target. The API provided +// in this file indirects the dependency. +// +// Example usage: +// static CrashKeyString* crash_key = +// AllocateCrashKeyString("name", CrashKeySize::Size32); +// SetCrashKeyString(crash_key, "value"); +// ClearCrashKeyString(crash_key); + +// The maximum length for a crash key's value must be one of the following +// pre-determined values. +enum class CrashKeySize { + Size32 = 32, + Size64 = 64, + Size256 = 256, +}; + +struct CrashKeyString; + +// Allocates a new crash key with the specified |name| with storage for a +// value up to length |size|. This will return null if the crash key system is +// not initialized. +BASE_EXPORT CrashKeyString* AllocateCrashKeyString(const char name[], + CrashKeySize size); + +// Stores |value| into the specified |crash_key|. The |crash_key| may be null +// if AllocateCrashKeyString() returned null. If |value| is longer than the +// size with which the key was allocated, it will be truncated. +BASE_EXPORT void SetCrashKeyString(CrashKeyString* crash_key, + base::StringPiece value); + +// Clears any value that was stored in |crash_key|. The |crash_key| may be +// null. +BASE_EXPORT void ClearCrashKeyString(CrashKeyString* crash_key); + +// A scoper that sets the specified key to value for the lifetime of the +// object, and clears it on destruction. +class BASE_EXPORT ScopedCrashKeyString { + public: + ScopedCrashKeyString(CrashKeyString* crash_key, base::StringPiece value); + ~ScopedCrashKeyString(); + + private: + CrashKeyString* const crash_key_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCrashKeyString); +}; + +//////////////////////////////////////////////////////////////////////////////// +// The following declarations are used to initialize the crash key system +// in //base by providing implementations for the above functions. + +// The virtual interface that provides the implementation for the crash key +// API. This is implemented by a higher-layer component, and the instance is +// set using the function below. +class CrashKeyImplementation { + public: + virtual ~CrashKeyImplementation() = default; + + virtual CrashKeyString* Allocate(const char name[], CrashKeySize size) = 0; + virtual void Set(CrashKeyString* crash_key, base::StringPiece value) = 0; + virtual void Clear(CrashKeyString* crash_key) = 0; +}; + +// Initializes the crash key system in base by replacing the existing +// implementation, if it exists, with |impl|. The |impl| is copied into base. +BASE_EXPORT void SetCrashKeyImplementation( + std::unique_ptr<CrashKeyImplementation> impl); + +// The base structure for a crash key, storing the allocation metadata. +struct CrashKeyString { + constexpr CrashKeyString(const char name[], CrashKeySize size) + : name(name), size(size) {} + const char* const name; + const CrashKeySize size; +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_CRASH_LOGGING_H_ diff --git a/security/sandbox/chromium/base/debug/debugger.h b/security/sandbox/chromium/base/debug/debugger.h new file mode 100644 index 0000000000..efc9b40cb9 --- /dev/null +++ b/security/sandbox/chromium/base/debug/debugger.h @@ -0,0 +1,50 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a cross platform interface for helper functions related to +// debuggers. You should use this to test if you're running under a debugger, +// and if you would like to yield (breakpoint) into the debugger. + +#ifndef BASE_DEBUG_DEBUGGER_H_ +#define BASE_DEBUG_DEBUGGER_H_ + +#include "base/base_export.h" + +namespace base { +namespace debug { + +// Waits wait_seconds seconds for a debugger to attach to the current process. +// When silent is false, an exception is thrown when a debugger is detected. +BASE_EXPORT bool WaitForDebugger(int wait_seconds, bool silent); + +// Returns true if the given process is being run under a debugger. +// +// On OS X, the underlying mechanism doesn't work when the sandbox is enabled. +// To get around this, this function caches its value. +// +// WARNING: Because of this, on OS X, a call MUST be made to this function +// BEFORE the sandbox is enabled. +BASE_EXPORT bool BeingDebugged(); + +// Break into the debugger, assumes a debugger is present. +BASE_EXPORT void BreakDebugger(); + +// Used in test code, this controls whether showing dialogs and breaking into +// the debugger is suppressed for debug errors, even in debug mode (normally +// release mode doesn't do this stuff -- this is controlled separately). +// Normally UI is not suppressed. This is normally used when running automated +// tests where we want a crash rather than a dialog or a debugger. +BASE_EXPORT void SetSuppressDebugUI(bool suppress); +BASE_EXPORT bool IsDebugUISuppressed(); + +// If a debugger is present, verifies that it is properly set up, and DCHECK()s +// if misconfigured. Currently only verifies that //tools/gdb/gdbinit has been +// sourced when using gdb on Linux and //tools/lldb/lldbinit.py has been sourced +// when using lldb on macOS. +BASE_EXPORT void VerifyDebugger(); + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_DEBUGGER_H_ diff --git a/security/sandbox/chromium/base/debug/leak_annotations.h b/security/sandbox/chromium/base/debug/leak_annotations.h new file mode 100644 index 0000000000..dc502461d0 --- /dev/null +++ b/security/sandbox/chromium/base/debug/leak_annotations.h @@ -0,0 +1,46 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_LEAK_ANNOTATIONS_H_ +#define BASE_DEBUG_LEAK_ANNOTATIONS_H_ + +#include "base/macros.h" +#include "build/build_config.h" + +// This file defines macros which can be used to annotate intentional memory +// leaks. Support for annotations is implemented in LeakSanitizer. Annotated +// objects will be treated as a source of live pointers, i.e. any heap objects +// reachable by following pointers from an annotated object will not be +// reported as leaks. +// +// ANNOTATE_SCOPED_MEMORY_LEAK: all allocations made in the current scope +// will be annotated as leaks. +// ANNOTATE_LEAKING_OBJECT_PTR(X): the heap object referenced by pointer X will +// be annotated as a leak. + +#if defined(LEAK_SANITIZER) && !defined(OS_NACL) + +#include <sanitizer/lsan_interface.h> + +class ScopedLeakSanitizerDisabler { + public: + ScopedLeakSanitizerDisabler() { __lsan_disable(); } + ~ScopedLeakSanitizerDisabler() { __lsan_enable(); } + private: + DISALLOW_COPY_AND_ASSIGN(ScopedLeakSanitizerDisabler); +}; + +#define ANNOTATE_SCOPED_MEMORY_LEAK \ + ScopedLeakSanitizerDisabler leak_sanitizer_disabler; static_cast<void>(0) + +#define ANNOTATE_LEAKING_OBJECT_PTR(X) __lsan_ignore_object(X); + +#else + +#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0) +#define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0) + +#endif + +#endif // BASE_DEBUG_LEAK_ANNOTATIONS_H_ diff --git a/security/sandbox/chromium/base/debug/profiler.cc b/security/sandbox/chromium/base/debug/profiler.cc new file mode 100644 index 0000000000..3530d61d07 --- /dev/null +++ b/security/sandbox/chromium/base/debug/profiler.cc @@ -0,0 +1,180 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/profiler.h" + +#include <string> + +#include "base/allocator/buildflags.h" +#include "base/debug/debugging_buildflags.h" +#include "base/process/process_handle.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include "base/win/current_module.h" +#include "base/win/pe_image.h" +#endif // defined(OS_WIN) + +// TODO(peria): Enable profiling on Windows. +#if BUILDFLAG(ENABLE_PROFILING) && BUILDFLAG(USE_TCMALLOC) && !defined(OS_WIN) +#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h" +#endif + +namespace base { +namespace debug { + +// TODO(peria): Enable profiling on Windows. +#if BUILDFLAG(ENABLE_PROFILING) && BUILDFLAG(USE_TCMALLOC) && !defined(OS_WIN) + +static int profile_count = 0; + +void StartProfiling(const std::string& name) { + ++profile_count; + std::string full_name(name); + std::string pid = NumberToString(GetCurrentProcId()); + std::string count = NumberToString(profile_count); + ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid); + ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count); + ProfilerStart(full_name.c_str()); +} + +void StopProfiling() { + ProfilerFlush(); + ProfilerStop(); +} + +void FlushProfiling() { + ProfilerFlush(); +} + +bool BeingProfiled() { + return ProfilingIsEnabledForAllThreads(); +} + +void RestartProfilingAfterFork() { + ProfilerRegisterThread(); +} + +bool IsProfilingSupported() { + return true; +} + +#else + +void StartProfiling(const std::string& name) { +} + +void StopProfiling() { +} + +void FlushProfiling() { +} + +bool BeingProfiled() { + return false; +} + +void RestartProfilingAfterFork() { +} + +bool IsProfilingSupported() { + return false; +} + +#endif + +#if !defined(OS_WIN) + +ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { + return nullptr; +} + +AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { + return nullptr; +} + +MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { + return nullptr; +} + +#else // defined(OS_WIN) + +namespace { + +struct FunctionSearchContext { + const char* name; + FARPROC function; +}; + +// Callback function to PEImage::EnumImportChunks. +bool FindResolutionFunctionInImports( + const base::win::PEImage &image, const char* module_name, + PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table, + PVOID cookie) { + FunctionSearchContext* context = + reinterpret_cast<FunctionSearchContext*>(cookie); + + DCHECK(context); + DCHECK(!context->function); + + // Our import address table contains pointers to the functions we import + // at this point. Let's retrieve the first such function and use it to + // find the module this import was resolved to by the loader. + const wchar_t* function_in_module = + reinterpret_cast<const wchar_t*>(import_address_table->u1.Function); + + // Retrieve the module by a function in the module. + const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; + HMODULE module = NULL; + if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) { + // This can happen if someone IAT patches us to a thunk. + return true; + } + + // See whether this module exports the function we're looking for. + FARPROC exported_func = ::GetProcAddress(module, context->name); + if (exported_func != NULL) { + // We found it, return the function and terminate the enumeration. + context->function = exported_func; + return false; + } + + // Keep going. + return true; +} + +template <typename FunctionType> +FunctionType FindFunctionInImports(const char* function_name) { + base::win::PEImage image(CURRENT_MODULE()); + + FunctionSearchContext ctx = { function_name, NULL }; + image.EnumImportChunks(FindResolutionFunctionInImports, &ctx, nullptr); + + return reinterpret_cast<FunctionType>(ctx.function); +} + +} // namespace + +ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() { + return FindFunctionInImports<ReturnAddressLocationResolver>( + "ResolveReturnAddressLocation"); +} + +AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() { + return FindFunctionInImports<AddDynamicSymbol>( + "AddDynamicSymbol"); +} + +MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { + return FindFunctionInImports<MoveDynamicSymbol>( + "MoveDynamicSymbol"); +} + +#endif // defined(OS_WIN) + +} // namespace debug +} // namespace base diff --git a/security/sandbox/chromium/base/debug/profiler.h b/security/sandbox/chromium/base/debug/profiler.h new file mode 100644 index 0000000000..1229e06234 --- /dev/null +++ b/security/sandbox/chromium/base/debug/profiler.h @@ -0,0 +1,76 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_PROFILER_H_ +#define BASE_DEBUG_PROFILER_H_ + +#include <stddef.h> + +#include <string> + +#include "base/base_export.h" + +// The Profiler functions allow usage of the underlying sampling based +// profiler. If the application has not been built with the necessary +// flags (-DENABLE_PROFILING and not -DNO_TCMALLOC) then these functions +// are noops. +namespace base { +namespace debug { + +// Start profiling with the supplied name. +// {pid} will be replaced by the process' pid and {count} will be replaced +// by the count of the profile run (starts at 1 with each process). +BASE_EXPORT void StartProfiling(const std::string& name); + +// Stop profiling and write out data. +BASE_EXPORT void StopProfiling(); + +// Force data to be written to file. +BASE_EXPORT void FlushProfiling(); + +// Returns true if process is being profiled. +BASE_EXPORT bool BeingProfiled(); + +// Reset profiling after a fork, which disables timers. +BASE_EXPORT void RestartProfilingAfterFork(); + +// Returns true iff this executable supports profiling. +BASE_EXPORT bool IsProfilingSupported(); + +// There's a class of profilers that use "return address swizzling" to get a +// hook on function exits. This class of profilers uses some form of entry hook, +// like e.g. binary instrumentation, or a compiler flag, that calls a hook each +// time a function is invoked. The hook then switches the return address on the +// stack for the address of an exit hook function, and pushes the original +// return address to a shadow stack of some type. When in due course the CPU +// executes a return to the exit hook, the exit hook will do whatever work it +// does on function exit, then arrange to return to the original return address. +// This class of profiler does not play well with programs that look at the +// return address, as does e.g. V8. V8 uses the return address to certain +// runtime functions to find the JIT code that called it, and from there finds +// the V8 data structures associated to the JS function involved. +// A return address resolution function is used to fix this. It allows such +// programs to resolve a location on stack where a return address originally +// resided, to the shadow stack location where the profiler stashed it. +typedef uintptr_t (*ReturnAddressLocationResolver)( + uintptr_t return_addr_location); + +typedef void (*AddDynamicSymbol)(const void* address, + size_t length, + const char* name, + size_t name_len); +typedef void (*MoveDynamicSymbol)(const void* address, const void* new_address); + + +// If this binary is instrumented and the instrumentation supplies a function +// for each of those purposes, find and return the function in question. +// Otherwise returns NULL. +BASE_EXPORT ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc(); +BASE_EXPORT AddDynamicSymbol GetProfilerAddDynamicSymbolFunc(); +BASE_EXPORT MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc(); + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_PROFILER_H_ |