GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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 "env.h" |
||
8 |
|||
9 |
#include <sstream> |
||
10 |
#include <string> |
||
11 |
|||
12 |
// Use FORCE_INLINE on functions that have a debug-category-enabled check first |
||
13 |
// and then ideally only a single function call following it, to maintain |
||
14 |
// performance for the common case (no debugging used). |
||
15 |
#ifdef __GNUC__ |
||
16 |
#define FORCE_INLINE __attribute__((always_inline)) |
||
17 |
#define COLD_NOINLINE __attribute__((cold, noinline)) |
||
18 |
#else |
||
19 |
#define FORCE_INLINE |
||
20 |
#define COLD_NOINLINE |
||
21 |
#endif |
||
22 |
|||
23 |
namespace node { |
||
24 |
|||
25 |
template <typename... Args> |
||
26 |
inline void FORCE_INLINE Debug(Environment* env, |
||
27 |
DebugCategory cat, |
||
28 |
const char* format, |
||
29 |
Args&&... args) { |
||
30 |
✓✓✓✓ ✓✓✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✓✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✓ |
47578 |
if (!UNLIKELY(env->debug_enabled(cat))) |
31 |
return; |
||
32 |
353 |
fprintf(stderr, format, std::forward<Args>(args)...); |
|
33 |
} |
||
34 |
|||
35 |
inline void FORCE_INLINE Debug(Environment* env, |
||
36 |
DebugCategory cat, |
||
37 |
const char* message) { |
||
38 |
✓✓✓✓ ✓✓✓✓ |
10133 |
if (!UNLIKELY(env->debug_enabled(cat))) |
39 |
return; |
||
40 |
96 |
fprintf(stderr, "%s", message); |
|
41 |
} |
||
42 |
|||
43 |
template <typename... Args> |
||
44 |
124 |
inline void Debug(Environment* env, |
|
45 |
DebugCategory cat, |
||
46 |
const std::string& format, |
||
47 |
Args&&... args) { |
||
48 |
124 |
Debug(env, cat, format.c_str(), std::forward<Args>(args)...); |
|
49 |
124 |
} |
|
50 |
|||
51 |
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that |
||
52 |
// the FORCE_INLINE flag on them doesn't apply to the contents of this function |
||
53 |
// as well. |
||
54 |
// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing |
||
55 |
// this function for speed and it should rather focus on keeping it out of |
||
56 |
// hot code paths. In particular, we want to keep the string concatenating code |
||
57 |
// out of the function containing the original `Debug()` call. |
||
58 |
template <typename... Args> |
||
59 |
124 |
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap, |
|
60 |
const char* format, |
||
61 |
Args&&... args) { |
||
62 |
124 |
Debug(async_wrap->env(), |
|
63 |
124 |
static_cast<DebugCategory>(async_wrap->provider_type()), |
|
64 |
124 |
async_wrap->diagnostic_name() + " " + format + "\n", |
|
65 |
454 |
std::forward<Args>(args)...); |
|
66 |
124 |
} |
|
67 |
|||
68 |
template <typename... Args> |
||
69 |
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap, |
||
70 |
const char* format, |
||
71 |
Args&&... args) { |
||
72 |
DCHECK_NOT_NULL(async_wrap); |
||
73 |
DebugCategory cat = |
||
74 |
1171992 |
static_cast<DebugCategory>(async_wrap->provider_type()); |
|
75 |
✗✓✓✓ ✗✓✗✓ ✗✓✗✓ ✗✓✓✓ ✗✓✗✓ ✓✓✗✓ ✓✓✓✓ ✗✓✓✓ ✓✓✓✓ ✗✓✗✓ ✗✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓✓✗✓ ✗✓✗✓ ✗✓✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✗✓✗✓ ✓✓✓✓ ✗✓✓✓ ✗✓✓✓ ✓✓✗✓ ✗✓✓✓ ✓✓✓✓ ✗✗✗✓ ✓✓✓✓ ✓✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ |
1171994 |
if (!UNLIKELY(async_wrap->env()->debug_enabled(cat))) |
76 |
return; |
||
77 |
✗✓✓✓ |
124 |
UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...); |
78 |
} |
||
79 |
|||
80 |
template <typename... Args> |
||
81 |
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap, |
||
82 |
const std::string& format, |
||
83 |
Args&&... args) { |
||
84 |
Debug(async_wrap, format.c_str(), std::forward<Args>(args)...); |
||
85 |
} |
||
86 |
|||
87 |
// Debug helper for inspecting the currently running `node` executable. |
||
88 |
class NativeSymbolDebuggingContext { |
||
89 |
public: |
||
90 |
static std::unique_ptr<NativeSymbolDebuggingContext> New(); |
||
91 |
|||
92 |
296 |
class SymbolInfo { |
|
93 |
public: |
||
94 |
std::string name; |
||
95 |
std::string filename; |
||
96 |
size_t line = 0; |
||
97 |
size_t dis = 0; |
||
98 |
|||
99 |
std::string Display() const; |
||
100 |
}; |
||
101 |
|||
102 |
19 |
NativeSymbolDebuggingContext() = default; |
|
103 |
✗✓ | 19 |
virtual ~NativeSymbolDebuggingContext() = default; |
104 |
|||
105 |
virtual SymbolInfo LookupSymbol(void* address) { return {}; } |
||
106 |
virtual bool IsMapped(void* address) { return false; } |
||
107 |
virtual int GetStackTrace(void** frames, int count) { return 0; } |
||
108 |
|||
109 |
NativeSymbolDebuggingContext(const NativeSymbolDebuggingContext&) = delete; |
||
110 |
NativeSymbolDebuggingContext(NativeSymbolDebuggingContext&&) = delete; |
||
111 |
NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&) |
||
112 |
= delete; |
||
113 |
NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&&) |
||
114 |
= delete; |
||
115 |
static std::vector<std::string> GetLoadedLibraries(); |
||
116 |
}; |
||
117 |
|||
118 |
// Variant of `uv_loop_close` that tries to be as helpful as possible |
||
119 |
// about giving information on currently existing handles, if there are any, |
||
120 |
// but still aborts the process. |
||
121 |
void CheckedUvLoopClose(uv_loop_t* loop); |
||
122 |
void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream); |
||
123 |
|||
124 |
} // namespace node |
||
125 |
|||
126 |
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
||
127 |
|||
128 |
#endif // SRC_DEBUG_UTILS_H_ |
Generated by: GCOVR (Version 3.4) |