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