GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: debug_utils.h Lines: 6 9 66.7 %
Date: 2022-08-31 04:20:31 Branches: 0 0 - %

Line Branch Exec Source
1
#ifndef SRC_DEBUG_UTILS_H_
2
#define SRC_DEBUG_UTILS_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "async_wrap.h"
7
#include "util.h"
8
9
#include <algorithm>
10
#include <sstream>
11
#include <string>
12
13
// Use FORCE_INLINE on functions that have a debug-category-enabled check first
14
// and then ideally only a single function call following it, to maintain
15
// performance for the common case (no debugging used).
16
#ifdef __GNUC__
17
#define FORCE_INLINE __attribute__((always_inline))
18
#define COLD_NOINLINE __attribute__((cold, noinline))
19
#else
20
#define FORCE_INLINE
21
#define COLD_NOINLINE
22
#endif
23
24
namespace node {
25
class Environment;
26
27
template <typename T>
28
inline std::string ToString(const T& value);
29
30
// C++-style variant of sprintf()/fprintf() that:
31
// - Returns an std::string
32
// - Handles \0 bytes correctly
33
// - Supports %p and %s. %d, %i and %u are aliases for %s.
34
// - Accepts any class that has a ToString() method for stringification.
35
template <typename... Args>
36
inline std::string SPrintF(const char* format, Args&&... args);
37
template <typename... Args>
38
inline void FPrintF(FILE* file, const char* format, Args&&... args);
39
void NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str);
40
41
// Listing the AsyncWrap provider types first enables us to cast directly
42
// from a provider type to a debug category.
43
#define DEBUG_CATEGORY_NAMES(V)                                                \
44
  NODE_ASYNC_PROVIDER_TYPES(V)                                                 \
45
  V(DIAGNOSTICS)                                                               \
46
  V(HUGEPAGES)                                                                 \
47
  V(INSPECTOR_SERVER)                                                          \
48
  V(INSPECTOR_PROFILER)                                                        \
49
  V(CODE_CACHE)                                                                \
50
  V(NGTCP2_DEBUG)                                                              \
51
  V(WASI)                                                                      \
52
  V(MKSNAPSHOT)
53
54
enum class DebugCategory : unsigned int {
55
#define V(name) name,
56
  DEBUG_CATEGORY_NAMES(V)
57
#undef V
58
};
59
60
#define V(name) +1
61
constexpr unsigned int kDebugCategoryCount = DEBUG_CATEGORY_NAMES(V);
62
#undef V
63
64
class NODE_EXTERN_PRIVATE EnabledDebugList {
65
 public:
66
  bool FORCE_INLINE enabled(DebugCategory category) const {
67
    DCHECK_LT(static_cast<unsigned int>(category), kDebugCategoryCount);
68
2262723
    return enabled_[static_cast<unsigned int>(category)];
69
  }
70
71
  // Uses NODE_DEBUG_NATIVE to initialize the categories. The env_vars variable
72
  // is parsed if it is not a nullptr, otherwise the system environment
73
  // variables are parsed.
74
  void Parse(std::shared_ptr<KVStore> env_vars = nullptr,
75
             v8::Isolate* isolate = nullptr);
76
77
 private:
78
  // Enable all categories matching cats.
79
  void Parse(const std::string& cats);
80
115
  void set_enabled(DebugCategory category) {
81
    DCHECK_LT(static_cast<unsigned int>(category), kDebugCategoryCount);
82
115
    enabled_[static_cast<int>(category)] = true;
83
115
  }
84
85
  bool enabled_[kDebugCategoryCount] = {false};
86
};
87
88
template <typename... Args>
89
inline void FORCE_INLINE Debug(EnabledDebugList* list,
90
                               DebugCategory cat,
91
                               const char* format,
92
                               Args&&... args);
93
94
inline void FORCE_INLINE Debug(EnabledDebugList* list,
95
                               DebugCategory cat,
96
                               const char* message);
97
98
template <typename... Args>
99
inline void FORCE_INLINE
100
Debug(Environment* env, DebugCategory cat, const char* format, Args&&... args);
101
102
inline void FORCE_INLINE Debug(Environment* env,
103
                               DebugCategory cat,
104
                               const char* message);
105
106
template <typename... Args>
107
inline void Debug(Environment* env,
108
                  DebugCategory cat,
109
                  const std::string& format,
110
                  Args&&... args);
111
112
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that
113
// the FORCE_INLINE flag on them doesn't apply to the contents of this function
114
// as well.
115
// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing
116
// this function for speed and it should rather focus on keeping it out of
117
// hot code paths. In particular, we want to keep the string concatenating code
118
// out of the function containing the original `Debug()` call.
119
template <typename... Args>
120
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
121
                                               const char* format,
122
                                               Args&&... args);
123
124
template <typename... Args>
125
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
126
                               const char* format,
127
                               Args&&... args);
128
129
template <typename... Args>
130
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
131
                               const std::string& format,
132
                               Args&&... args);
133
134
// Debug helper for inspecting the currently running `node` executable.
135
class NativeSymbolDebuggingContext {
136
 public:
137
  static std::unique_ptr<NativeSymbolDebuggingContext> New();
138
139
  class SymbolInfo {
140
   public:
141
    std::string name;
142
    std::string filename;
143
    size_t line = 0;
144
    size_t dis = 0;
145
146
    std::string Display() const;
147
  };
148
149
37
  NativeSymbolDebuggingContext() = default;
150
74
  virtual ~NativeSymbolDebuggingContext() = default;
151
152
  virtual SymbolInfo LookupSymbol(void* address) { return {}; }
153
  virtual bool IsMapped(void* address) { return false; }
154
  virtual int GetStackTrace(void** frames, int count) { return 0; }
155
156
  NativeSymbolDebuggingContext(const NativeSymbolDebuggingContext&) = delete;
157
  NativeSymbolDebuggingContext(NativeSymbolDebuggingContext&&) = delete;
158
  NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&)
159
    = delete;
160
  NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&&)
161
    = delete;
162
  static std::vector<std::string> GetLoadedLibraries();
163
};
164
165
// Variant of `uv_loop_close` that tries to be as helpful as possible
166
// about giving information on currently existing handles, if there are any,
167
// but still aborts the process.
168
void CheckedUvLoopClose(uv_loop_t* loop);
169
void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream);
170
171
namespace per_process {
172
extern NODE_EXTERN_PRIVATE EnabledDebugList enabled_debug_list;
173
174
template <typename... Args>
175
inline void FORCE_INLINE Debug(DebugCategory cat,
176
                               const char* format,
177
                               Args&&... args);
178
179
inline void FORCE_INLINE Debug(DebugCategory cat, const char* message);
180
}  // namespace per_process
181
}  // namespace node
182
183
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
184
185
#endif  // SRC_DEBUG_UTILS_H_