clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name xray_basic_logging.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D XRAY_HAS_EXCEPTIONS=1 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/projects/compiler-rt/lib/xray -I /build/llvm-toolchain-snapshot-7~svn338205/projects/compiler-rt/lib/xray -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -I /build/llvm-toolchain-snapshot-7~svn338205/projects/compiler-rt/lib/xray/.. -I /build/llvm-toolchain-snapshot-7~svn338205/projects/compiler-rt/lib/xray/../../include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -Wno-unused-parameter -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -Wno-unused-parameter -Wno-variadic-macros -Wno-non-virtual-dtor -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/projects/compiler-rt/lib/xray -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fvisibility-inlines-hidden -fno-builtin -fno-rtti -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/projects/compiler-rt/lib/xray/xray_basic_logging.cc -faddrsig
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | #include <errno(*__errno_location ()).h> |
19 | #include <fcntl.h> |
20 | #include <pthread.h> |
21 | #include <sys/stat.h> |
22 | #include <sys/syscall.h> |
23 | #include <sys/types.h> |
24 | #include <time.h> |
25 | #include <unistd.h> |
26 | |
27 | #include "sanitizer_common/sanitizer_allocator_internal.h" |
28 | #include "sanitizer_common/sanitizer_libc.h" |
29 | #include "xray/xray_records.h" |
30 | #include "xray_recursion_guard.h" |
31 | #include "xray_basic_flags.h" |
32 | #include "xray_basic_logging.h" |
33 | #include "xray_defs.h" |
34 | #include "xray_flags.h" |
35 | #include "xray_interface_internal.h" |
36 | #include "xray_tsc.h" |
37 | #include "xray_utils.h" |
38 | |
39 | namespace __xray { |
40 | |
41 | SpinMutex LogMutex; |
42 | |
43 | |
44 | |
45 | struct alignas(16) StackEntry { |
46 | int32_t FuncId; |
47 | uint16_t Type; |
48 | uint8_t CPU; |
49 | uint8_t Padding; |
50 | uint64_t TSC; |
51 | }; |
52 | |
53 | static_assert(sizeof(StackEntry) == 16, "Wrong size for StackEntry"); |
54 | |
55 | struct alignas(64) ThreadLocalData { |
56 | void *InMemoryBuffer = nullptr; |
57 | size_t BufferSize = 0; |
58 | size_t BufferOffset = 0; |
59 | void *ShadowStack = nullptr; |
60 | size_t StackSize = 0; |
61 | size_t StackEntries = 0; |
62 | int Fd = -1; |
63 | }; |
64 | |
65 | static pthread_key_t PThreadKey; |
66 | |
67 | static atomic_uint8_t BasicInitialized{0}; |
68 | |
69 | BasicLoggingOptions GlobalOptions; |
70 | |
71 | thread_local atomic_uint8_t Guard{0}; |
72 | |
73 | static atomic_uint8_t UseRealTSC{0}; |
74 | static atomic_uint64_t ThresholdTicks{0}; |
75 | static atomic_uint64_t TicksPerSec{0}; |
76 | static atomic_uint64_t CycleFrequency{NanosecondsPerSecond}; |
77 | |
78 | static int openLogFile() XRAY_NEVER_INSTRUMENT { |
79 | int F = getLogFD(); |
80 | if (F == -1) |
81 | return -1; |
82 | |
83 | static pthread_once_t DetectOnce = PTHREAD_ONCE_INIT0; |
84 | pthread_once(&DetectOnce, +[] { |
85 | if (atomic_load(&UseRealTSC, memory_order_acquire)) |
86 | atomic_store(&CycleFrequency, getTSCFrequency(), memory_order_release); |
87 | }); |
88 | |
89 | |
90 | |
91 | |
92 | XRayFileHeader Header; |
93 | |
94 | |
95 | Header.Version = 3; |
96 | Header.Type = FileTypes::NAIVE_LOG; |
97 | Header.CycleFrequency = atomic_load(&CycleFrequency, memory_order_acquire); |
98 | |
99 | |
100 | |
101 | Header.ConstantTSC = 1; |
102 | Header.NonstopTSC = 1; |
103 | retryingWriteAll(F, reinterpret_cast<char *>(&Header), |
104 | reinterpret_cast<char *>(&Header) + sizeof(Header)); |
105 | return F; |
106 | } |
107 | |
108 | static int getGlobalFd() XRAY_NEVER_INSTRUMENT { |
109 | static pthread_once_t OnceInit = PTHREAD_ONCE_INIT0; |
110 | static int Fd = 0; |
111 | pthread_once(&OnceInit, +[] { Fd = openLogFile(); }); |
112 | return Fd; |
113 | } |
114 | |
115 | static ThreadLocalData &getThreadLocalData() XRAY_NEVER_INSTRUMENT { |
116 | thread_local ThreadLocalData TLD; |
117 | thread_local bool UNUSED__attribute__((unused)) TOnce = [] { |
118 | if (GlobalOptions.ThreadBufferSize == 0) { |
119 | if (Verbosity()) |
120 | Report("Not initializing TLD since ThreadBufferSize == 0.\n"); |
121 | return false; |
122 | } |
123 | pthread_setspecific(PThreadKey, &TLD); |
124 | TLD.Fd = getGlobalFd(); |
125 | TLD.InMemoryBuffer = reinterpret_cast<XRayRecord *>( |
126 | InternalAlloc(sizeof(XRayRecord) * GlobalOptions.ThreadBufferSize, |
127 | nullptr, alignof(XRayRecord))); |
128 | TLD.BufferSize = GlobalOptions.ThreadBufferSize; |
129 | TLD.BufferOffset = 0; |
130 | if (GlobalOptions.MaxStackDepth == 0) { |
131 | if (Verbosity()) |
132 | Report("Not initializing the ShadowStack since MaxStackDepth == 0.\n"); |
133 | TLD.StackSize = 0; |
134 | TLD.StackEntries = 0; |
135 | TLD.ShadowStack = nullptr; |
136 | return false; |
137 | } |
138 | TLD.ShadowStack = reinterpret_cast<StackEntry *>( |
139 | InternalAlloc(sizeof(StackEntry) * GlobalOptions.MaxStackDepth, nullptr, |
140 | alignof(StackEntry))); |
141 | TLD.StackSize = GlobalOptions.MaxStackDepth; |
142 | TLD.StackEntries = 0; |
143 | return false; |
144 | }(); |
145 | return TLD; |
146 | } |
147 | |
148 | template <class RDTSC> |
149 | void InMemoryRawLog(int32_t FuncId, XRayEntryType Type, |
150 | RDTSC ReadTSC) XRAY_NEVER_INSTRUMENT { |
151 | auto &TLD = getThreadLocalData(); |
152 | int Fd = getGlobalFd(); |
153 | if (Fd == -1) |
154 | return; |
155 | |
156 | |
157 | |
158 | |
159 | RecursionGuard G(Guard); |
160 | if (!G) |
161 | return; |
162 | |
163 | uint8_t CPU = 0; |
164 | uint64_t TSC = ReadTSC(CPU); |
165 | |
166 | switch (Type) { |
167 | case XRayEntryType::ENTRY: |
168 | case XRayEntryType::LOG_ARGS_ENTRY: { |
169 | |
170 | if (TLD.StackEntries++ >= TLD.StackSize) |
171 | return; |
172 | |
173 | |
174 | |
175 | StackEntry E; |
176 | E.FuncId = FuncId; |
177 | E.CPU = CPU; |
178 | E.Type = Type; |
179 | E.TSC = TSC; |
180 | auto StackEntryPtr = static_cast<char *>(TLD.ShadowStack) + |
181 | (sizeof(StackEntry) * (TLD.StackEntries - 1)); |
182 | internal_memcpy(StackEntryPtr, &E, sizeof(StackEntry)); |
183 | break; |
184 | } |
185 | case XRayEntryType::EXIT: |
186 | case XRayEntryType::TAIL: { |
187 | if (TLD.StackEntries == 0) |
188 | break; |
189 | |
190 | if (--TLD.StackEntries >= TLD.StackSize) |
191 | return; |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | StackEntry StackTop; |
204 | auto StackEntryPtr = static_cast<char *>(TLD.ShadowStack) + |
205 | (sizeof(StackEntry) * TLD.StackEntries); |
206 | internal_memcpy(&StackTop, StackEntryPtr, sizeof(StackEntry)); |
207 | if (StackTop.FuncId == FuncId && StackTop.CPU == CPU && |
208 | StackTop.TSC < TSC) { |
209 | auto Delta = TSC - StackTop.TSC; |
210 | if (Delta < atomic_load(&ThresholdTicks, memory_order_relaxed)) { |
211 | DCHECK(TLD.BufferOffset > 0); |
212 | TLD.BufferOffset -= StackTop.Type == XRayEntryType::ENTRY ? 1 : 2; |
213 | return; |
214 | } |
215 | } |
216 | break; |
217 | } |
218 | default: |
219 | |
220 | DCHECK(false && "Unsupported XRayEntryType encountered."); |
221 | break; |
222 | } |
223 | |
224 | |
225 | |
226 | XRayRecord R; |
227 | R.RecordType = RecordTypes::NORMAL; |
228 | R.CPU = CPU; |
229 | R.TSC = TSC; |
230 | R.TId = GetTid(); |
231 | R.PId = internal_getpid(); |
232 | R.Type = Type; |
233 | R.FuncId = FuncId; |
234 | auto FirstEntry = reinterpret_cast<XRayRecord *>(TLD.InMemoryBuffer); |
235 | internal_memcpy(FirstEntry + TLD.BufferOffset, &R, sizeof(R)); |
236 | if (++TLD.BufferOffset == TLD.BufferSize) { |
237 | SpinMutexLock L(&LogMutex); |
238 | retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry), |
239 | reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset)); |
240 | TLD.BufferOffset = 0; |
241 | TLD.StackEntries = 0; |
242 | } |
243 | } |
244 | |
245 | template <class RDTSC> |
246 | void InMemoryRawLogWithArg(int32_t FuncId, XRayEntryType Type, uint64_t Arg1, |
247 | RDTSC ReadTSC) XRAY_NEVER_INSTRUMENT { |
248 | auto &TLD = getThreadLocalData(); |
249 | auto FirstEntry = |
250 | reinterpret_cast<XRayArgPayload *>(TLD.InMemoryBuffer); |
251 | const auto &BuffLen = TLD.BufferSize; |
252 | int Fd = getGlobalFd(); |
253 | if (Fd == -1) |
254 | return; |
255 | |
256 | |
257 | |
258 | |
259 | if (TLD.BufferOffset + 2 > BuffLen) { |
260 | SpinMutexLock L(&LogMutex); |
261 | retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry), |
262 | reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset)); |
263 | TLD.BufferOffset = 0; |
264 | TLD.StackEntries = 0; |
265 | } |
266 | |
267 | |
268 | InMemoryRawLog(FuncId, Type, ReadTSC); |
269 | |
270 | RecursionGuard G(Guard); |
271 | if (!G) |
272 | return; |
273 | |
274 | |
275 | XRayArgPayload R; |
276 | R.RecordType = RecordTypes::ARG_PAYLOAD; |
277 | R.FuncId = FuncId; |
278 | R.TId = GetTid(); |
279 | R.PId = internal_getpid(); |
280 | R.Arg = Arg1; |
281 | internal_memcpy(FirstEntry + TLD.BufferOffset, &R, sizeof(R)); |
282 | if (++TLD.BufferOffset == BuffLen) { |
283 | SpinMutexLock L(&LogMutex); |
284 | retryingWriteAll(Fd, reinterpret_cast<char *>(FirstEntry), |
285 | reinterpret_cast<char *>(FirstEntry + TLD.BufferOffset)); |
286 | TLD.BufferOffset = 0; |
287 | TLD.StackEntries = 0; |
288 | } |
289 | } |
290 | |
291 | void basicLoggingHandleArg0RealTSC(int32_t FuncId, |
292 | XRayEntryType Type) XRAY_NEVER_INSTRUMENT { |
293 | InMemoryRawLog(FuncId, Type, readTSC); |
294 | } |
295 | |
296 | void basicLoggingHandleArg0EmulateTSC(int32_t FuncId, XRayEntryType Type) |
297 | XRAY_NEVER_INSTRUMENT { |
298 | InMemoryRawLog(FuncId, Type, [](uint8_t &CPU) XRAY_NEVER_INSTRUMENT { |
299 | timespec TS; |
300 | int result = clock_gettime(CLOCK_REALTIME0, &TS); |
301 | if (result != 0) { |
302 | Report("clock_gettimg(2) return %d, errno=%d.", result, int(errno(*__errno_location ()))); |
303 | TS = {0, 0}; |
304 | } |
305 | CPU = 0; |
306 | return TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec; |
307 | }); |
308 | } |
309 | |
310 | void basicLoggingHandleArg1RealTSC(int32_t FuncId, XRayEntryType Type, |
311 | uint64_t Arg1) XRAY_NEVER_INSTRUMENT { |
312 | InMemoryRawLogWithArg(FuncId, Type, Arg1, readTSC); |
313 | } |
314 | |
315 | void basicLoggingHandleArg1EmulateTSC(int32_t FuncId, XRayEntryType Type, |
316 | uint64_t Arg1) XRAY_NEVER_INSTRUMENT { |
317 | InMemoryRawLogWithArg( |
318 | FuncId, Type, Arg1, [](uint8_t &CPU) XRAY_NEVER_INSTRUMENT { |
319 | timespec TS; |
320 | int result = clock_gettime(CLOCK_REALTIME0, &TS); |
321 | if (result != 0) { |
322 | Report("clock_gettimg(2) return %d, errno=%d.", result, int(errno(*__errno_location ()))); |
323 | TS = {0, 0}; |
324 | } |
325 | CPU = 0; |
326 | return TS.tv_sec * NanosecondsPerSecond + TS.tv_nsec; |
327 | }); |
328 | } |
329 | |
330 | static void TLDDestructor(void *P) XRAY_NEVER_INSTRUMENT { |
331 | ThreadLocalData &TLD = *reinterpret_cast<ThreadLocalData *>(P); |
332 | auto ExitGuard = at_scope_exit([&TLD] { |
333 | |
334 | if (TLD.InMemoryBuffer) |
335 | InternalFree(TLD.InMemoryBuffer); |
336 | if (TLD.ShadowStack) |
337 | InternalFree(TLD.ShadowStack); |
338 | if (Verbosity()) |
339 | Report("Cleaned up log for TID: %d\n", GetTid()); |
340 | }); |
341 | |
342 | if (TLD.Fd == -1 || TLD.BufferOffset == 0) { |
343 | if (Verbosity()) |
344 | Report("Skipping buffer for TID: %d; Fd = %d; Offset = %llu\n", GetTid(), |
345 | TLD.Fd, TLD.BufferOffset); |
346 | return; |
347 | } |
348 | |
349 | { |
350 | SpinMutexLock L(&LogMutex); |
351 | retryingWriteAll(TLD.Fd, reinterpret_cast<char *>(TLD.InMemoryBuffer), |
352 | reinterpret_cast<char *>(TLD.InMemoryBuffer) + |
353 | (sizeof(XRayRecord) * TLD.BufferOffset)); |
354 | } |
355 | |
356 | |
357 | |
358 | |
359 | |
360 | fsync(TLD.Fd); |
361 | } |
362 | |
363 | XRayLogInitStatus basicLoggingInit(size_t BufferSize, size_t BufferMax, |
364 | void *Options, |
365 | size_t OptionsSize) XRAY_NEVER_INSTRUMENT { |
366 | uint8_t Expected = 0; |
367 | if (!atomic_compare_exchange_strong(&BasicInitialized, &Expected, 1, |
| |
368 | memory_order_acq_rel)) { |
369 | if (Verbosity()) |
370 | Report("Basic logging already initialized.\n"); |
371 | return XRayLogInitStatus::XRAY_LOG_INITIALIZED; |
372 | } |
373 | |
374 | static pthread_once_t OnceInit = PTHREAD_ONCE_INIT0; |
375 | pthread_once(&OnceInit, +[] { |
376 | pthread_key_create(&PThreadKey, TLDDestructor); |
377 | atomic_store(&UseRealTSC, probeRequiredCPUFeatures(), memory_order_release); |
378 | |
379 | atomic_store(&TicksPerSec, |
380 | probeRequiredCPUFeatures() ? getTSCFrequency() |
381 | : NanosecondsPerSecond, |
382 | memory_order_release); |
383 | if (!atomic_load(&UseRealTSC, memory_order_relaxed) && Verbosity()) |
384 | Report("WARNING: Required CPU features missing for XRay instrumentation, " |
385 | "using emulation instead.\n"); |
386 | }); |
387 | |
388 | if (BufferSize == 0 && BufferMax == 0 && Options != nullptr) { |
| 2 | | Assuming 'BufferSize' is equal to 0 | |
|
| 3 | | Assuming 'BufferMax' is equal to 0 | |
|
| 4 | | Assuming pointer value is null | |
|
| |
389 | FlagParser P; |
390 | BasicFlags F; |
391 | F.setDefaults(); |
392 | registerXRayBasicFlags(&P, &F); |
393 | P.ParseString(useCompilerDefinedBasicFlags()); |
394 | auto *EnvOpts = GetEnv("XRAY_BASIC_OPTIONS"); |
395 | if (EnvOpts == nullptr) |
396 | EnvOpts = ""; |
397 | |
398 | P.ParseString(EnvOpts); |
399 | |
400 | |
401 | |
402 | if (internal_strlen(EnvOpts) == 0) { |
403 | F.func_duration_threshold_us = |
404 | flags()->xray_naive_log_func_duration_threshold_us; |
405 | F.max_stack_depth = flags()->xray_naive_log_max_stack_depth; |
406 | F.thread_buffer_size = flags()->xray_naive_log_thread_buffer_size; |
407 | } |
408 | |
409 | P.ParseString(static_cast<const char *>(Options)); |
410 | GlobalOptions.ThreadBufferSize = F.thread_buffer_size; |
411 | GlobalOptions.DurationFilterMicros = F.func_duration_threshold_us; |
412 | GlobalOptions.MaxStackDepth = F.max_stack_depth; |
413 | *basicFlags() = F; |
414 | } else if (OptionsSize != sizeof(BasicLoggingOptions)) { |
| 6 | | Assuming the condition is false | |
|
| |
415 | Report("Invalid options size, potential ABI mismatch; expected %d got %d", |
416 | sizeof(BasicLoggingOptions), OptionsSize); |
417 | return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED; |
418 | } else { |
419 | if (Verbosity()) |
| 8 | | Assuming the condition is false | |
|
| |
420 | Report("XRay Basic: struct-based init is deprecated, please use " |
421 | "string-based configuration instead.\n"); |
422 | GlobalOptions = *reinterpret_cast<BasicLoggingOptions *>(Options); |
| 10 | | Forming reference to null pointer |
|
423 | } |
424 | |
425 | atomic_store(&ThresholdTicks, |
426 | atomic_load(&TicksPerSec, memory_order_acquire) * |
427 | GlobalOptions.DurationFilterMicros / 1000000, |
428 | memory_order_release); |
429 | __xray_set_handler_arg1(atomic_load(&UseRealTSC, memory_order_acquire) |
430 | ? basicLoggingHandleArg1RealTSC |
431 | : basicLoggingHandleArg1EmulateTSC); |
432 | __xray_set_handler(atomic_load(&UseRealTSC, memory_order_acquire) |
433 | ? basicLoggingHandleArg0RealTSC |
434 | : basicLoggingHandleArg0EmulateTSC); |
435 | |
436 | |
437 | |
438 | __xray_remove_customevent_handler(); |
439 | __xray_remove_typedevent_handler(); |
440 | |
441 | return XRayLogInitStatus::XRAY_LOG_INITIALIZED; |
442 | } |
443 | |
444 | XRayLogInitStatus basicLoggingFinalize() XRAY_NEVER_INSTRUMENT { |
445 | uint8_t Expected = 0; |
446 | if (!atomic_compare_exchange_strong(&BasicInitialized, &Expected, 0, |
447 | memory_order_acq_rel) && |
448 | Verbosity()) |
449 | Report("Basic logging already finalized.\n"); |
450 | |
451 | |
452 | |
453 | |
454 | return XRayLogInitStatus::XRAY_LOG_FINALIZED; |
455 | } |
456 | |
457 | XRayLogFlushStatus basicLoggingFlush() XRAY_NEVER_INSTRUMENT { |
458 | |
459 | |
460 | return XRayLogFlushStatus::XRAY_LOG_FLUSHED; |
461 | } |
462 | |
463 | |
464 | void basicLoggingHandleArg0Empty(int32_t, XRayEntryType) XRAY_NEVER_INSTRUMENT { |
465 | } |
466 | |
467 | bool basicLogDynamicInitializer() XRAY_NEVER_INSTRUMENT { |
468 | XRayLogImpl Impl{ |
469 | basicLoggingInit, |
470 | basicLoggingFinalize, |
471 | basicLoggingHandleArg0Empty, |
472 | basicLoggingFlush, |
473 | }; |
474 | auto RegistrationResult = __xray_log_register_mode("xray-basic", Impl); |
475 | if (RegistrationResult != XRayLogRegisterStatus::XRAY_REGISTRATION_OK && |
476 | Verbosity()) |
477 | Report("Cannot register XRay Basic Mode to 'xray-basic'; error = %d\n", |
478 | RegistrationResult); |
479 | if (flags()->xray_naive_log || |
480 | !internal_strcmp(flags()->xray_mode, "xray-basic")) { |
481 | auto SelectResult = __xray_log_select_mode("xray-basic"); |
482 | if (SelectResult != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) { |
483 | if (Verbosity()) |
484 | Report("Failed selecting XRay Basic Mode; error = %d\n", SelectResult); |
485 | return false; |
486 | } |
487 | |
488 | |
489 | |
490 | |
491 | auto *Env = GetEnv("XRAY_BASIC_OPTIONS"); |
492 | auto InitResult = |
493 | __xray_log_init_mode("xray-basic", Env == nullptr ? "" : Env); |
494 | if (InitResult != XRayLogInitStatus::XRAY_LOG_INITIALIZED) { |
495 | if (Verbosity()) |
496 | Report("Failed initializing XRay Basic Mode; error = %d\n", InitResult); |
497 | return false; |
498 | } |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | static pthread_once_t DynamicOnce = PTHREAD_ONCE_INIT0; |
506 | pthread_once(&DynamicOnce, +[] { |
507 | static void *FakeTLD = nullptr; |
508 | FakeTLD = &getThreadLocalData(); |
509 | Atexit(+[] { TLDDestructor(FakeTLD); }); |
510 | }); |
511 | } |
512 | return true; |
513 | } |
514 | |
515 | } |
516 | |
517 | static auto UNUSED__attribute__((unused)) Unused = __xray::basicLogDynamicInitializer(); |