@@ -253,6 +253,122 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace,
253
253
return true ;
254
254
}
255
255
256
+ #if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
257
+ void sys::symbolizeAddresses (AddressSet &Addresses,
258
+ SymbolizedAddressMap &SymbolizedAddresses) {
259
+ assert (!DisableSymbolicationFlag && !getenv (DisableSymbolizationEnv) &&
260
+ " Debugify origin stacktraces require symbolization to be enabled." );
261
+
262
+ // Convert Set of Addresses to ordered list.
263
+ SmallVector<void *, 0 > AddressList (Addresses.begin (), Addresses.end ());
264
+ if (AddressList.empty ())
265
+ return ;
266
+ int NumAddresses = AddressList.size ();
267
+ llvm::sort (AddressList);
268
+
269
+ // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
270
+ // alongside our binary, then in $PATH.
271
+ ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code ();
272
+ if (const char *Path = getenv (LLVMSymbolizerPathEnv)) {
273
+ LLVMSymbolizerPathOrErr = sys::findProgramByName (Path);
274
+ }
275
+ if (!LLVMSymbolizerPathOrErr)
276
+ LLVMSymbolizerPathOrErr = sys::findProgramByName (" llvm-symbolizer" );
277
+ assert (!!LLVMSymbolizerPathOrErr &&
278
+ " Debugify origin stacktraces require llvm-symbolizer." );
279
+ const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
280
+
281
+ // Try to guess the main executable name, since we don't have argv0 available
282
+ // here.
283
+ std::string MainExecutableName = sys::fs::getMainExecutable (nullptr , nullptr );
284
+
285
+ BumpPtrAllocator Allocator;
286
+ StringSaver StrPool (Allocator);
287
+ std::vector<const char *> Modules (NumAddresses, nullptr );
288
+ std::vector<intptr_t > Offsets (NumAddresses, 0 );
289
+ if (!findModulesAndOffsets (AddressList.data (), NumAddresses, Modules.data (),
290
+ Offsets.data (), MainExecutableName.c_str (),
291
+ StrPool))
292
+ return ;
293
+ int InputFD;
294
+ SmallString<32 > InputFile, OutputFile;
295
+ sys::fs::createTemporaryFile (" symbolizer-input" , " " , InputFD, InputFile);
296
+ sys::fs::createTemporaryFile (" symbolizer-output" , " " , OutputFile);
297
+ FileRemover InputRemover (InputFile.c_str ());
298
+ FileRemover OutputRemover (OutputFile.c_str ());
299
+
300
+ {
301
+ raw_fd_ostream Input (InputFD, true );
302
+ for (int i = 0 ; i < NumAddresses; i++) {
303
+ if (Modules[i])
304
+ Input << Modules[i] << " " << (void *)Offsets[i] << " \n " ;
305
+ }
306
+ }
307
+
308
+ std::optional<StringRef> Redirects[] = {InputFile.str (), OutputFile.str (),
309
+ StringRef (" " )};
310
+ StringRef Args[] = {" llvm-symbolizer" , " --functions=linkage" , " --inlining" ,
311
+ #ifdef _WIN32
312
+ // Pass --relative-address on Windows so that we don't
313
+ // have to add ImageBase from PE file.
314
+ // FIXME: Make this the default for llvm-symbolizer.
315
+ " --relative-address" ,
316
+ #endif
317
+ " --demangle" };
318
+ int RunResult =
319
+ sys::ExecuteAndWait (LLVMSymbolizerPath, Args, std::nullopt, Redirects);
320
+ if (RunResult != 0 )
321
+ return ;
322
+
323
+ // This report format is based on the sanitizer stack trace printer. See
324
+ // sanitizer_stacktrace_printer.cc in compiler-rt.
325
+ auto OutputBuf = MemoryBuffer::getFile (OutputFile.c_str ());
326
+ if (!OutputBuf)
327
+ return ;
328
+ StringRef Output = OutputBuf.get ()->getBuffer ();
329
+ SmallVector<StringRef, 32 > Lines;
330
+ Output.split (Lines, " \n " );
331
+ auto CurLine = Lines.begin ();
332
+ for (int i = 0 ; i < NumAddresses; i++) {
333
+ assert (!SymbolizedAddresses.contains (AddressList[i]));
334
+ std::string &SymbolizedAddr = SymbolizedAddresses[AddressList[i]];
335
+ raw_string_ostream OS (SymbolizedAddr);
336
+ if (!Modules[i]) {
337
+ OS << format_ptr (AddressList[i]) << ' \n ' ;
338
+ continue ;
339
+ }
340
+ // Read pairs of lines (function name and file/line info) until we
341
+ // encounter empty line.
342
+ for (bool IsFirst = true ;; IsFirst = false ) {
343
+ if (CurLine == Lines.end ())
344
+ return ;
345
+ StringRef FunctionName = *CurLine++;
346
+ if (FunctionName.empty ())
347
+ break ;
348
+ // Add indentation for lines after the first; we use 3 spaces, because
349
+ // currently that aligns with the expected indentation that will be added
350
+ // to the first line by Debugify.
351
+ if (!IsFirst)
352
+ OS << " " ;
353
+ OS << format_ptr (AddressList[i]) << ' ' ;
354
+ if (!FunctionName.starts_with (" ??" ))
355
+ OS << FunctionName << ' ' ;
356
+ if (CurLine == Lines.end ()) {
357
+ OS << ' \n ' ;
358
+ return ;
359
+ }
360
+ StringRef FileLineInfo = *CurLine++;
361
+ if (!FileLineInfo.starts_with (" ??" ))
362
+ OS << FileLineInfo;
363
+ else
364
+ OS << " (" << Modules[i] << ' +' << format_hex (Offsets[i], 0 ) << " )" ;
365
+ OS << ' \n ' ;
366
+ }
367
+ }
368
+ return ;
369
+ }
370
+ #endif
371
+
256
372
static bool printMarkupContext (raw_ostream &OS, const char *MainExecutableName);
257
373
258
374
LLVM_ATTRIBUTE_USED
0 commit comments