llvm/compiler-rt/lib/asan/asan_globals.cpp

//===-- asan_globals.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// Handle globals.
//===----------------------------------------------------------------------===//

#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_mapping.h"
#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
#include "asan_suppressions.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_dense_map.h"
#include "sanitizer_common/sanitizer_list.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include "sanitizer_common/sanitizer_thread_safety.h"

namespace __asan {

Global;

struct GlobalListNode {};
ListOfGlobals;

static Mutex mu_for_globals;
static ListOfGlobals list_of_all_globals SANITIZER_GUARDED_BY();

struct DynInitGlobal {};

// We want to remember where a certain range of globals was registered.
struct GlobalRegistrationSite {};
GlobalRegistrationSiteVector;
static GlobalRegistrationSiteVector *global_registration_site_vector;

static ListOfGlobals &GlobalsByIndicator(uptr odr_indicator)
    SANITIZER_REQUIRES(mu_for_globals) {}

static const char *current_dynamic_init_module_name
    SANITIZER_GUARDED_BY(mu_for_globals) =;

DynInitGlobalsByModule;

// TODO: Add a NoDestroy helper, this patter is very common in sanitizers.
static DynInitGlobalsByModule &DynInitGlobals()
    SANITIZER_REQUIRES(mu_for_globals) {}

ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {}

ALWAYS_INLINE void PoisonRedZones(const Global &g) {}

const uptr kMinimalDistanceFromAnotherGlobal =;

static void AddGlobalToList(ListOfGlobals &list, const Global *g) {}

static void UnpoisonDynamicGlobals(IntrusiveList<DynInitGlobal> &dyn_globals,
                                   bool mark_initialized) {}

static void PoisonDynamicGlobals(
    const IntrusiveList<DynInitGlobal> &dyn_globals) {}

static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {}

static void ReportGlobal(const Global &g, const char *prefix) {}

static u32 FindRegistrationSite(const Global *g) {}

int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
                         int max_globals) {}

enum GlobalSymbolState {};

// Check ODR violation for given global G via special ODR indicator. We use
// this method in case compiler instruments global variables through their
// local aliases.
static void CheckODRViolationViaIndicator(const Global *g)
    SANITIZER_REQUIRES(mu_for_globals) {}

// Check ODR violation for given global G by checking if it's already poisoned.
// We use this method in case compiler doesn't use private aliases for global
// variables.
static void CheckODRViolationViaPoisoning(const Global *g)
    SANITIZER_REQUIRES(mu_for_globals) {}

// Clang provides two different ways for global variables protection:
// it can poison the global itself or its private alias. In former
// case we may poison same symbol multiple times, that can help us to
// cheaply detect ODR violation: if we try to poison an already poisoned
// global, we have ODR violation error.
// In latter case, we poison each symbol exactly once, so we use special
// indicator symbol to perform similar check.
// In either case, compiler provides a special odr_indicator field to Global
// structure, that can contain two kinds of values:
//   1) Non-zero value. In this case, odr_indicator is an address of
//      corresponding indicator variable for given global.
//   2) Zero. This means that we don't use private aliases for global variables
//      and can freely check ODR violation with the first method.
//
// This routine chooses between two different methods of ODR violation
// detection.
static inline bool UseODRIndicator(const Global *g) {}

// Register a global variable.
// This function may be called more than once for every global
// so we store the globals in a map.
static void RegisterGlobal(const Global *g) SANITIZER_REQUIRES(mu_for_globals) {}

static void UnregisterGlobal(const Global *g)
    SANITIZER_REQUIRES(mu_for_globals) {}

void StopInitOrderChecking() {}

static bool IsASCII(unsigned char c) {}

const char *MaybeDemangleGlobalName(const char *name) {}

// Check if the global is a zero-terminated ASCII string. If so, print it.
void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) {}

void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g,
                         bool print_module_name) {}

} // namespace __asan

// ---------------------- Interface ---------------- {{{1
usingnamespace__asan;

// Apply __asan_register_globals to all globals found in the same loaded
// executable or shared library as `flag'. The flag tracks whether globals have
// already been registered or not for this image.
void __asan_register_image_globals(uptr *flag) {}

// This mirrors __asan_register_image_globals.
void __asan_unregister_image_globals(uptr *flag) {}

void __asan_register_elf_globals(uptr *flag, void *start, void *stop) {}

void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop) {}

// Register an array of globals.
void __asan_register_globals(__asan_global *globals, uptr n) {}

// Unregister an array of globals.
// We must do this when a shared objects gets dlclosed.
void __asan_unregister_globals(__asan_global *globals, uptr n) {}

// This method runs immediately prior to dynamic initialization in each TU,
// when all dynamically initialized globals are unpoisoned.  This method
// poisons all global variables not defined in this TU, so that a dynamic
// initializer can only touch global variables in the same TU.
void __asan_before_dynamic_init(const char *module_name) {}

// Maybe SANITIZER_CAN_USE_PREINIT_ARRAY is to conservative for `.init_array`,
// however we should not make mistake here. If `UnpoisonBeforeMain` was not
// executed at all we will have false reports on globals.
#if SANITIZER_CAN_USE_PREINIT_ARRAY
// This optimization aims to reduce the overhead of `__asan_after_dynamic_init`
// calls by leveraging incremental unpoisoning/poisoning in
// `__asan_before_dynamic_init`. We expect most `__asan_after_dynamic_init
// calls` to be no-ops. However, to ensure all globals are unpoisoned before the
// `main`, we force `UnpoisonBeforeMain` to fully execute
// `__asan_after_dynamic_init`.

// With lld, `UnpoisonBeforeMain` runs after standard `.init_array`, making it
// the final `__asan_after_dynamic_init` call for the static runtime. In
// contrast, GNU ld executes it earlier, causing subsequent
// `__asan_after_dynamic_init` calls to perform full unpoisoning, losing the
// optimization.
bool allow_after_dynamic_init SANITIZER_GUARDED_BY(mu_for_globals) =;

static void UnpoisonBeforeMain(void) {}

__attribute__((section(".init_array.65537"), used)) static void (
    *asan_after_init_array)(void) =;
#else
// Incremental poisoning is disabled, unpoison globals immediately.
static constexpr bool allow_after_dynamic_init = true;
#endif  // SANITIZER_CAN_USE_PREINIT_ARRAY

// This method runs immediately after dynamic initialization in each TU, when
// all dynamically initialized globals except for those defined in the current
// TU are poisoned.  It simply unpoisons all dynamically initialized globals.
void __asan_after_dynamic_init() {}