11cb0ef41Sopenharmony_ci#ifndef SRC_DEBUG_UTILS_H_ 21cb0ef41Sopenharmony_ci#define SRC_DEBUG_UTILS_H_ 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#include "async_wrap.h" 71cb0ef41Sopenharmony_ci#include "util.h" 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include <algorithm> 101cb0ef41Sopenharmony_ci#include <sstream> 111cb0ef41Sopenharmony_ci#include <string> 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci// Use FORCE_INLINE on functions that have a debug-category-enabled check first 141cb0ef41Sopenharmony_ci// and then ideally only a single function call following it, to maintain 151cb0ef41Sopenharmony_ci// performance for the common case (no debugging used). 161cb0ef41Sopenharmony_ci#ifdef __GNUC__ 171cb0ef41Sopenharmony_ci#define FORCE_INLINE __attribute__((always_inline)) 181cb0ef41Sopenharmony_ci#define COLD_NOINLINE __attribute__((cold, noinline)) 191cb0ef41Sopenharmony_ci#else 201cb0ef41Sopenharmony_ci#define FORCE_INLINE 211cb0ef41Sopenharmony_ci#define COLD_NOINLINE 221cb0ef41Sopenharmony_ci#endif 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_cinamespace node { 251cb0ef41Sopenharmony_ciclass Environment; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_citemplate <typename T> 281cb0ef41Sopenharmony_ciinline std::string ToString(const T& value); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci// C++-style variant of sprintf()/fprintf() that: 311cb0ef41Sopenharmony_ci// - Returns an std::string 321cb0ef41Sopenharmony_ci// - Handles \0 bytes correctly 331cb0ef41Sopenharmony_ci// - Supports %p and %s. %d, %i and %u are aliases for %s. 341cb0ef41Sopenharmony_ci// - Accepts any class that has a ToString() method for stringification. 351cb0ef41Sopenharmony_citemplate <typename... Args> 361cb0ef41Sopenharmony_ciinline std::string SPrintF(const char* format, Args&&... args); 371cb0ef41Sopenharmony_citemplate <typename... Args> 381cb0ef41Sopenharmony_ciinline void FPrintF(FILE* file, const char* format, Args&&... args); 391cb0ef41Sopenharmony_civoid NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci// Listing the AsyncWrap provider types first enables us to cast directly 421cb0ef41Sopenharmony_ci// from a provider type to a debug category. 431cb0ef41Sopenharmony_ci#define DEBUG_CATEGORY_NAMES(V) \ 441cb0ef41Sopenharmony_ci NODE_ASYNC_PROVIDER_TYPES(V) \ 451cb0ef41Sopenharmony_ci V(DIAGNOSTICS) \ 461cb0ef41Sopenharmony_ci V(HUGEPAGES) \ 471cb0ef41Sopenharmony_ci V(INSPECTOR_SERVER) \ 481cb0ef41Sopenharmony_ci V(INSPECTOR_PROFILER) \ 491cb0ef41Sopenharmony_ci V(CODE_CACHE) \ 501cb0ef41Sopenharmony_ci V(NGTCP2_DEBUG) \ 511cb0ef41Sopenharmony_ci V(WASI) \ 521cb0ef41Sopenharmony_ci V(MKSNAPSHOT) \ 531cb0ef41Sopenharmony_ci V(PERMISSION_MODEL) 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cienum class DebugCategory : unsigned int { 561cb0ef41Sopenharmony_ci#define V(name) name, 571cb0ef41Sopenharmony_ci DEBUG_CATEGORY_NAMES(V) 581cb0ef41Sopenharmony_ci#undef V 591cb0ef41Sopenharmony_ci}; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci#define V(name) +1 621cb0ef41Sopenharmony_ciconstexpr unsigned int kDebugCategoryCount = DEBUG_CATEGORY_NAMES(V); 631cb0ef41Sopenharmony_ci#undef V 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ciclass NODE_EXTERN_PRIVATE EnabledDebugList { 661cb0ef41Sopenharmony_ci public: 671cb0ef41Sopenharmony_ci bool FORCE_INLINE enabled(DebugCategory category) const { 681cb0ef41Sopenharmony_ci DCHECK_LT(static_cast<unsigned int>(category), kDebugCategoryCount); 691cb0ef41Sopenharmony_ci return enabled_[static_cast<unsigned int>(category)]; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci // Uses NODE_DEBUG_NATIVE to initialize the categories. The env_vars variable 731cb0ef41Sopenharmony_ci // is parsed if it is not a nullptr, otherwise the system environment 741cb0ef41Sopenharmony_ci // variables are parsed. 751cb0ef41Sopenharmony_ci void Parse(std::shared_ptr<KVStore> env_vars = nullptr, 761cb0ef41Sopenharmony_ci v8::Isolate* isolate = nullptr); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci private: 791cb0ef41Sopenharmony_ci // Enable all categories matching cats. 801cb0ef41Sopenharmony_ci void Parse(const std::string& cats); 811cb0ef41Sopenharmony_ci void set_enabled(DebugCategory category) { 821cb0ef41Sopenharmony_ci DCHECK_LT(static_cast<unsigned int>(category), kDebugCategoryCount); 831cb0ef41Sopenharmony_ci enabled_[static_cast<int>(category)] = true; 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci bool enabled_[kDebugCategoryCount] = {false}; 871cb0ef41Sopenharmony_ci}; 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_citemplate <typename... Args> 901cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(EnabledDebugList* list, 911cb0ef41Sopenharmony_ci DebugCategory cat, 921cb0ef41Sopenharmony_ci const char* format, 931cb0ef41Sopenharmony_ci Args&&... args); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(EnabledDebugList* list, 961cb0ef41Sopenharmony_ci DebugCategory cat, 971cb0ef41Sopenharmony_ci const char* message); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_citemplate <typename... Args> 1001cb0ef41Sopenharmony_ciinline void FORCE_INLINE 1011cb0ef41Sopenharmony_ciDebug(Environment* env, DebugCategory cat, const char* format, Args&&... args); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(Environment* env, 1041cb0ef41Sopenharmony_ci DebugCategory cat, 1051cb0ef41Sopenharmony_ci const char* message); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_citemplate <typename... Args> 1081cb0ef41Sopenharmony_ciinline void Debug(Environment* env, 1091cb0ef41Sopenharmony_ci DebugCategory cat, 1101cb0ef41Sopenharmony_ci const std::string& format, 1111cb0ef41Sopenharmony_ci Args&&... args); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that 1141cb0ef41Sopenharmony_ci// the FORCE_INLINE flag on them doesn't apply to the contents of this function 1151cb0ef41Sopenharmony_ci// as well. 1161cb0ef41Sopenharmony_ci// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing 1171cb0ef41Sopenharmony_ci// this function for speed and it should rather focus on keeping it out of 1181cb0ef41Sopenharmony_ci// hot code paths. In particular, we want to keep the string concatenating code 1191cb0ef41Sopenharmony_ci// out of the function containing the original `Debug()` call. 1201cb0ef41Sopenharmony_citemplate <typename... Args> 1211cb0ef41Sopenharmony_civoid COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap, 1221cb0ef41Sopenharmony_ci const char* format, 1231cb0ef41Sopenharmony_ci Args&&... args); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_citemplate <typename... Args> 1261cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(AsyncWrap* async_wrap, 1271cb0ef41Sopenharmony_ci const char* format, 1281cb0ef41Sopenharmony_ci Args&&... args); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_citemplate <typename... Args> 1311cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(AsyncWrap* async_wrap, 1321cb0ef41Sopenharmony_ci const std::string& format, 1331cb0ef41Sopenharmony_ci Args&&... args); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci// Debug helper for inspecting the currently running `node` executable. 1361cb0ef41Sopenharmony_ciclass NativeSymbolDebuggingContext { 1371cb0ef41Sopenharmony_ci public: 1381cb0ef41Sopenharmony_ci static std::unique_ptr<NativeSymbolDebuggingContext> New(); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci class SymbolInfo { 1411cb0ef41Sopenharmony_ci public: 1421cb0ef41Sopenharmony_ci std::string name; 1431cb0ef41Sopenharmony_ci std::string filename; 1441cb0ef41Sopenharmony_ci size_t line = 0; 1451cb0ef41Sopenharmony_ci size_t dis = 0; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci std::string Display() const; 1481cb0ef41Sopenharmony_ci }; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci NativeSymbolDebuggingContext() = default; 1511cb0ef41Sopenharmony_ci virtual ~NativeSymbolDebuggingContext() = default; 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci virtual SymbolInfo LookupSymbol(void* address) { return {}; } 1541cb0ef41Sopenharmony_ci virtual bool IsMapped(void* address) { return false; } 1551cb0ef41Sopenharmony_ci virtual int GetStackTrace(void** frames, int count) { return 0; } 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci NativeSymbolDebuggingContext(const NativeSymbolDebuggingContext&) = delete; 1581cb0ef41Sopenharmony_ci NativeSymbolDebuggingContext(NativeSymbolDebuggingContext&&) = delete; 1591cb0ef41Sopenharmony_ci NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&) 1601cb0ef41Sopenharmony_ci = delete; 1611cb0ef41Sopenharmony_ci NativeSymbolDebuggingContext operator=(NativeSymbolDebuggingContext&&) 1621cb0ef41Sopenharmony_ci = delete; 1631cb0ef41Sopenharmony_ci static std::vector<std::string> GetLoadedLibraries(); 1641cb0ef41Sopenharmony_ci}; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci// Variant of `uv_loop_close` that tries to be as helpful as possible 1671cb0ef41Sopenharmony_ci// about giving information on currently existing handles, if there are any, 1681cb0ef41Sopenharmony_ci// but still aborts the process. 1691cb0ef41Sopenharmony_civoid CheckedUvLoopClose(uv_loop_t* loop); 1701cb0ef41Sopenharmony_civoid PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream); 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_cinamespace per_process { 1731cb0ef41Sopenharmony_ciextern NODE_EXTERN_PRIVATE EnabledDebugList enabled_debug_list; 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_citemplate <typename... Args> 1761cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(DebugCategory cat, 1771cb0ef41Sopenharmony_ci const char* format, 1781cb0ef41Sopenharmony_ci Args&&... args); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ciinline void FORCE_INLINE Debug(DebugCategory cat, const char* message); 1811cb0ef41Sopenharmony_ci} // namespace per_process 1821cb0ef41Sopenharmony_ci} // namespace node 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci#endif // SRC_DEBUG_UTILS_H_ 187