asherah 1.3.27 → 1.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cobhan.h CHANGED
@@ -35,11 +35,8 @@ calculate_cobhan_buffer_allocation_size(size_t data_len_bytes) {
35
35
  }
36
36
 
37
37
  __attribute__((always_inline)) inline void
38
- configure_cbuffer(char *cobhan_buffer, size_t length) {
39
- if (unlikely(verbose_flag)) {
40
- debug_log(__func__, "configure_cbuffer(" + format_ptr(cobhan_buffer) +
41
- ", " + std::to_string(length) + ")");
42
- }
38
+ configure_cbuffer(Logger &logger, char *cobhan_buffer, size_t length) {
39
+ logger.debug_log_configure_cbuffer(__func__, cobhan_buffer, length);
43
40
 
44
41
  *((int32_t *)cobhan_buffer) = length;
45
42
  // Reserved for future use
@@ -61,12 +58,13 @@ get_canary_ptr(char *cobhan_buffer) {
61
58
  return cbuffer_data_ptr(cobhan_buffer) + cobhan_buffer_size_bytes + 1;
62
59
  }
63
60
 
64
- __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
61
+ __attribute__((always_inline)) inline bool check_canary_ptr(Logger &logger,
62
+ char *canary_ptr) {
65
63
  int32_t zero_value = *((int32_t *)(canary_ptr));
66
64
  if (zero_value != 0) {
67
65
  std::string error_msg =
68
66
  "Canary check failed: " + std::to_string(zero_value) + " != 0";
69
- error_log(__func__, error_msg);
67
+ logger.error_log(__func__, error_msg);
70
68
  return false;
71
69
  }
72
70
  int32_t canary_value = *((int32_t *)(canary_ptr + sizeof(int32_t)));
@@ -74,61 +72,61 @@ __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
74
72
  std::string error_msg =
75
73
  "Canary check failed: " + std::to_string(canary_value) +
76
74
  " != " + std::to_string(canary_constant);
77
- error_log(__func__, error_msg);
75
+ logger.error_log(__func__, error_msg);
78
76
  return false;
79
77
  }
80
78
  return true;
81
79
  }
82
80
 
83
81
  __attribute__((always_inline)) inline std::unique_ptr<char[]>
84
- heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
82
+ heap_allocate_cbuffer(Logger &logger, const char *variable_name,
83
+ size_t size_bytes) {
85
84
  size_t cobhan_buffer_allocation_size =
86
85
  calculate_cobhan_buffer_allocation_size(size_bytes);
87
86
 
88
- if (unlikely(verbose_flag)) {
89
- debug_log_new(__func__, variable_name, cobhan_buffer_allocation_size);
90
- }
87
+ logger.debug_log_new(__func__, variable_name, cobhan_buffer_allocation_size);
91
88
 
92
89
  char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_allocation_size];
93
90
  if (unlikely(cobhan_buffer == nullptr)) {
94
91
  std::string error_msg = "new[" +
95
92
  std::to_string(cobhan_buffer_allocation_size) +
96
93
  "] returned null";
97
- error_log(__func__, error_msg);
94
+ logger.error_log(__func__, error_msg);
98
95
  return nullptr;
99
96
  }
100
97
  std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
101
- configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
98
+ configure_cbuffer(logger, cobhan_buffer, size_bytes + safety_padding_bytes);
102
99
  return cobhan_buffer_unique_ptr;
103
100
  }
104
101
 
