1c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===-- sanitizer_symbolizer_libcdep.cc -----------------------------------===// 2c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// 3c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// The LLVM Compiler Infrastructure 4c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// 5c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// This file is distributed under the University of Illinois Open Source 6c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// License. See LICENSE.TXT for details. 7c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// 8c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===----------------------------------------------------------------------===// 9c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// 10c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// This file is shared between AddressSanitizer and ThreadSanitizer 11c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne// run-time libraries. 12c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne//===----------------------------------------------------------------------===// 13c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne 147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_allocator_internal.h" 15c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne#include "sanitizer_internal_defs.h" 167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "sanitizer_symbolizer_internal.h" 17c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne 18c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbournenamespace __sanitizer { 19c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne 207c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractToken(const char *str, const char *delims, char **result) { 217c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar uptr prefix_len = internal_strcspn(str, delims); 227c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *result = (char*)InternalAlloc(prefix_len + 1); 237c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar internal_memcpy(*result, str, prefix_len); 247c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar (*result)[prefix_len] = '\0'; 257c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const char *prefix_end = str + prefix_len; 267c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (*prefix_end != '\0') prefix_end++; 277c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return prefix_end; 287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractInt(const char *str, const char *delims, int *result) { 317c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar char *buff; 327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const char *ret = ExtractToken(str, delims, &buff); 337c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (buff != 0) { 347c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *result = (int)internal_atoll(buff); 357c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar InternalFree(buff); 377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return ret; 387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 397c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 407c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractUptr(const char *str, const char *delims, uptr *result) { 417c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar char *buff; 427c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const char *ret = ExtractToken(str, delims, &buff); 437c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (buff != 0) { 447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *result = (uptr)internal_atoll(buff); 457c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar } 467c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar InternalFree(buff); 477c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return ret; 487c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 497c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 507c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, 517c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar char **result) { 527c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const char *found_delimiter = internal_strstr(str, delimiter); 537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar uptr prefix_len = 547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar found_delimiter ? found_delimiter - str : internal_strlen(str); 557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar *result = (char *)InternalAlloc(prefix_len + 1); 567c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar internal_memcpy(*result, str, prefix_len); 577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar (*result)[prefix_len] = '\0'; 587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar const char *prefix_end = str + prefix_len; 597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter); 607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return prefix_end; 617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar} 627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar 63259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga NainarSymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { 64259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 65259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar const char *module_name; 66259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar uptr module_offset; 67259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar SymbolizedStack *res = SymbolizedStack::New(addr); 68259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) 69259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return res; 70259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar // Always fill data about module name and offset. 71259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar res->info.FillModuleInfo(module_name, module_offset); 72259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (auto iter = Iterator(&tools_); iter.hasNext();) { 73259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar auto *tool = iter.next(); 74259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar SymbolizerScope sym_scope(this); 75259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (tool->SymbolizePC(addr, res)) { 76259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return res; 77259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 78259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 79259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return res; 80259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 81259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 82259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { 83259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 84259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar const char *module_name; 85259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar uptr module_offset; 86259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) 87259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return false; 88259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar info->Clear(); 89259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar info->module = internal_strdup(module_name); 90259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar info->module_offset = module_offset; 91259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (auto iter = Iterator(&tools_); iter.hasNext();) { 92259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar auto *tool = iter.next(); 93259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar SymbolizerScope sym_scope(this); 94259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (tool->SymbolizeData(addr, info)) { 95259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return true; 96259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 97259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 98259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return true; 99259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 100259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 101259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, 102259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar uptr *module_address) { 103259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 104259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar const char *internal_module_name = nullptr; 105259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name, 106259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar module_address)) 107259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return false; 108259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 109259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (module_name) 110259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar *module_name = module_names_.GetOwnedCopy(internal_module_name); 111259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return true; 112259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 113259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 114259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarvoid Symbolizer::Flush() { 115259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 116259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (auto iter = Iterator(&tools_); iter.hasNext();) { 117259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar auto *tool = iter.next(); 118259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar SymbolizerScope sym_scope(this); 119259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar tool->Flush(); 120259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 121259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 122259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 123259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarconst char *Symbolizer::Demangle(const char *name) { 124259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 125259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (auto iter = Iterator(&tools_); iter.hasNext();) { 126259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar auto *tool = iter.next(); 127259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar SymbolizerScope sym_scope(this); 128259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (const char *demangled = tool->Demangle(name)) 129259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return demangled; 130259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 131259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return PlatformDemangle(name); 132259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 133259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 134259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarvoid Symbolizer::PrepareForSandboxing() { 135259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar BlockingMutexLock l(&mu_); 136259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar PlatformPrepareForSandboxing(); 137259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 138259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 139259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, 140259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar const char **module_name, 141259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar uptr *module_offset) { 142259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar LoadedModule *module = FindModuleForAddress(address); 143259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (module == 0) 144259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return false; 145259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar *module_name = module->full_name(); 146259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar *module_offset = address - module->base_address(); 147259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return true; 148259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 149259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 150259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga NainarLoadedModule *Symbolizer::FindModuleForAddress(uptr address) { 151259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar bool modules_were_reloaded = false; 152259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (!modules_fresh_) { 153259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (uptr i = 0; i < n_modules_; i++) 154259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar modules_[i].clear(); 155259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar n_modules_ = 156259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar GetListOfModules(modules_, kMaxNumberOfModules, /* filter */ nullptr); 157259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar CHECK_GT(n_modules_, 0); 158259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar CHECK_LT(n_modules_, kMaxNumberOfModules); 159259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar modules_fresh_ = true; 160259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar modules_were_reloaded = true; 161259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 162259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar for (uptr i = 0; i < n_modules_; i++) { 163259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (modules_[i].containsAddress(address)) { 164259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return &modules_[i]; 165259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 166259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 167259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar // Reload the modules and look up again, if we haven't tried it yet. 168259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar if (!modules_were_reloaded) { 169259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors. 170259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar // It's too aggressive to reload the list of modules each time we fail 171259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar // to find a module for a given address. 172259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar modules_fresh_ = false; 173259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return FindModuleForAddress(address); 174259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar } 175259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return 0; 176259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar} 177259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 178c1a1ed62228288155459d39194995a36aca4a8a6Peter CollingbourneSymbolizer *Symbolizer::GetOrInit() { 179e00495aa0f3b114c7b764769d9450e5d2efb8e64Alexey Samsonov SpinMutexLock l(&init_mu_); 1806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (symbolizer_) 1816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return symbolizer_; 1827c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar symbolizer_ = PlatformInit(); 1837c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar CHECK(symbolizer_); 1847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return symbolizer_; 185c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne} 186c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne 1873d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// For now we assume the following protocol: 1883d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// For each request of the form 1893d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <module_name> <module_offset> 1903d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// passed to STDIN, external symbolizer prints to STDOUT response: 1913d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <function_name> 1923d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <file_name>:<line_number>:<column_number> 1933d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <function_name> 1943d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <file_name>:<line_number>:<column_number> 1953d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// ... 1963d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <empty line> 1973d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarclass LLVMSymbolizerProcess : public SymbolizerProcess { 1983d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar public: 1993d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {} 2003d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2013d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar private: 2023d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar bool ReachedEndOfOutput(const char *buffer, uptr length) const override { 2033d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Empty line marks the end of llvm-symbolizer output. 2043d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return length >= 2 && buffer[length - 1] == '\n' && 2053d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar buffer[length - 2] == '\n'; 2063d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 2073d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2083d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar void GetArgV(const char *path_to_binary, 2093d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char *(&argv)[kArgVMax]) const override { 2103d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#if defined(__x86_64h__) 2113d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=x86_64h"; 2123d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#elif defined(__x86_64__) 2133d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=x86_64"; 2143d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#elif defined(__i386__) 2153d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=i386"; 2163d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__) 2173d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=powerpc64"; 2183d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) 2193d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=powerpc64le"; 2203d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#else 2213d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char* const kSymbolizerArch = "--default-arch=unknown"; 2223d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#endif 2233d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2243d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar const char *const inline_flag = common_flags()->symbolize_inline_frames 2253d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar ? "--inlining=true" 2263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar : "--inlining=false"; 2273d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar int i = 0; 2283d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar argv[i++] = path_to_binary; 2293d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar argv[i++] = inline_flag; 2303d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar argv[i++] = kSymbolizerArch; 2313d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar argv[i++] = nullptr; 2323d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 2333d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar}; 2343d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2353d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga NainarLLVMSymbolizer::LLVMSymbolizer(const char *path, LowLevelAllocator *allocator) 2363d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {} 2373d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2383d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Parse a <file>:<line>[:<column>] buffer. The file path may contain colons on 2393d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Windows, so extract tokens from the right hand side first. The column info is 2403d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// also optional. 2413d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarstatic const char *ParseFileLineInfo(AddressInfo *info, const char *str) { 2423d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar char *file_line_info = 0; 2433d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ExtractToken(str, "\n", &file_line_info); 2443d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK(file_line_info); 2453d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Parse the last :<int>, which must be there. 2463d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar char *last_colon = internal_strrchr(file_line_info, ':'); 2473d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK(last_colon); 2483d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar int line_or_column = internal_atoll(last_colon + 1); 2493d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Truncate the string at the last colon and find the next-to-last colon. 2503d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar *last_colon = '\0'; 2513d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar last_colon = internal_strrchr(file_line_info, ':'); 2523d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (last_colon && IsDigit(last_colon[1])) { 2533d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // If the second-to-last colon is followed by a digit, it must be the line 2543d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // number, and the previous parsed number was a column. 2553d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->line = internal_atoll(last_colon + 1); 2563d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->column = line_or_column; 2573d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar *last_colon = '\0'; 2583d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } else { 2593d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Otherwise, we have line info but no column info. 2603d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->line = line_or_column; 2613d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->column = 0; 2623d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 2633d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar ExtractToken(file_line_info, "", &info->file); 2643d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar InternalFree(file_line_info); 2653d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return str; 2663d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 2673d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2683d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Parses one or more two-line strings in the following format: 2693d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <function_name> 2703d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <file_name>:<line_number>[:<column_number>] 2713d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of 2723d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// them use the same output format. 2733d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarvoid ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) { 2743d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar bool top_frame = true; 2753d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar SymbolizedStack *last = res; 2763d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar while (true) { 2773d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar char *function_name = 0; 2783d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ExtractToken(str, "\n", &function_name); 2793d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK(function_name); 2803d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (function_name[0] == '\0') { 2813d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // There are no more frames. 2823d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar InternalFree(function_name); 2833d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar break; 2843d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 2853d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar SymbolizedStack *cur; 2863d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (top_frame) { 2873d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar cur = res; 2883d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar top_frame = false; 2893d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } else { 2903d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar cur = SymbolizedStack::New(res->info.address); 2913d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar cur->info.FillModuleInfo(res->info.module, res->info.module_offset); 2923d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar last->next = cur; 2933d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar last = cur; 2943d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 2953d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 2963d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar AddressInfo *info = &cur->info; 2973d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->function = function_name; 2983d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ParseFileLineInfo(info, str); 2993d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3003d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Functions and filenames can be "??", in which case we write 0 3013d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // to address info to mark that names are unknown. 3023d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (0 == internal_strcmp(info->function, "??")) { 3033d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar InternalFree(info->function); 3043d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->function = 0; 3053d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3063d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (0 == internal_strcmp(info->file, "??")) { 3073d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar InternalFree(info->file); 3083d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->file = 0; 3093d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3103d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3113d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3123d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3133d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Parses a two-line string in the following format: 3143d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <symbol_name> 3153d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// <start_address> <size> 3163d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar// Used by LLVMSymbolizer and InternalSymbolizer. 3173d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarvoid ParseSymbolizeDataOutput(const char *str, DataInfo *info) { 3183d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ExtractToken(str, "\n", &info->name); 3193d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ExtractUptr(str, " ", &info->start); 3203d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar str = ExtractUptr(str, "\n", &info->size); 3213d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3223d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3233d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { 3243d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module, 3253d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar stack->info.module_offset)) { 3263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar ParseSymbolizePCOutput(buf, stack); 3273d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 3283d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3293d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return false; 3303d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3313d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3323d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { 3333d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (const char *buf = 3343d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar SendCommand(/*is_data*/ true, info->module, info->module_offset)) { 3353d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar ParseSymbolizeDataOutput(buf, info); 3363d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar info->start += (addr - info->module_offset); // Add the base address. 3373d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 3383d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3393d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return false; 3403d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3413d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3423d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarconst char *LLVMSymbolizer::SendCommand(bool is_data, const char *module_name, 3433d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar uptr module_offset) { 3443d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK(module_name); 3453d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n", 3463d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar is_data ? "DATA " : "", module_name, module_offset); 3473d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return symbolizer_process_->SendCommand(buffer_); 3483d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3493d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3503d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga NainarSymbolizerProcess::SymbolizerProcess(const char *path, bool use_forkpty) 3513d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar : path_(path), 3523d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar input_fd_(kInvalidFd), 3533d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar output_fd_(kInvalidFd), 3543d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar times_restarted_(0), 3553d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar failed_to_start_(false), 3563d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar reported_invalid_path_(false), 3573d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar use_forkpty_(use_forkpty) { 3583d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK(path_); 3593d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CHECK_NE(path_[0], '\0'); 3603d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3613d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3623d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarconst char *SymbolizerProcess::SendCommand(const char *command) { 3633d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) { 3643d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // Start or restart symbolizer if we failed to send command to it. 3653d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (const char *res = SendCommandImpl(command)) 3663d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return res; 3673d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar Restart(); 3683d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3693d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!failed_to_start_) { 3703d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar Report("WARNING: Failed to use and restart external symbolizer!\n"); 3713d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar failed_to_start_ = true; 3723d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 3733d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return 0; 3743d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3753d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3763d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarconst char *SymbolizerProcess::SendCommandImpl(const char *command) { 3773d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd) 3783d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return 0; 3793d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!WriteToSymbolizer(command, internal_strlen(command))) 3803d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return 0; 3813d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!ReadFromSymbolizer(buffer_, kBufferSize)) 3823d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return 0; 3833d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return buffer_; 3843d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3853d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3863d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool SymbolizerProcess::Restart() { 3873d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (input_fd_ != kInvalidFd) 3883d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CloseFile(input_fd_); 3893d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (output_fd_ != kInvalidFd) 3903d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar CloseFile(output_fd_); 3913d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return StartSymbolizerSubprocess(); 3923d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 3933d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 3943d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool SymbolizerProcess::ReadFromSymbolizer(char *buffer, uptr max_length) { 3953d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (max_length == 0) 3963d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 3973d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar uptr read_len = 0; 3983d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar while (true) { 3993d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar uptr just_read = 0; 4003d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar bool success = ReadFromFile(input_fd_, buffer + read_len, 4013d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar max_length - read_len - 1, &just_read); 4023d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // We can't read 0 bytes, as we don't expect external symbolizer to close 4033d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar // its stdout. 4043d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!success || just_read == 0) { 4053d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_); 4063d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return false; 4073d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 4083d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar read_len += just_read; 4093d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (ReachedEndOfOutput(buffer, read_len)) 4103d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar break; 4113d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 4123d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar buffer[read_len] = '\0'; 4133d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 4143d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 4153d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 4163d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) { 4173d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (length == 0) 4183d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 4193d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar uptr write_len = 0; 4203d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar bool success = WriteToFile(output_fd_, buffer, length, &write_len); 4213d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar if (!success || write_len != length) { 4223d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_); 4233d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return false; 4243d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar } 4253d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar return true; 4263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar} 4273d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar 428c1a1ed62228288155459d39194995a36aca4a8a6Peter Collingbourne} // namespace __sanitizer 429