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/.asherah-version +1 -1
- package/package.json +2 -1
- package/scripts/download-libraries.sh +13 -10
- package/src/asherah.cc +144 -114
- package/src/asherah.d.ts +4 -0
- package/src/cobhan.h +23 -25
- package/src/cobhan_napi_interop.h +54 -59
- package/src/logging.cc +218 -2
- package/src/logging.h +43 -70
- package/SHA256SUMS +0 -4
- package/SHA256SUMS-darwin +0 -4
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
|
-
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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,
|
|
106
|
-
max_stack_alloc_size,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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__,
|
|
19
|
-
|
|
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
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
134
|
-
|
|
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,
|
|
149
|
-
max_stack_alloc_size,
|
|
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
|
-
|
|
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(
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
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,
|
|
177
|
-
max_stack_alloc_size,
|
|
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(
|
|
187
|
-
|
|
188
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
2
|
-
|
|
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
|
+
}
|