1353944Sdim//===-- sanitizer_symbolizer_libcdep.cpp ----------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is shared between AddressSanitizer and ThreadSanitizer 10353944Sdim// run-time libraries. 11353944Sdim//===----------------------------------------------------------------------===// 12353944Sdim 13353944Sdim#include "sanitizer_allocator_internal.h" 14353944Sdim#include "sanitizer_internal_defs.h" 15353944Sdim#include "sanitizer_symbolizer_internal.h" 16353944Sdim 17353944Sdimnamespace __sanitizer { 18353944Sdim 19353944SdimSymbolizer *Symbolizer::GetOrInit() { 20353944Sdim SpinMutexLock l(&init_mu_); 21353944Sdim if (symbolizer_) 22353944Sdim return symbolizer_; 23353944Sdim symbolizer_ = PlatformInit(); 24353944Sdim CHECK(symbolizer_); 25353944Sdim return symbolizer_; 26353944Sdim} 27353944Sdim 28353944Sdim// See sanitizer_symbolizer_markup.cpp. 29353944Sdim#if !SANITIZER_SYMBOLIZER_MARKUP 30353944Sdim 31353944Sdimconst char *ExtractToken(const char *str, const char *delims, char **result) { 32353944Sdim uptr prefix_len = internal_strcspn(str, delims); 33353944Sdim *result = (char*)InternalAlloc(prefix_len + 1); 34353944Sdim internal_memcpy(*result, str, prefix_len); 35353944Sdim (*result)[prefix_len] = '\0'; 36353944Sdim const char *prefix_end = str + prefix_len; 37353944Sdim if (*prefix_end != '\0') prefix_end++; 38353944Sdim return prefix_end; 39353944Sdim} 40353944Sdim 41353944Sdimconst char *ExtractInt(const char *str, const char *delims, int *result) { 42353944Sdim char *buff; 43353944Sdim const char *ret = ExtractToken(str, delims, &buff); 44353944Sdim if (buff != 0) { 45353944Sdim *result = (int)internal_atoll(buff); 46353944Sdim } 47353944Sdim InternalFree(buff); 48353944Sdim return ret; 49353944Sdim} 50353944Sdim 51353944Sdimconst char *ExtractUptr(const char *str, const char *delims, uptr *result) { 52353944Sdim char *buff; 53353944Sdim const char *ret = ExtractToken(str, delims, &buff); 54353944Sdim if (buff != 0) { 55353944Sdim *result = (uptr)internal_atoll(buff); 56353944Sdim } 57353944Sdim InternalFree(buff); 58353944Sdim return ret; 59353944Sdim} 60353944Sdim 61353944Sdimconst char *ExtractSptr(const char *str, const char *delims, sptr *result) { 62353944Sdim char *buff; 63353944Sdim const char *ret = ExtractToken(str, delims, &buff); 64353944Sdim if (buff != 0) { 65353944Sdim *result = (sptr)internal_atoll(buff); 66353944Sdim } 67353944Sdim InternalFree(buff); 68353944Sdim return ret; 69353944Sdim} 70353944Sdim 71353944Sdimconst char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, 72353944Sdim char **result) { 73353944Sdim const char *found_delimiter = internal_strstr(str, delimiter); 74353944Sdim uptr prefix_len = 75353944Sdim found_delimiter ? found_delimiter - str : internal_strlen(str); 76353944Sdim *result = (char *)InternalAlloc(prefix_len + 1); 77353944Sdim internal_memcpy(*result, str, prefix_len); 78353944Sdim (*result)[prefix_len] = '\0'; 79353944Sdim const char *prefix_end = str + prefix_len; 80353944Sdim if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter); 81353944Sdim return prefix_end; 82353944Sdim} 83353944Sdim 84353944SdimSymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { 85353944Sdim BlockingMutexLock l(&mu_); 86353944Sdim const char *module_name; 87353944Sdim uptr module_offset; 88353944Sdim ModuleArch arch; 89353944Sdim SymbolizedStack *res = SymbolizedStack::New(addr); 90353944Sdim if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset, 91353944Sdim &arch)) 92353944Sdim return res; 93353944Sdim // Always fill data about module name and offset. 94353944Sdim res->info.FillModuleInfo(module_name, module_offset, arch); 95353944Sdim for (auto &tool : tools_) { 96353944Sdim SymbolizerScope sym_scope(this); 97353944Sdim if (tool.SymbolizePC(addr, res)) { 98353944Sdim return res; 99353944Sdim } 100353944Sdim } 101353944Sdim return res; 102353944Sdim} 103353944Sdim 104353944Sdimbool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { 105353944Sdim BlockingMutexLock l(&mu_); 106353944Sdim const char *module_name; 107353944Sdim uptr module_offset; 108353944Sdim ModuleArch arch; 109353944Sdim if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset, 110353944Sdim &arch)) 111353944Sdim return false; 112353944Sdim info->Clear(); 113353944Sdim info->module = internal_strdup(module_name); 114353944Sdim info->module_offset = module_offset; 115353944Sdim info->module_arch = arch; 116353944Sdim for (auto &tool : tools_) { 117353944Sdim SymbolizerScope sym_scope(this); 118353944Sdim if (tool.SymbolizeData(addr, info)) { 119353944Sdim return true; 120353944Sdim } 121353944Sdim } 122353944Sdim return true; 123353944Sdim} 124353944Sdim 125353944Sdimbool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { 126353944Sdim BlockingMutexLock l(&mu_); 127353944Sdim const char *module_name; 128353944Sdim if (!FindModuleNameAndOffsetForAddress( 129353944Sdim addr, &module_name, &info->module_offset, &info->module_arch)) 130353944Sdim return false; 131353944Sdim info->module = internal_strdup(module_name); 132353944Sdim for (auto &tool : tools_) { 133353944Sdim SymbolizerScope sym_scope(this); 134353944Sdim if (tool.SymbolizeFrame(addr, info)) { 135353944Sdim return true; 136353944Sdim } 137353944Sdim } 138353944Sdim return true; 139353944Sdim} 140353944Sdim 141353944Sdimbool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, 142353944Sdim uptr *module_address) { 143353944Sdim BlockingMutexLock l(&mu_); 144353944Sdim const char *internal_module_name = nullptr; 145353944Sdim ModuleArch arch; 146353944Sdim if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name, 147353944Sdim module_address, &arch)) 148353944Sdim return false; 149353944Sdim 150353944Sdim if (module_name) 151353944Sdim *module_name = module_names_.GetOwnedCopy(internal_module_name); 152353944Sdim return true; 153353944Sdim} 154353944Sdim 155353944Sdimvoid Symbolizer::Flush() { 156353944Sdim BlockingMutexLock l(&mu_); 157353944Sdim for (auto &tool : tools_) { 158353944Sdim SymbolizerScope sym_scope(this); 159353944Sdim tool.Flush(); 160353944Sdim } 161353944Sdim} 162353944Sdim 163353944Sdimconst char *Symbolizer::Demangle(const char *name) { 164353944Sdim BlockingMutexLock l(&mu_); 165353944Sdim for (auto &tool : tools_) { 166353944Sdim SymbolizerScope sym_scope(this); 167353944Sdim if (const char *demangled = tool.Demangle(name)) 168353944Sdim return demangled; 169353944Sdim } 170353944Sdim return PlatformDemangle(name); 171353944Sdim} 172353944Sdim 173353944Sdimbool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, 174353944Sdim const char **module_name, 175353944Sdim uptr *module_offset, 176353944Sdim ModuleArch *module_arch) { 177353944Sdim const LoadedModule *module = FindModuleForAddress(address); 178353944Sdim if (module == nullptr) 179353944Sdim return false; 180353944Sdim *module_name = module->full_name(); 181353944Sdim *module_offset = address - module->base_address(); 182353944Sdim *module_arch = module->arch(); 183353944Sdim return true; 184353944Sdim} 185353944Sdim 186353944Sdimvoid Symbolizer::RefreshModules() { 187353944Sdim modules_.init(); 188353944Sdim fallback_modules_.fallbackInit(); 189353944Sdim RAW_CHECK(modules_.size() > 0); 190353944Sdim modules_fresh_ = true; 191353944Sdim} 192353944Sdim 193353944Sdimstatic const LoadedModule *SearchForModule(const ListOfModules &modules, 194353944Sdim uptr address) { 195353944Sdim for (uptr i = 0; i < modules.size(); i++) { 196353944Sdim if (modules[i].containsAddress(address)) { 197353944Sdim return &modules[i]; 198353944Sdim } 199353944Sdim } 200353944Sdim return nullptr; 201353944Sdim} 202353944Sdim 203353944Sdimconst LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { 204353944Sdim bool modules_were_reloaded = false; 205353944Sdim if (!modules_fresh_) { 206353944Sdim RefreshModules(); 207353944Sdim modules_were_reloaded = true; 208353944Sdim } 209353944Sdim const LoadedModule *module = SearchForModule(modules_, address); 210353944Sdim if (module) return module; 211353944Sdim 212353944Sdim // dlopen/dlclose interceptors invalidate the module list, but when 213353944Sdim // interception is disabled, we need to retry if the lookup fails in 214353944Sdim // case the module list changed. 215353944Sdim#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE 216353944Sdim if (!modules_were_reloaded) { 217353944Sdim RefreshModules(); 218353944Sdim module = SearchForModule(modules_, address); 219353944Sdim if (module) return module; 220353944Sdim } 221353944Sdim#endif 222353944Sdim 223353944Sdim if (fallback_modules_.size()) { 224353944Sdim module = SearchForModule(fallback_modules_, address); 225353944Sdim } 226353944Sdim return module; 227353944Sdim} 228353944Sdim 229353944Sdim// For now we assume the following protocol: 230353944Sdim// For each request of the form 231353944Sdim// <module_name> <module_offset> 232353944Sdim// passed to STDIN, external symbolizer prints to STDOUT response: 233353944Sdim// <function_name> 234353944Sdim// <file_name>:<line_number>:<column_number> 235353944Sdim// <function_name> 236353944Sdim// <file_name>:<line_number>:<column_number> 237353944Sdim// ... 238353944Sdim// <empty line> 239353944Sdimclass LLVMSymbolizerProcess : public SymbolizerProcess { 240353944Sdim public: 241353944Sdim explicit LLVMSymbolizerProcess(const char *path) 242353944Sdim : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_MAC) {} 243353944Sdim 244353944Sdim private: 245353944Sdim bool ReachedEndOfOutput(const char *buffer, uptr length) const override { 246353944Sdim // Empty line marks the end of llvm-symbolizer output. 247353944Sdim return length >= 2 && buffer[length - 1] == '\n' && 248353944Sdim buffer[length - 2] == '\n'; 249353944Sdim } 250353944Sdim 251353944Sdim // When adding a new architecture, don't forget to also update 252353944Sdim // script/asan_symbolize.py and sanitizer_common.h. 253353944Sdim void GetArgV(const char *path_to_binary, 254353944Sdim const char *(&argv)[kArgVMax]) const override { 255353944Sdim#if defined(__x86_64h__) 256353944Sdim const char* const kSymbolizerArch = "--default-arch=x86_64h"; 257353944Sdim#elif defined(__x86_64__) 258353944Sdim const char* const kSymbolizerArch = "--default-arch=x86_64"; 259353944Sdim#elif defined(__i386__) 260353944Sdim const char* const kSymbolizerArch = "--default-arch=i386"; 261353944Sdim#elif defined(__aarch64__) 262353944Sdim const char* const kSymbolizerArch = "--default-arch=arm64"; 263353944Sdim#elif defined(__arm__) 264353944Sdim const char* const kSymbolizerArch = "--default-arch=arm"; 265353944Sdim#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 266353944Sdim const char* const kSymbolizerArch = "--default-arch=powerpc64"; 267353944Sdim#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 268353944Sdim const char* const kSymbolizerArch = "--default-arch=powerpc64le"; 269353944Sdim#elif defined(__s390x__) 270353944Sdim const char* const kSymbolizerArch = "--default-arch=s390x"; 271353944Sdim#elif defined(__s390__) 272353944Sdim const char* const kSymbolizerArch = "--default-arch=s390"; 273353944Sdim#else 274353944Sdim const char* const kSymbolizerArch = "--default-arch=unknown"; 275353944Sdim#endif 276353944Sdim 277353944Sdim const char *const inline_flag = common_flags()->symbolize_inline_frames 278353944Sdim ? "--inlining=true" 279353944Sdim : "--inlining=false"; 280353944Sdim int i = 0; 281353944Sdim argv[i++] = path_to_binary; 282353944Sdim argv[i++] = inline_flag; 283353944Sdim argv[i++] = kSymbolizerArch; 284353944Sdim argv[i++] = nullptr; 285353944Sdim } 286353944Sdim}; 287353944Sdim 288353944SdimLLVMSymbolizer::LLVMSymbolizer(const char *path, LowLevelAllocator *allocator) 289353944Sdim : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {} 290353944Sdim 291353944Sdim// Parse a <file>:<line>[:<column>] buffer. The file path may contain colons on 292353944Sdim// Windows, so extract tokens from the right hand side first. The column info is 293353944Sdim// also optional. 294353944Sdimstatic const char *ParseFileLineInfo(AddressInfo *info, const char *str) { 295353944Sdim char *file_line_info = 0; 296353944Sdim str = ExtractToken(str, "\n", &file_line_info); 297353944Sdim CHECK(file_line_info); 298353944Sdim 299353944Sdim if (uptr size = internal_strlen(file_line_info)) { 300353944Sdim char *back = file_line_info + size - 1; 301353944Sdim for (int i = 0; i < 2; ++i) { 302353944Sdim while (back > file_line_info && IsDigit(*back)) --back; 303353944Sdim if (*back != ':' || !IsDigit(back[1])) break; 304353944Sdim info->column = info->line; 305353944Sdim info->line = internal_atoll(back + 1); 306353944Sdim // Truncate the string at the colon to keep only filename. 307353944Sdim *back = '\0'; 308353944Sdim --back; 309353944Sdim } 310353944Sdim ExtractToken(file_line_info, "", &info->file); 311353944Sdim } 312353944Sdim 313353944Sdim InternalFree(file_line_info); 314353944Sdim return str; 315353944Sdim} 316353944Sdim 317353944Sdim// Parses one or more two-line strings in the following format: 318353944Sdim// <function_name> 319353944Sdim// <file_name>:<line_number>[:<column_number>] 320353944Sdim// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of 321353944Sdim// them use the same output format. 322353944Sdimvoid ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) { 323353944Sdim bool top_frame = true; 324353944Sdim SymbolizedStack *last = res; 325353944Sdim while (true) { 326353944Sdim char *function_name = 0; 327353944Sdim str = ExtractToken(str, "\n", &function_name); 328353944Sdim CHECK(function_name); 329353944Sdim if (function_name[0] == '\0') { 330353944Sdim // There are no more frames. 331353944Sdim InternalFree(function_name); 332353944Sdim break; 333353944Sdim } 334353944Sdim SymbolizedStack *cur; 335353944Sdim if (top_frame) { 336353944Sdim cur = res; 337353944Sdim top_frame = false; 338353944Sdim } else { 339353944Sdim cur = SymbolizedStack::New(res->info.address); 340353944Sdim cur->info.FillModuleInfo(res->info.module, res->info.module_offset, 341353944Sdim res->info.module_arch); 342353944Sdim last->next = cur; 343353944Sdim last = cur; 344353944Sdim } 345353944Sdim 346353944Sdim AddressInfo *info = &cur->info; 347353944Sdim info->function = function_name; 348353944Sdim str = ParseFileLineInfo(info, str); 349353944Sdim 350353944Sdim // Functions and filenames can be "??", in which case we write 0 351353944Sdim // to address info to mark that names are unknown. 352353944Sdim if (0 == internal_strcmp(info->function, "??")) { 353353944Sdim InternalFree(info->function); 354353944Sdim info->function = 0; 355353944Sdim } 356353944Sdim if (0 == internal_strcmp(info->file, "??")) { 357353944Sdim InternalFree(info->file); 358353944Sdim info->file = 0; 359353944Sdim } 360353944Sdim } 361353944Sdim} 362353944Sdim 363353944Sdim// Parses a two-line string in the following format: 364353944Sdim// <symbol_name> 365353944Sdim// <start_address> <size> 366353944Sdim// Used by LLVMSymbolizer and InternalSymbolizer. 367353944Sdimvoid ParseSymbolizeDataOutput(const char *str, DataInfo *info) { 368353944Sdim str = ExtractToken(str, "\n", &info->name); 369353944Sdim str = ExtractUptr(str, " ", &info->start); 370353944Sdim str = ExtractUptr(str, "\n", &info->size); 371353944Sdim} 372353944Sdim 373353944Sdimstatic void ParseSymbolizeFrameOutput(const char *str, 374353944Sdim InternalMmapVector<LocalInfo> *locals) { 375353944Sdim if (internal_strncmp(str, "??", 2) == 0) 376353944Sdim return; 377353944Sdim 378353944Sdim while (*str) { 379353944Sdim LocalInfo local; 380353944Sdim str = ExtractToken(str, "\n", &local.function_name); 381353944Sdim str = ExtractToken(str, "\n", &local.name); 382353944Sdim 383353944Sdim AddressInfo addr; 384353944Sdim str = ParseFileLineInfo(&addr, str); 385353944Sdim local.decl_file = addr.file; 386353944Sdim local.decl_line = addr.line; 387353944Sdim 388353944Sdim local.has_frame_offset = internal_strncmp(str, "??", 2) != 0; 389353944Sdim str = ExtractSptr(str, " ", &local.frame_offset); 390353944Sdim 391353944Sdim local.has_size = internal_strncmp(str, "??", 2) != 0; 392353944Sdim str = ExtractUptr(str, " ", &local.size); 393353944Sdim 394353944Sdim local.has_tag_offset = internal_strncmp(str, "??", 2) != 0; 395353944Sdim str = ExtractUptr(str, "\n", &local.tag_offset); 396353944Sdim 397353944Sdim locals->push_back(local); 398353944Sdim } 399353944Sdim} 400353944Sdim 401353944Sdimbool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { 402353944Sdim AddressInfo *info = &stack->info; 403353944Sdim const char *buf = FormatAndSendCommand( 404353944Sdim "CODE", info->module, info->module_offset, info->module_arch); 405353944Sdim if (buf) { 406353944Sdim ParseSymbolizePCOutput(buf, stack); 407353944Sdim return true; 408353944Sdim } 409353944Sdim return false; 410353944Sdim} 411353944Sdim 412353944Sdimbool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { 413353944Sdim const char *buf = FormatAndSendCommand( 414353944Sdim "DATA", info->module, info->module_offset, info->module_arch); 415353944Sdim if (buf) { 416353944Sdim ParseSymbolizeDataOutput(buf, info); 417353944Sdim info->start += (addr - info->module_offset); // Add the base address. 418353944Sdim return true; 419353944Sdim } 420353944Sdim return false; 421353944Sdim} 422353944Sdim 423353944Sdimbool LLVMSymbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { 424353944Sdim const char *buf = FormatAndSendCommand( 425353944Sdim "FRAME", info->module, info->module_offset, info->module_arch); 426353944Sdim if (buf) { 427353944Sdim ParseSymbolizeFrameOutput(buf, &info->locals); 428353944Sdim return true; 429353944Sdim } 430353944Sdim return false; 431353944Sdim} 432353944Sdim 433353944Sdimconst char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix, 434353944Sdim const char *module_name, 435353944Sdim uptr module_offset, 436353944Sdim ModuleArch arch) { 437353944Sdim CHECK(module_name); 438353944Sdim if (arch == kModuleArchUnknown) { 439353944Sdim if (internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n", 440353944Sdim command_prefix, module_name, 441353944Sdim module_offset) >= static_cast<int>(kBufferSize)) { 442353944Sdim Report("WARNING: Command buffer too small"); 443353944Sdim return nullptr; 444353944Sdim } 445353944Sdim } else { 446353944Sdim if (internal_snprintf(buffer_, kBufferSize, "%s \"%s:%s\" 0x%zx\n", 447353944Sdim command_prefix, module_name, ModuleArchToString(arch), 448353944Sdim module_offset) >= static_cast<int>(kBufferSize)) { 449353944Sdim Report("WARNING: Command buffer too small"); 450353944Sdim return nullptr; 451353944Sdim } 452353944Sdim } 453353944Sdim return symbolizer_process_->SendCommand(buffer_); 454353944Sdim} 455353944Sdim 456353944SdimSymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn) 457353944Sdim : path_(path), 458353944Sdim input_fd_(kInvalidFd), 459353944Sdim output_fd_(kInvalidFd), 460353944Sdim times_restarted_(0), 461353944Sdim failed_to_start_(false), 462353944Sdim reported_invalid_path_(false), 463353944Sdim use_posix_spawn_(use_posix_spawn) { 464353944Sdim CHECK(path_); 465353944Sdim CHECK_NE(path_[0], '\0'); 466353944Sdim} 467353944Sdim 468353944Sdimstatic bool IsSameModule(const char* path) { 469353944Sdim if (const char* ProcessName = GetProcessName()) { 470353944Sdim if (const char* SymbolizerName = StripModuleName(path)) { 471353944Sdim return !internal_strcmp(ProcessName, SymbolizerName); 472353944Sdim } 473353944Sdim } 474353944Sdim return false; 475353944Sdim} 476353944Sdim 477353944Sdimconst char *SymbolizerProcess::SendCommand(const char *command) { 478353944Sdim if (failed_to_start_) 479353944Sdim return nullptr; 480353944Sdim if (IsSameModule(path_)) { 481353944Sdim Report("WARNING: Symbolizer was blocked from starting itself!\n"); 482353944Sdim failed_to_start_ = true; 483353944Sdim return nullptr; 484353944Sdim } 485353944Sdim for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) { 486353944Sdim // Start or restart symbolizer if we failed to send command to it. 487353944Sdim if (const char *res = SendCommandImpl(command)) 488353944Sdim return res; 489353944Sdim Restart(); 490353944Sdim } 491353944Sdim if (!failed_to_start_) { 492353944Sdim Report("WARNING: Failed to use and restart external symbolizer!\n"); 493353944Sdim failed_to_start_ = true; 494353944Sdim } 495353944Sdim return 0; 496353944Sdim} 497353944Sdim 498353944Sdimconst char *SymbolizerProcess::SendCommandImpl(const char *command) { 499353944Sdim if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd) 500353944Sdim return 0; 501353944Sdim if (!WriteToSymbolizer(command, internal_strlen(command))) 502353944Sdim return 0; 503353944Sdim if (!ReadFromSymbolizer(buffer_, kBufferSize)) 504353944Sdim return 0; 505353944Sdim return buffer_; 506353944Sdim} 507353944Sdim 508353944Sdimbool SymbolizerProcess::Restart() { 509353944Sdim if (input_fd_ != kInvalidFd) 510353944Sdim CloseFile(input_fd_); 511353944Sdim if (output_fd_ != kInvalidFd) 512353944Sdim CloseFile(output_fd_); 513353944Sdim return StartSymbolizerSubprocess(); 514353944Sdim} 515353944Sdim 516353944Sdimbool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) { 517353944Sdim if (max_length == 0) 518353944Sdim return true; 519353944Sdim uptr read_len = 0; 520353944Sdim while (true) { 521353944Sdim uptr just_read = 0; 522353944Sdim bool success = ReadFromFile(input_fd_, buffer + read_len, 523353944Sdim max_length - read_len - 1, &just_read); 524353944Sdim // We can't read 0 bytes, as we don't expect external symbolizer to close 525353944Sdim // its stdout. 526353944Sdim if (!success || just_read == 0) { 527353944Sdim Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_); 528353944Sdim return false; 529353944Sdim } 530353944Sdim read_len += just_read; 531353944Sdim if (ReachedEndOfOutput(buffer, read_len)) 532353944Sdim break; 533353944Sdim if (read_len + 1 == max_length) { 534353944Sdim Report("WARNING: Symbolizer buffer too small\n"); 535353944Sdim read_len = 0; 536353944Sdim break; 537353944Sdim } 538353944Sdim } 539353944Sdim buffer[read_len] = '\0'; 540353944Sdim return true; 541353944Sdim} 542353944Sdim 543353944Sdimbool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) { 544353944Sdim if (length == 0) 545353944Sdim return true; 546353944Sdim uptr write_len = 0; 547353944Sdim bool success = WriteToFile(output_fd_, buffer, length, &write_len); 548353944Sdim if (!success || write_len != length) { 549353944Sdim Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_); 550353944Sdim return false; 551353944Sdim } 552353944Sdim return true; 553353944Sdim} 554353944Sdim 555353944Sdim#endif // !SANITIZER_SYMBOLIZER_MARKUP 556353944Sdim 557353944Sdim} // namespace __sanitizer 558