Bug Summary

File:projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc
Warning:line 343, column 3
Value stored to 'str' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sanitizer_symbolizer_libcdep.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -analyzer-config-compatibility-mode=true -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-9/lib/clang/9.0.0 -D HAVE_RPC_XDR_H=1 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/projects/compiler-rt/lib/sanitizer_common -I /build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn362543/include -I /build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/.. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.0.0/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-comment -Wno-unused-parameter -Wno-variadic-macros -Wno-non-virtual-dtor -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/projects/compiler-rt/lib/sanitizer_common -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn362543=. -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-2019-06-05-060531-1271-1 -x c++ /build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc -faddrsig
1//===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_allocator_internal.h"
14#include "sanitizer_internal_defs.h"
15#include "sanitizer_symbolizer_internal.h"
16
17namespace __sanitizer {
18
19Symbolizer *Symbolizer::GetOrInit() {
20 SpinMutexLock l(&init_mu_);
21 if (symbolizer_)
22 return symbolizer_;
23 symbolizer_ = PlatformInit();
24 CHECK(symbolizer_)do { __sanitizer::u64 v1 = (__sanitizer::u64)((symbolizer_));
__sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect
(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 24, "(" "(symbolizer_)" ") " "!=" " (" "0" ")", v1, v2); } while
(false)
;
25 return symbolizer_;
26}
27
28// See sanitizer_symbolizer_markup.cc.
29#if !SANITIZER_SYMBOLIZER_MARKUP0
30
31const char *ExtractToken(const char *str, const char *delims, char **result) {
32 uptr prefix_len = internal_strcspn(str, delims);
33 *result = (char*)InternalAlloc(prefix_len + 1);
34 internal_memcpy(*result, str, prefix_len);
35 (*result)[prefix_len] = '\0';
36 const char *prefix_end = str + prefix_len;
37 if (*prefix_end != '\0') prefix_end++;
38 return prefix_end;
39}
40
41const char *ExtractInt(const char *str, const char *delims, int *result) {
42 char *buff;
43 const char *ret = ExtractToken(str, delims, &buff);
44 if (buff != 0) {
45 *result = (int)internal_atoll(buff);
46 }
47 InternalFree(buff);
48 return ret;
49}
50
51const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
52 char *buff;
53 const char *ret = ExtractToken(str, delims, &buff);
54 if (buff != 0) {
55 *result = (uptr)internal_atoll(buff);
56 }
57 InternalFree(buff);
58 return ret;
59}
60
61const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
62 char **result) {
63 const char *found_delimiter = internal_strstr(str, delimiter);
64 uptr prefix_len =
65 found_delimiter ? found_delimiter - str : internal_strlen(str);
66 *result = (char *)InternalAlloc(prefix_len + 1);
67 internal_memcpy(*result, str, prefix_len);
68 (*result)[prefix_len] = '\0';
69 const char *prefix_end = str + prefix_len;
70 if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
71 return prefix_end;
72}
73
74SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
75 BlockingMutexLock l(&mu_);
76 const char *module_name;
77 uptr module_offset;
78 ModuleArch arch;
79 SymbolizedStack *res = SymbolizedStack::New(addr);
80 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
81 &arch))
82 return res;
83 // Always fill data about module name and offset.
84 res->info.FillModuleInfo(module_name, module_offset, arch);
85 for (auto &tool : tools_) {
86 SymbolizerScope sym_scope(this);
87 if (tool.SymbolizePC(addr, res)) {
88 return res;
89 }
90 }
91 return res;
92}
93
94bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
95 BlockingMutexLock l(&mu_);
96 const char *module_name;
97 uptr module_offset;
98 ModuleArch arch;
99 if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
100 &arch))
101 return false;
102 info->Clear();
103 info->module = internal_strdup(module_name);
104 info->module_offset = module_offset;
105 info->module_arch = arch;
106 for (auto &tool : tools_) {
107 SymbolizerScope sym_scope(this);
108 if (tool.SymbolizeData(addr, info)) {
109 return true;
110 }
111 }
112 return true;
113}
114
115bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
116 uptr *module_address) {
117 BlockingMutexLock l(&mu_);
118 const char *internal_module_name = nullptr;
119 ModuleArch arch;
120 if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
121 module_address, &arch))
122 return false;
123
124 if (module_name)
125 *module_name = module_names_.GetOwnedCopy(internal_module_name);
126 return true;
127}
128
129void Symbolizer::Flush() {
130 BlockingMutexLock l(&mu_);
131 for (auto &tool : tools_) {
132 SymbolizerScope sym_scope(this);
133 tool.Flush();
134 }
135}
136
137const char *Symbolizer::Demangle(const char *name) {
138 BlockingMutexLock l(&mu_);
139 for (auto &tool : tools_) {
140 SymbolizerScope sym_scope(this);
141 if (const char *demangled = tool.Demangle(name))
142 return demangled;
143 }
144 return PlatformDemangle(name);
145}
146
147bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
148 const char **module_name,
149 uptr *module_offset,
150 ModuleArch *module_arch) {
151 const LoadedModule *module = FindModuleForAddress(address);
152 if (module == nullptr)
153 return false;
154 *module_name = module->full_name();
155 *module_offset = address - module->base_address();
156 *module_arch = module->arch();
157 return true;
158}
159
160void Symbolizer::RefreshModules() {
161 modules_.init();
162 fallback_modules_.fallbackInit();
163 RAW_CHECK(modules_.size() > 0)do { if (__builtin_expect(!!(!(modules_.size() > 0)), 0)) {
RawWrite("modules_.size() > 0"); Die(); } } while (0)
;
164 modules_fresh_ = true;
165}
166
167static const LoadedModule *SearchForModule(const ListOfModules &modules,
168 uptr address) {
169 for (uptr i = 0; i < modules.size(); i++) {
170 if (modules[i].containsAddress(address)) {
171 return &modules[i];
172 }
173 }
174 return nullptr;
175}
176
177const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
178 bool modules_were_reloaded = false;
179 if (!modules_fresh_) {
180 RefreshModules();
181 modules_were_reloaded = true;
182 }
183 const LoadedModule *module = SearchForModule(modules_, address);
184 if (module) return module;
185
186 // dlopen/dlclose interceptors invalidate the module list, but when
187 // interception is disabled, we need to retry if the lookup fails in
188 // case the module list changed.
189#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
190 if (!modules_were_reloaded) {
191 RefreshModules();
192 module = SearchForModule(modules_, address);
193 if (module) return module;
194 }
195#endif
196
197 if (fallback_modules_.size()) {
198 module = SearchForModule(fallback_modules_, address);
199 }
200 return module;
201}
202
203// For now we assume the following protocol:
204// For each request of the form
205// <module_name> <module_offset>
206// passed to STDIN, external symbolizer prints to STDOUT response:
207// <function_name>
208// <file_name>:<line_number>:<column_number>
209// <function_name>
210// <file_name>:<line_number>:<column_number>
211// ...
212// <empty line>
213class LLVMSymbolizerProcess : public SymbolizerProcess {
214 public:
215 explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
216
217 private:
218 bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
219 // Empty line marks the end of llvm-symbolizer output.
220 return length >= 2 && buffer[length - 1] == '\n' &&
221 buffer[length - 2] == '\n';
222 }
223
224 // When adding a new architecture, don't forget to also update
225 // script/asan_symbolize.py and sanitizer_common.h.
226 void GetArgV(const char *path_to_binary,
227 const char *(&argv)[kArgVMax]) const override {
228#if defined(__x86_64h__)
229 const char* const kSymbolizerArch = "--default-arch=x86_64h";
230#elif defined(__x86_64__1)
231 const char* const kSymbolizerArch = "--default-arch=x86_64";
232#elif defined(__i386__)
233 const char* const kSymbolizerArch = "--default-arch=i386";
234#elif defined(__aarch64__)
235 const char* const kSymbolizerArch = "--default-arch=arm64";
236#elif defined(__arm__)
237 const char* const kSymbolizerArch = "--default-arch=arm";
238#elif defined(__powerpc64__) && __BYTE_ORDER__1234 == __ORDER_BIG_ENDIAN__4321
239 const char* const kSymbolizerArch = "--default-arch=powerpc64";
240#elif defined(__powerpc64__) && __BYTE_ORDER__1234 == __ORDER_LITTLE_ENDIAN__1234
241 const char* const kSymbolizerArch = "--default-arch=powerpc64le";
242#elif defined(__s390x__)
243 const char* const kSymbolizerArch = "--default-arch=s390x";
244#elif defined(__s390__)
245 const char* const kSymbolizerArch = "--default-arch=s390";
246#else
247 const char* const kSymbolizerArch = "--default-arch=unknown";
248#endif
249
250 const char *const inline_flag = common_flags()->symbolize_inline_frames
251 ? "--inlining=true"
252 : "--inlining=false";
253 int i = 0;
254 argv[i++] = path_to_binary;
255 argv[i++] = inline_flag;
256 argv[i++] = kSymbolizerArch;
257 argv[i++] = nullptr;
258 }
259};
260
261LLVMSymbolizer::LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
262 : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
263
264// Parse a <file>:<line>[:<column>] buffer. The file path may contain colons on
265// Windows, so extract tokens from the right hand side first. The column info is
266// also optional.
267static const char *ParseFileLineInfo(AddressInfo *info, const char *str) {
268 char *file_line_info = 0;
269 str = ExtractToken(str, "\n", &file_line_info);
270 CHECK(file_line_info)do { __sanitizer::u64 v1 = (__sanitizer::u64)((file_line_info
)); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect
(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 270, "(" "(file_line_info)" ") " "!=" " (" "0" ")", v1, v2)
; } while (false)
;
271
272 if (uptr size = internal_strlen(file_line_info)) {
273 char *back = file_line_info + size - 1;
274 for (int i = 0; i < 2; ++i) {
275 while (back > file_line_info && IsDigit(*back)) --back;
276 if (*back != ':' || !IsDigit(back[1])) break;
277 info->column = info->line;
278 info->line = internal_atoll(back + 1);
279 // Truncate the string at the colon to keep only filename.
280 *back = '\0';
281 --back;
282 }
283 ExtractToken(file_line_info, "", &info->file);
284 }
285
286 InternalFree(file_line_info);
287 return str;
288}
289
290// Parses one or more two-line strings in the following format:
291// <function_name>
292// <file_name>:<line_number>[:<column_number>]
293// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
294// them use the same output format.
295void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
296 bool top_frame = true;
297 SymbolizedStack *last = res;
298 while (true) {
299 char *function_name = 0;
300 str = ExtractToken(str, "\n", &function_name);
301 CHECK(function_name)do { __sanitizer::u64 v1 = (__sanitizer::u64)((function_name)
); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect
(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 301, "(" "(function_name)" ") " "!=" " (" "0" ")", v1, v2);
} while (false)
;
302 if (function_name[0] == '\0') {
303 // There are no more frames.
304 InternalFree(function_name);
305 break;
306 }
307 SymbolizedStack *cur;
308 if (top_frame) {
309 cur = res;
310 top_frame = false;
311 } else {
312 cur = SymbolizedStack::New(res->info.address);
313 cur->info.FillModuleInfo(res->info.module, res->info.module_offset,
314 res->info.module_arch);
315 last->next = cur;
316 last = cur;
317 }
318
319 AddressInfo *info = &cur->info;
320 info->function = function_name;
321 str = ParseFileLineInfo(info, str);
322
323 // Functions and filenames can be "??", in which case we write 0
324 // to address info to mark that names are unknown.
325 if (0 == internal_strcmp(info->function, "??")) {
326 InternalFree(info->function);
327 info->function = 0;
328 }
329 if (0 == internal_strcmp(info->file, "??")) {
330 InternalFree(info->file);
331 info->file = 0;
332 }
333 }
334}
335
336// Parses a two-line string in the following format:
337// <symbol_name>
338// <start_address> <size>
339// Used by LLVMSymbolizer and InternalSymbolizer.
340void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
341 str = ExtractToken(str, "\n", &info->name);
342 str = ExtractUptr(str, " ", &info->start);
343 str = ExtractUptr(str, "\n", &info->size);
Value stored to 'str' is never read
344}
345
346bool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
347 AddressInfo *info = &stack->info;
348 const char *buf = FormatAndSendCommand(
349 /*is_data*/ false, info->module, info->module_offset, info->module_arch);
350 if (buf) {
351 ParseSymbolizePCOutput(buf, stack);
352 return true;
353 }
354 return false;
355}
356
357bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
358 const char *buf = FormatAndSendCommand(
359 /*is_data*/ true, info->module, info->module_offset, info->module_arch);
360 if (buf) {
361 ParseSymbolizeDataOutput(buf, info);
362 info->start += (addr - info->module_offset); // Add the base address.
363 return true;
364 }
365 return false;
366}
367
368const char *LLVMSymbolizer::FormatAndSendCommand(bool is_data,
369 const char *module_name,
370 uptr module_offset,
371 ModuleArch arch) {
372 CHECK(module_name)do { __sanitizer::u64 v1 = (__sanitizer::u64)((module_name));
__sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect
(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 372, "(" "(module_name)" ") " "!=" " (" "0" ")", v1, v2); }
while (false)
;
373 const char *is_data_str = is_data ? "DATA " : "";
374 if (arch == kModuleArchUnknown) {
375 if (internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n", is_data_str,
376 module_name,
377 module_offset) >= static_cast<int>(kBufferSize)) {
378 Report("WARNING: Command buffer too small");
379 return nullptr;
380 }
381 } else {
382 if (internal_snprintf(buffer_, kBufferSize, "%s\"%s:%s\" 0x%zx\n",
383 is_data_str, module_name, ModuleArchToString(arch),
384 module_offset) >= static_cast<int>(kBufferSize)) {
385 Report("WARNING: Command buffer too small");
386 return nullptr;
387 }
388 }
389 return symbolizer_process_->SendCommand(buffer_);
390}
391
392SymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty)
393 : path_(path),
394 input_fd_(kInvalidFd((fd_t)-1)),
395 output_fd_(kInvalidFd((fd_t)-1)),
396 times_restarted_(0),
397 failed_to_start_(false),
398 reported_invalid_path_(false),
399 use_forkpty_(use_forkpty) {
400 CHECK(path_)do { __sanitizer::u64 v1 = (__sanitizer::u64)((path_)); __sanitizer
::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1
!= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 400, "(" "(path_)" ") " "!=" " (" "0" ")", v1, v2); } while
(false)
;
401 CHECK_NE(path_[0], '\0')do { __sanitizer::u64 v1 = (__sanitizer::u64)((path_[0])); __sanitizer
::u64 v2 = (__sanitizer::u64)(('\0')); if (__builtin_expect(!
!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-9~svn362543/projects/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc"
, 401, "(" "(path_[0])" ") " "!=" " (" "('\\0')" ")", v1, v2)
; } while (false)
;
402}
403
404static bool IsSameModule(const char* path) {
405 if (const char* ProcessName = GetProcessName()) {
406 if (const char* SymbolizerName = StripModuleName(path)) {
407 return !internal_strcmp(ProcessName, SymbolizerName);
408 }
409 }
410 return false;
411}
412
413const char *SymbolizerProcess::SendCommand(const char *command) {
414 if (failed_to_start_)
415 return nullptr;
416 if (IsSameModule(path_)) {
417 Report("WARNING: Symbolizer was blocked from starting itself!\n");
418 failed_to_start_ = true;
419 return nullptr;
420 }
421 for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
422 // Start or restart symbolizer if we failed to send command to it.
423 if (const char *res = SendCommandImpl(command))
424 return res;
425 Restart();
426 }
427 if (!failed_to_start_) {
428 Report("WARNING: Failed to use and restart external symbolizer!\n");
429 failed_to_start_ = true;
430 }
431 return 0;
432}
433
434const char *SymbolizerProcess::SendCommandImpl(const char *command) {
435 if (input_fd_ == kInvalidFd((fd_t)-1) || output_fd_ == kInvalidFd((fd_t)-1))
436 return 0;
437 if (!WriteToSymbolizer(command, internal_strlen(command)))
438 return 0;
439 if (!ReadFromSymbolizer(buffer_, kBufferSize))
440 return 0;
441 return buffer_;
442}
443
444bool SymbolizerProcess::Restart() {
445 if (input_fd_ != kInvalidFd((fd_t)-1))
446 CloseFile(input_fd_);
447 if (output_fd_ != kInvalidFd((fd_t)-1))
448 CloseFile(output_fd_);
449 return StartSymbolizerSubprocess();
450}
451
452bool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) {
453 if (max_length == 0)
454 return true;
455 uptr read_len = 0;
456 while (true) {
457 uptr just_read = 0;
458 bool success = ReadFromFile(input_fd_, buffer + read_len,
459 max_length - read_len - 1, &just_read);
460 // We can't read 0 bytes, as we don't expect external symbolizer to close
461 // its stdout.
462 if (!success || just_read == 0) {
463 Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
464 return false;
465 }
466 read_len += just_read;
467 if (ReachedEndOfOutput(buffer, read_len))
468 break;
469 if (read_len + 1 == max_length) {
470 Report("WARNING: Symbolizer buffer too small\n");
471 read_len = 0;
472 break;
473 }
474 }
475 buffer[read_len] = '\0';
476 return true;
477}
478
479bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
480 if (length == 0)
481 return true;
482 uptr write_len = 0;
483 bool success = WriteToFile(output_fd_, buffer, length, &write_len);
484 if (!success || write_len != length) {
485 Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
486 return false;
487 }
488 return true;
489}
490
491#endif // !SANITIZER_SYMBOLIZER_MARKUP
492
493} // namespace __sanitizer