105
- #define ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, unique_ptr, \
106
- max_stack_alloc_size, function_name) \
102
+ #define ALLOCATE_CBUFFER_UNIQUE_PTR(logger, cobhan_buffer, buffer_size, \
103
+ unique_ptr, max_stack_alloc_size, \
104
+ function_name) \
107
105
  do { \
108
106
  if (buffer_size < max_stack_alloc_size) { \
109
107
  /* If the buffer is small enough, allocate it on the stack */ \
110
108
  size_t cobhan_buffer##_cobhan_buffer_allocation_size = \
111
109
  calculate_cobhan_buffer_allocation_size(buffer_size); \
112
- debug_log_alloca(function_name, #cobhan_buffer, \
113
- cobhan_buffer##_cobhan_buffer_allocation_size); \
110
+ logger.debug_log_alloca(function_name, #cobhan_buffer, \
111
+ cobhan_buffer##_cobhan_buffer_allocation_size); \
114
112
  cobhan_buffer = \
115
113
  (char *)alloca(cobhan_buffer##_cobhan_buffer_allocation_size); \
116
- configure_cbuffer(cobhan_buffer, buffer_size); \
114
+ configure_cbuffer(logger, cobhan_buffer, buffer_size); \
117
115
  } else { \
118
116
  /* Otherwise, allocate it on the heap */ \
119
- unique_ptr = heap_allocate_cbuffer(#cobhan_buffer, buffer_size); \
117
+ unique_ptr = heap_allocate_cbuffer(logger, #cobhan_buffer, buffer_size); \
120
118
  cobhan_buffer = unique_ptr.get(); \
121
119
  } \
122
120
  if (unlikely(cobhan_buffer == nullptr)) { \
123
- log_error_and_throw(function_name, \
124
- "Failed to allocate " #cobhan_buffer); \
121
+ logger.log_error_and_throw(function_name, \
122
+ "Failed to allocate " #cobhan_buffer); \
125
123
  } \
126
124
  } while (0);
127
125
 
128
- #define ALLOCATE_CBUFFER(cobhan_buffer, buffer_size, max_stack_alloc_size, \
129
- function_name) \
126
+ #define ALLOCATE_CBUFFER(logger, cobhan_buffer, buffer_size, \
127
+ max_stack_alloc_size, function_name) \
130
128
  std::unique_ptr<char[]> cobhan_buffer##_unique_ptr; \
131
- ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, \
129
+ ALLOCATE_CBUFFER_UNIQUE_PTR(logger, cobhan_buffer, buffer_size, \
132
130
  cobhan_buffer##_unique_ptr, \
133
131
  max_stack_alloc_size, function_name);
134
132
 
@@ -9,14 +9,15 @@
9
9
  std::string napi_status_to_string(napi_status status);
10
10
 
11
11
  __attribute__((always_inline)) inline size_t
12
- nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
12
+ nstring_utf8_byte_length(Napi::Env &env, Logger &logger, Napi::String &str) {
13
13
  napi_status status;
14
14
  size_t utf8_length;
15
15
 
16
16
  status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
17
17
  if (unlikely(status != napi_ok)) {
18
- error_log(__func__, "napi_get_value_string_utf8 length check failed: " +
19
- napi_status_to_string(status));
18
+ logger.error_log(__func__,
19
+ "napi_get_value_string_utf8 length check failed: " +
20
+ napi_status_to_string(status));
20
21
  return (size_t)(-1);
21
22
  }
22
23
 
@@ -24,28 +25,23 @@ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
24
25
  }
25
26
 
26
27
  __attribute__((always_inline)) inline char *
27
- copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
28
+ copy_nstring_to_cbuffer(Napi::Env &env, Logger &logger, Napi::String &str,
28
29
  size_t str_utf8_byte_length, char *cobhan_buffer,
29
30
  size_t *byte_length) {
30
31
 
31
32
  size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
32
33
  if (unlikely(cobhan_buffer_size_bytes <= 0)) {
33
- error_log(__func__, "Invalid cobhan buffer byte length");
34
+ logger.error_log(__func__, "Invalid cobhan buffer byte length");
34
35
  return nullptr;
35
36
  }
36
37
 
37
38
  if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
38
- error_log(__func__, "String too large for cobhan buffer");
39
+ logger.error_log(__func__, "String too large for cobhan buffer");
39
40
  return nullptr;
40
41
  }
41
42
 
42
- if (unlikely(verbose_flag)) {
43
- debug_log(__func__,
44
- "Copying " + std::to_string(str_utf8_byte_length) + " bytes to " +
45
- format_ptr(cbuffer_data_ptr(cobhan_buffer)) + " - " +
46
- format_ptr((cbuffer_data_ptr(cobhan_buffer) +
47
- str_utf8_byte_length)));
48
- }
43
+ logger.debug_log_copy_buffer(__func__, cbuffer_data_ptr(cobhan_buffer),
44
+ str_utf8_byte_length);
49
45
 
50
46
  napi_status status;
51
47
  size_t copied_bytes;
@@ -55,31 +51,31 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
55
51
  status = napi_get_value_string_utf8(env, str, cbuffer_data_ptr(cobhan_buffer),
56
52
  str_utf8_byte_length + 1, &copied_bytes);
57
53
  if (unlikely(status != napi_ok)) {
58
- error_log(__func__, "Napi utf8 string conversion failure: " +
59
- napi_status_to_string(status));
54
+ logger.error_log(__func__, "Napi utf8 string conversion failure: " +
55
+ napi_status_to_string(status));
60
56
  return nullptr;
61
57
  }
62
58
 
63
59
  if (unlikely(copied_bytes != str_utf8_byte_length)) {
64
- error_log(__func__, "Did not copy expected number of bytes " +
65
- std::to_string(str_utf8_byte_length) + " copied " +
66
- std::to_string(copied_bytes));
60
+ logger.error_log(__func__, "Did not copy expected number of bytes " +
61
+ std::to_string(str_utf8_byte_length) +
62
+ " copied " + std::to_string(copied_bytes));
67
63
  return nullptr;
68
64
  }
69
65
 
70
- configure_cbuffer(cobhan_buffer, copied_bytes);
66
+ configure_cbuffer(logger, cobhan_buffer, copied_bytes);
71
67
 
72
68
  *byte_length = copied_bytes;
73
69
  return cobhan_buffer;
74
70
  }
75
71
 
76
72
  __attribute__((always_inline)) inline Napi::String
77
- cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
73
+ cbuffer_to_nstring(Napi::Env &env, Logger &logger, char *cobhan_buffer) {
78
74
  napi_value output;
79
75
 
80
76
  int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
81
77
  if (cobhan_buffer_size_bytes <= 0) {
82
- log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
78
+ logger.log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
83
79
  }
84
80
 
85
81
  // Using C function because it allows length delimited input
@@ -87,18 +83,18 @@ cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
87
83
  env, cbuffer_data_ptr(cobhan_buffer), cobhan_buffer_size_bytes, &output);
88
84
 
89
85
  if (unlikely(status != napi_ok)) {
90
- log_error_and_throw(__func__, "napi_create_string_utf8 failed: " +
91
- napi_status_to_string(status));
86
+ logger.log_error_and_throw(__func__, "napi_create_string_utf8 failed: " +
87
+ napi_status_to_string(status));
92
88
  }
93
89
 
94
90
  return Napi::String(env, output);
95
91
  }
96
92
 
97
93
  __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
98
- cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
94
+ cbuffer_to_nbuffer(Napi::Env &env, Logger &logger, char *cobhan_buffer) {
99
95
  int32_t cobhan_buffer_byte_length = cbuffer_byte_length(cobhan_buffer);
100
96
  if (unlikely(cobhan_buffer_byte_length <= 0)) {
101
- log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
97
+ logger.log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
102
98
  }
103
99
 
104
100
  Napi::Buffer<unsigned char> nbuffer = Napi::Buffer<unsigned char>::Copy(
@@ -106,91 +102,90 @@ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
106
102
  cobhan_buffer_byte_length);
107
103
 
108
104
  if (unlikely(nbuffer.ByteLength() != (size_t)cobhan_buffer_byte_length)) {
109
- log_error_and_throw(__func__,
110
- "Failed to copy cobhan buffer to napi buffer");
105
+ logger.log_error_and_throw(__func__,
106
+ "Failed to copy cobhan buffer to napi buffer");
111
107
  }
112
108
 
113
109
  return nbuffer;
114
110
  }
115
111
 
116
112
  __attribute__((always_inline)) inline char *
117
- copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
113
+ copy_nbuffer_to_cbuffer(Napi::Env &env, Logger &logger,
114
+ Napi::Buffer<unsigned char> &nbuffer,
118
115
  char *cobhan_buffer) {
119
116
 
120
117
  int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
121
118
  if (unlikely(cobhan_buffer_size_bytes <= 0)) {
122
- error_log(__func__, "Invalid cobhan buffer byte length");
119
+ logger.error_log(__func__, "Invalid cobhan buffer byte length");
123
120
  return nullptr;
124
121
  }
125
122
 
126
123
  size_t nbuffer_byte_length = nbuffer.ByteLength();
127
124
  if (nbuffer_byte_length > INT32_MAX ||
128
125
  cobhan_buffer_size_bytes < (int32_t)nbuffer_byte_length) {
129
- error_log(__func__, "Buffer too large for cobhan buffer");
126
+ logger.error_log(__func__, "Buffer too large for cobhan buffer");
130
127
  return nullptr;
131
128
  }
132
129
 
133
- if (unlikely(verbose_flag)) {
134
- debug_log(__func__,
135
- "Copying " + std::to_string(nbuffer_byte_length) + " bytes to " +
136
- format_ptr(cbuffer_data_ptr(cobhan_buffer)) + " - " +
137
- format_ptr(
138
- (cbuffer_data_ptr(cobhan_buffer) + nbuffer_byte_length)));
139
- }
130
+ logger.debug_log_copy_buffer(__func__, cbuffer_data_ptr(cobhan_buffer),
131
+ nbuffer_byte_length);
140
132
 
141
133
  memcpy(cbuffer_data_ptr(cobhan_buffer), nbuffer.Data(), nbuffer_byte_length);
142
- configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
134
+ configure_cbuffer(logger, cobhan_buffer, nbuffer_byte_length);
143
135
  return cobhan_buffer;
144
136
  }
145
137
 
146
138
  // These are macros due to the use of alloca()
147
139
 
148
- #define NAPI_STRING_TO_CBUFFER(env, napi_string, cobhan_buffer, bytes_copied, \
149
- max_stack_alloc_size, function_name) \
140
+ #define NAPI_STRING_TO_CBUFFER(env, logger, napi_string, cobhan_buffer, \
141
+ bytes_copied, max_stack_alloc_size, \
142
+ function_name) \
150
143
  std::unique_ptr<char[]> napi_string##_unique_ptr; \
151
144
  do { \
152
145
  /* Determine size */ \
153
146
  size_t napi_string##_utf8_byte_length = \
154
- nstring_utf8_byte_length(env, napi_string); \
147
+ nstring_utf8_byte_length(env, logger, napi_string); \
155
148
  if (unlikely(napi_string##_utf8_byte_length == (size_t)(-1))) { \
156
- log_error_and_throw(function_name, \
157
- "Failed to get " #napi_string " utf8 length"); \
149
+ logger.log_error_and_throw(function_name, "Failed to get " #napi_string \
150
+ " utf8 length"); \
158
151
  } \
159
152
  if (unlikely(napi_string##_utf8_byte_length == 0)) { \
160
- log_error_and_throw(function_name, #napi_string " is empty"); \
153
+ logger.log_error_and_throw(function_name, #napi_string " is empty"); \
161
154
  } \
162
155
  /* Allocate */ \
163
- ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_string##_utf8_byte_length, \
164
- napi_string##_unique_ptr, \
165
- max_stack_alloc_size, function_name); \
156
+ ALLOCATE_CBUFFER_UNIQUE_PTR( \
157
+ logger, cobhan_buffer, napi_string##_utf8_byte_length, \
158
+ napi_string##_unique_ptr, max_stack_alloc_size, function_name); \
166
159
  /* Copy */ \
167
- cobhan_buffer = copy_nstring_to_cbuffer(env, napi_string, \
160
+ cobhan_buffer = copy_nstring_to_cbuffer(env, logger, napi_string, \
168
161
  napi_string##_utf8_byte_length, \
169
162
  cobhan_buffer, &bytes_copied); \
170
163
  if (unlikely(cobhan_buffer == nullptr)) { \
171
- log_error_and_throw(function_name, \
172
- "Failed to copy " #napi_string " to cobhan buffer"); \
164
+ logger.log_error_and_throw(function_name, "Failed to copy " #napi_string \
165
+ " to cobhan buffer"); \
173
166
  } \
174
167
  } while (0);
175
168
 
176
- #define NAPI_BUFFER_TO_CBUFFER(env, napi_buffer, cobhan_buffer, bytes_copied, \
177
- max_stack_alloc_size, function_name) \
169
+ #define NAPI_BUFFER_TO_CBUFFER(env, logger, napi_buffer, cobhan_buffer, \
170
+ bytes_copied, max_stack_alloc_size, \
171
+ function_name) \
178
172
  std::unique_ptr<char[]> napi_buffer##_unique_ptr; \
179
173
  do { \
180
174
  /* Determine size */ \
181
175
  size_t napi_buffer##_byte_length = napi_buffer.ByteLength(); \
182
176
  if (unlikely(napi_buffer##_byte_length == 0)) { \
183
- log_error_and_throw(function_name, #napi_buffer " is empty"); \
177
+ logger.log_error_and_throw(function_name, #napi_buffer " is empty"); \
184
178
  } \
185
179
  /* Allocate */ \
186
- ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_buffer##_byte_length, \
187
- napi_buffer##_unique_ptr, \
188
- max_stack_alloc_size, function_name); \
180
+ ALLOCATE_CBUFFER_UNIQUE_PTR( \
181
+ logger, cobhan_buffer, napi_buffer##_byte_length, \
182
+ napi_buffer##_unique_ptr, max_stack_alloc_size, function_name); \
189
183
  /* Copy */ \
190
- cobhan_buffer = copy_nbuffer_to_cbuffer(env, napi_buffer, cobhan_buffer); \
184
+ cobhan_buffer = \
185
+ copy_nbuffer_to_cbuffer(env, logger, napi_buffer, cobhan_buffer); \
191
186
  if (unlikely(cobhan_buffer == nullptr)) { \
192
- log_error_and_throw(function_name, \
193
- "Failed to copy " #napi_buffer " to cobhan buffer"); \
187
+ logger.log_error_and_throw(function_name, "Failed to copy " #napi_buffer \
188
+ " to cobhan buffer"); \
194
189
  } \
195
190
  bytes_copied = napi_buffer##_byte_length; \
196
191
  } while (0);
package/src/logging.cc CHANGED
@@ -1,2 +1,218 @@
1
- #include <cstdint>
2
- __attribute__((used)) int32_t verbose_flag = 0;
1
+ #include "logging.h"
2
+
3
+ Logger::Logger() {}
4
+
5
+ Logger::Logger(Napi::Function new_log_hook) {
6
+ if (unlikely(new_log_hook.IsEmpty())) {
7
+ throw new std::runtime_error("new_log_hook cannot be nullptr");
8
+ }
9
+ log_hook = Napi::Persistent(new_log_hook);
10
+ }
11
+
12
+ Logger::~Logger() {
13
+ if (!log_hook.IsEmpty()) {
14
+ log_hook.Unref();
15
+ }
16
+ }
17
+
18
+ void Logger::set_log_hook(Napi::Function new_log_hook) {
19
+ if (unlikely(new_log_hook.IsEmpty())) {
20
+ throw new std::runtime_error("new_log_hook cannot be nullptr");
21
+ }
22
+ if (!log_hook.IsEmpty()) {
23
+ log_hook.Unref();
24
+ }
25
+ log_hook = Napi::Persistent(new_log_hook);
26
+ }
27
+
28
+ void Logger::set_verbose_flag(int32_t verbose) { verbose_flag = verbose; }
29
+
30
+ void Logger::debug_log(const char *function_name, const char *message) {
31
+ if (unlikely(verbose_flag)) {
32
+ if (unlikely(log_hook.IsEmpty())) {
33
+ stderr_debug_log(function_name, message);
34
+ } else {
35
+ Napi::Env env = log_hook.Env();
36
+ Napi::HandleScope scope(env);
37
+ Napi::Function log_hook_function = log_hook.Value();
38
+ log_hook_function.Call(
39
+ {Napi::Number::New(env, posix_log_level_debug),
40
+ Napi::String::New(env, asherah_node_prefix + function_name + ": " +
41
+ message)});
42
+ }
43
+ }
44
+ }
45
+
46
+ void Logger::debug_log(const char *function_name, std::string message) {
47
+ if (unlikely(verbose_flag)) {
48
+ if (unlikely(log_hook.IsEmpty())) {
49
+ stderr_debug_log(function_name, message);
50
+ } else {
51
+ Napi::Env env = log_hook.Env();
52
+ Napi::HandleScope scope(env);
53
+ Napi::Function log_hook_function = log_hook.Value();
54
+ log_hook_function.Call(
55
+ {Napi::Number::New(env, posix_log_level_debug),
56
+ Napi::String::New(env, asherah_node_prefix + function_name + ": " +
57
+ message)});
58
+ }
59
+ }
60
+ }
61
+
62
+ void Logger::debug_log_alloca(const char *function_name,
63
+ const char *variable_name, size_t length) {
64
+ if (unlikely(verbose_flag)) {
65
+ if (unlikely(log_hook.IsEmpty())) {
66
+ stderr_debug_log_alloca(function_name, variable_name, length);
67
+ } else {
68
+ Napi::Env env = log_hook.Env();
69
+ Napi::HandleScope scope(env);
70
+ Napi::Function log_hook_function = log_hook.Value();
71
+ log_hook_function.Call(
72
+ {Napi::Number::New(env, posix_log_level_debug),
73
+ Napi::String::New(env, asherah_node_prefix + function_name +
74
+ ": Calling alloca(" +
75
+ std::to_string(length) +
76
+ ") (stack) for " + variable_name)});
77
+ }
78
+ }
79
+ }
80
+
81
+ void Logger::debug_log_new(const char *function_name, const char *variable_name,
82
+ size_t length) {
83
+ if (unlikely(verbose_flag)) {
84
+ if (unlikely(log_hook.IsEmpty())) {
85
+ stderr_debug_log_new(function_name, variable_name, length);
86
+ } else {
87
+ Napi::Env env = log_hook.Env();
88
+ Napi::HandleScope scope(env);
89
+ Napi::Function log_hook_function = log_hook.Value();
90
+ log_hook_function.Call(
91
+ {Napi::Number::New(env, posix_log_level_debug),
92
+ Napi::String::New(env, asherah_node_prefix + function_name +
93
+ ": Calling new[" +
94
+ std::to_string(length) + "] (heap) for " +
95
+ variable_name)});
96
+ }
97
+ }
98
+ }
99
+
100
+ void Logger::debug_log_copy_buffer(const char *function_name,
101
+ const char *buffer, size_t length) {
102
+ if (unlikely(verbose_flag)) {
103
+ debug_log(__func__, "Copying " + std::to_string(length) + " bytes to " +
104
+ format_ptr(buffer) + " - " +
105
+ format_ptr(buffer + length));
106
+ }
107
+ }
108
+
109
+ void Logger::debug_log_configure_cbuffer(const char *function_name,
110
+ const char *variable_name,
111
+ size_t length) {
112
+ if (unlikely(verbose_flag)) {
113
+ debug_log(__func__, "configure_cbuffer(" + format_ptr(variable_name) +
114
+ ", " + std::to_string(length) + ")");
115
+ }
116
+ }
117
+
118
+ void Logger::error_log(const char *function_name, const char *message) {
119
+ if (unlikely(verbose_flag)) {
120
+ if (unlikely(log_hook.IsEmpty())) {
121
+ stderr_error_log(function_name, message);
122
+ } else {
123
+ Napi::Env env = log_hook.Env();
124
+ Napi::HandleScope scope(env);
125
+ Napi::Function log_hook_function = log_hook.Value();
126
+ log_hook_function.Call(
127
+ {Napi::Number::New(env, posix_log_level_error),
128
+ Napi::String::New(env, asherah_node_prefix + function_name + ": " +
129
+ message)});
130
+ }
131
+ }
132
+ }
133
+
134
+ void Logger::error_log(const char *function_name, std::string message) {
135
+ if (unlikely(verbose_flag)) {
136
+ if (unlikely(log_hook.IsEmpty())) {
137
+ stderr_error_log(function_name, message);
138
+ } else {
139
+ Napi::Env env = log_hook.Env();
140
+ Napi::HandleScope scope(env);
141
+ Napi::Function log_hook_function = log_hook.Value();
142
+ log_hook_function.Call(
143
+ {Napi::Number::New(env, posix_log_level_error),
144
+ Napi::String::New(env, asherah_node_prefix + function_name + ": " +
145
+ message)});
146
+ }
147
+ }
148
+ }
149
+
150
+ __attribute__((always_inline)) inline void
151
+ Logger::stderr_debug_log(const char *function_name, const char *message) {
152
+ if (unlikely(verbose_flag)) {
153
+ std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
154
+ << std::endl
155
+ << std::flush;
156
+ }
157
+ }
158
+
159
+ __attribute__((always_inline)) inline void
160
+ Logger::stderr_debug_log(const char *function_name, std::string message) {
161
+ if (unlikely(verbose_flag)) {
162
+ std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
163
+ << std::endl
164
+ << std::flush;
165
+ }
166
+ }
167
+
168
+ __attribute__((always_inline)) inline void
169
+ Logger::stderr_debug_log_alloca(const char *function_name,
170
+ const char *variable_name, size_t length) {
171
+ if (unlikely(verbose_flag)) {
172
+ std::cerr << "asherah-node: [DEBUG] " << function_name
173
+ << ": Calling alloca(" << length << ") (stack) for "
174
+ << variable_name << std::endl
175
+ << std::flush;
176
+ }
177
+ }
178
+
179
+ __attribute__((always_inline)) inline void
180
+ Logger::stderr_debug_log_new(const char *function_name,
181
+ const char *variable_name, size_t length) {
182
+ if (unlikely(verbose_flag)) {
183
+ std::cerr << "asherah-node: [DEBUG] " << function_name << ": Calling new["
184
+ << length << "] (heap) for " << variable_name << std::endl
185
+ << std::flush;
186
+ }
187
+ }
188
+
189
+ __attribute__((always_inline)) inline void
190
+ Logger::stderr_error_log(const char *function_name, const char *message) {
191
+ if (unlikely(verbose_flag)) {
192
+ std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
193
+ << std::endl
194
+ << std::flush;
195
+ }
196
+ }
197
+
198
+ __attribute__((always_inline)) inline void
199
+ Logger::stderr_error_log(const char *function_name, std::string message) {
200
+ if (unlikely(verbose_flag)) {
201
+ std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
202
+ << std::endl
203
+ << std::flush;
204
+ }
205
+ }
206
+
207
+ __attribute__((always_inline)) inline std::string
208
+ Logger::format_ptr(const char *ptr) {
209
+ std::ostringstream ss;
210
+ ss << "0x" << std::hex << (intptr_t)ptr;
211
+ return ss.str();
212
+ }
213
+
214
+ __attribute__((always_inline, noreturn)) inline void
215
+ Logger::log_error_and_throw(const char *function_name, std::string error_msg) {
216
+ error_log(function_name, error_msg);
217
+ throw new std::runtime_error(function_name + (": " + error_msg));
218
+ }