summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/base/debug
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /security/sandbox/chromium/base/debug
parentInitial commit. (diff)
downloadfirefox-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.cc16
-rw-r--r--security/sandbox/chromium/base/debug/alias.h44
-rw-r--r--security/sandbox/chromium/base/debug/crash_logging.h104
-rw-r--r--security/sandbox/chromium/base/debug/debugger.h50
-rw-r--r--security/sandbox/chromium/base/debug/leak_annotations.h46
-rw-r--r--security/sandbox/chromium/base/debug/profiler.cc180
-rw-r--r--security/sandbox/chromium/base/debug/profiler.h76
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_