1//===-- Instrumentation.h ---------------------------------------*- C++ -*-===// 2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3// See https://llvm.org/LICENSE.txt for license information. 4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5// 6//===----------------------------------------------------------------------===// 7 8#ifndef LLDB_UTILITY_INSTRUMENTATION_H 9#define LLDB_UTILITY_INSTRUMENTATION_H 10 11#include "lldb/Utility/FileSpec.h" 12#include "lldb/Utility/Log.h" 13#include "llvm/ADT/DenseMap.h" 14#include "llvm/ADT/StringRef.h" 15#include "llvm/Support/ErrorHandling.h" 16 17#include <map> 18#include <thread> 19#include <type_traits> 20 21namespace lldb_private { 22namespace instrumentation { 23 24template <typename T, 25 typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0> 26inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { 27 ss << t; 28} 29 30template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, 31 int>::type = 0> 32inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { 33 ss << &t; 34} 35 36template <typename T> 37inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { 38 ss << reinterpret_cast<void *>(t); 39} 40 41template <typename T> 42inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { 43 ss << reinterpret_cast<const void *>(t); 44} 45 46template <> 47inline void stringify_append<char>(llvm::raw_string_ostream &ss, 48 const char *t) { 49 ss << '\"' << t << '\"'; 50} 51 52template <> 53inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, 54 const std::nullptr_t &t) { 55 ss << "\"nullptr\""; 56} 57 58template <typename Head> 59inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { 60 stringify_append(ss, head); 61} 62 63template <typename Head, typename... Tail> 64inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head, 65 const Tail &...tail) { 66 stringify_append(ss, head); 67 ss << ", "; 68 stringify_helper(ss, tail...); 69} 70 71template <typename... Ts> inline std::string stringify_args(const Ts &...ts) { 72 std::string buffer; 73 llvm::raw_string_ostream ss(buffer); 74 stringify_helper(ss, ts...); 75 return ss.str(); 76} 77 78/// RAII object for instrumenting LLDB API functions. 79class Instrumenter { 80public: 81 Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args = {}); 82 ~Instrumenter(); 83 84private: 85 void UpdateBoundary(); 86 87 llvm::StringRef m_pretty_func; 88 89 /// Whether this function call was the one crossing the API boundary. 90 bool m_local_boundary = false; 91}; 92} // namespace instrumentation 93} // namespace lldb_private 94 95#define LLDB_INSTRUMENT() \ 96 lldb_private::instrumentation::Instrumenter _instr(LLVM_PRETTY_FUNCTION); 97 98#define LLDB_INSTRUMENT_VA(...) \ 99 lldb_private::instrumentation::Instrumenter _instr( \ 100 LLVM_PRETTY_FUNCTION, \ 101 lldb_private::instrumentation::stringify_args(__VA_ARGS__)); 102 103#endif // LLDB_UTILITY_INSTRUMENTATION_H 104