| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 
 | //===-- xray_init.cpp -------------------------------------------*- C++ -*-===//
//
// 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 XRay, a dynamic runtime instrumentation system.
//
// XRay initialisation logic.
//===----------------------------------------------------------------------===//
#include <fcntl.h>
#include <strings.h>
#include <unistd.h>
#include "sanitizer_common/sanitizer_common.h"
#include "xray_defs.h"
#include "xray_flags.h"
#include "xray_interface_internal.h"
extern "C" {
void __xray_init();
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak));
extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak));
#if SANITIZER_APPLE
// HACK: This is a temporary workaround to make XRay build on 
// Darwin, but it will probably not work at runtime.
const XRaySledEntry __start_xray_instr_map[] = {};
extern const XRaySledEntry __stop_xray_instr_map[] = {};
extern const XRayFunctionSledIndex __start_xray_fn_idx[] = {};
extern const XRayFunctionSledIndex __stop_xray_fn_idx[] = {};
#endif
}
using namespace __xray;
// When set to 'true' this means the XRay runtime has been initialised. We use
// the weak symbols defined above (__start_xray_inst_map and
// __stop_xray_instr_map) to initialise the instrumentation map that XRay uses
// for runtime patching/unpatching of instrumentation points.
//
// FIXME: Support DSO instrumentation maps too. The current solution only works
// for statically linked executables.
atomic_uint8_t XRayInitialized{0};
// This should always be updated before XRayInitialized is updated.
SpinMutex XRayInstrMapMutex;
XRaySledMap XRayInstrMap;
// Global flag to determine whether the flags have been initialized.
atomic_uint8_t XRayFlagsInitialized{0};
// A mutex to allow only one thread to initialize the XRay data structures.
SpinMutex XRayInitMutex;
// __xray_init() will do the actual loading of the current process' memory map
// and then proceed to look for the .xray_instr_map section/segment.
void __xray_init() XRAY_NEVER_INSTRUMENT {
  SpinMutexLock Guard(&XRayInitMutex);
  // Short-circuit if we've already initialized XRay before.
  if (atomic_load(&XRayInitialized, memory_order_acquire))
    return;
  // XRAY is not compatible with PaX MPROTECT
  CheckMPROTECT();
  if (!atomic_load(&XRayFlagsInitialized, memory_order_acquire)) {
    initializeFlags();
    atomic_store(&XRayFlagsInitialized, true, memory_order_release);
  }
  if (__start_xray_instr_map == nullptr) {
    if (Verbosity())
      Report("XRay instrumentation map missing. Not initializing XRay.\n");
    return;
  }
  {
    SpinMutexLock Guard(&XRayInstrMapMutex);
    XRayInstrMap.Sleds = __start_xray_instr_map;
    XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
    if (__start_xray_fn_idx != nullptr) {
      XRayInstrMap.SledsIndex = __start_xray_fn_idx;
      XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx;
    } else {
      size_t CountFunctions = 0;
      uint64_t LastFnAddr = 0;
      for (std::size_t I = 0; I < XRayInstrMap.Entries; I++) {
        const auto &Sled = XRayInstrMap.Sleds[I];
        const auto Function = Sled.function();
        if (Function != LastFnAddr) {
          CountFunctions++;
          LastFnAddr = Function;
        }
      }
      XRayInstrMap.Functions = CountFunctions;
    }
  }
  atomic_store(&XRayInitialized, true, memory_order_release);
#ifndef XRAY_NO_PREINIT
  if (flags()->patch_premain)
    __xray_patch();
#endif
}
// FIXME: Make check-xray tests work on FreeBSD without
// SANITIZER_CAN_USE_PREINIT_ARRAY.
// See sanitizer_internal_defs.h where the macro is defined.
// Calling unresolved PLT functions in .preinit_array can lead to deadlock on
// FreeBSD but here it seems benign.
#if !defined(XRAY_NO_PREINIT) &&                                               \
    (SANITIZER_CAN_USE_PREINIT_ARRAY || SANITIZER_FREEBSD)
// Only add the preinit array initialization if the sanitizers can.
__attribute__((section(".preinit_array"),
               used)) void (*__local_xray_preinit)(void) = __xray_init;
#else
// If we cannot use the .preinit_array section, we should instead use dynamic
// initialisation.
__attribute__ ((constructor (0)))
static void __local_xray_dyninit() {
  __xray_init();
}
#endif
 |