[llvm] r252118 - [Windows] Symbolize with llvm-symbolizer instead of dbghelp in a self-host

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 5 08:43:46 PST 2015


Your fix looks correct. Sorry for the breakage, I thought there'd be one
Unix implementation of that function...

On Wed, Nov 4, 2015 at 6:34 PM, Mehdi Amini <mehdi.amini at apple.com> wrote:

> Hi Reid,
>
> It seems that this commit broke the OS X build, I tried to fix it in
> r252137, can you take a look?
>
> Thanks,
>
> Mehdi
>
> > On Nov 4, 2015, at 5:07 PM, Reid Kleckner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
> >
> > Author: rnk
> > Date: Wed Nov  4 19:07:54 2015
> > New Revision: 252118
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=252118&view=rev
> > Log:
> > [Windows] Symbolize with llvm-symbolizer instead of dbghelp in a
> self-host
> >
> > Summary:
> > llvm-symbolizer understands both PDBs and DWARF, so it is more likely to
> > succeed at symbolization. If llvm-symbolizer is unavailable, we will
> > fall back to dbghelp. This also makes our crash traces more similar
> > between Windows and Linux.
> >
> > Reviewers: Bigcheese, zturner, chapuni
> >
> > Subscribers: llvm-commits
> >
> > Differential Revision: http://reviews.llvm.org/D12884
> >
> > Modified:
> >    llvm/trunk/lib/Support/Signals.cpp
> >    llvm/trunk/lib/Support/Unix/Signals.inc
> >    llvm/trunk/lib/Support/Windows/Signals.inc
> >
> > Modified: llvm/trunk/lib/Support/Signals.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Signals.cpp?rev=252118&r1=252117&r2=252118&view=diff
> >
> ==============================================================================
> > --- llvm/trunk/lib/Support/Signals.cpp (original)
> > +++ llvm/trunk/lib/Support/Signals.cpp Wed Nov  4 19:07:54 2015
> > @@ -12,10 +12,20 @@
> > //
> >
> //===----------------------------------------------------------------------===//
> >
> > +#include "llvm/ADT/STLExtras.h"
> > +#include "llvm/ADT/StringRef.h"
> > #include "llvm/Config/config.h"
> > +#include "llvm/Support/ErrorOr.h"
> > +#include "llvm/Support/FileSystem.h"
> > +#include "llvm/Support/FileUtilities.h"
> > +#include "llvm/Support/Format.h"
> > #include "llvm/Support/ManagedStatic.h"
> > +#include "llvm/Support/MemoryBuffer.h"
> > +#include "llvm/Support/Mutex.h"
> > +#include "llvm/Support/Program.h"
> > #include "llvm/Support/Signals.h"
> > -
> > +#include "llvm/Support/StringSaver.h"
> > +#include "llvm/Support/raw_ostream.h"
> > #include <vector>
> >
> > namespace llvm {
> > @@ -37,6 +47,118 @@ void sys::RunSignalHandlers() {
> > }
> > }
> >
> > +using namespace llvm;
> > +
> > +static bool findModulesAndOffsets(void **StackTrace, int Depth,
> > +                                  const char **Modules, intptr_t
> *Offsets,
> > +                                  const char *MainExecutableName,
> > +                                  StringSaver &StrPool);
> > +
> > +/// Format a pointer value as hexadecimal. Zero pad it out so its
> always the
> > +/// same width.
> > +static FormattedNumber format_ptr(void *PC) {
> > +  // Each byte is two hex digits plus 2 for the 0x prefix.
> > +  unsigned PtrWidth = 2 + 2 * sizeof(void *);
> > +  return format_hex((uint64_t)PC, PtrWidth);
> > +}
> > +
> > +/// Helper that launches llvm-symbolizer and symbolizes a backtrace.
> > +static bool printSymbolizedStackTrace(void **StackTrace, int Depth,
> > +                                      llvm::raw_ostream &OS) {
> > +  // FIXME: Subtract necessary number from StackTrace entries to turn
> return addresses
> > +  // into actual instruction addresses.
> > +  // Use llvm-symbolizer tool to symbolize the stack traces.
> > +  ErrorOr<std::string> LLVMSymbolizerPathOrErr =
> > +      sys::findProgramByName("llvm-symbolizer");
> > +  if (!LLVMSymbolizerPathOrErr)
> > +    return false;
> > +  const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
> > +  // We don't know argv0 or the address of main() at this point, but try
> > +  // to guess it anyway (it's possible on some platforms).
> > +  std::string MainExecutableName = sys::fs::getMainExecutable(nullptr,
> nullptr);
> > +  if (MainExecutableName.empty() ||
> > +      MainExecutableName.find("llvm-symbolizer") != std::string::npos)
> > +    return false;
> > +
> > +  BumpPtrAllocator Allocator;
> > +  StringSaver StrPool(Allocator);
> > +  std::vector<const char *> Modules(Depth, nullptr);
> > +  std::vector<intptr_t> Offsets(Depth, 0);
> > +  if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(),
> Offsets.data(),
> > +                             MainExecutableName.c_str(), StrPool))
> > +    return false;
> > +  int InputFD;
> > +  SmallString<32> InputFile, OutputFile;
> > +  sys::fs::createTemporaryFile("symbolizer-input", "", InputFD,
> InputFile);
> > +  sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
> > +  FileRemover InputRemover(InputFile.c_str());
> > +  FileRemover OutputRemover(OutputFile.c_str());
> > +
> > +  {
> > +    raw_fd_ostream Input(InputFD, true);
> > +    for (int i = 0; i < Depth; i++) {
> > +      if (Modules[i])
> > +        Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
> > +    }
> > +  }
> > +
> > +  StringRef InputFileStr(InputFile);
> > +  StringRef OutputFileStr(OutputFile);
> > +  StringRef StderrFileStr;
> > +  const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr,
> > +                                  &StderrFileStr};
> > +  const char *Args[] = {"llvm-symbolizer", "--functions=linkage",
> "--inlining",
> > +#ifdef LLVM_ON_WIN32
> > +                        // Pass --relative-address on Windows so that
> we don't
> > +                        // have to add ImageBase from PE file.
> > +                        // FIXME: Make this the default for
> llvm-symbolizer.
> > +                        "--relative-address",
> > +#endif
> > +                        "--demangle", nullptr};
> > +  int RunResult =
> > +      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
> > +  if (RunResult != 0)
> > +    return false;
> > +
> > +  // This report format is based on the sanitizer stack trace printer.
> See
> > +  // sanitizer_stacktrace_printer.cc in compiler-rt.
> > +  auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
> > +  if (!OutputBuf)
> > +    return false;
> > +  StringRef Output = OutputBuf.get()->getBuffer();
> > +  SmallVector<StringRef, 32> Lines;
> > +  Output.split(Lines, "\n");
> > +  auto CurLine = Lines.begin();
> > +  int frame_no = 0;
> > +  for (int i = 0; i < Depth; i++) {
> > +    if (!Modules[i]) {
> > +      OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) <<
> '\n';
> > +      continue;
> > +    }
> > +    // Read pairs of lines (function name and file/line info) until we
> > +    // encounter empty line.
> > +    for (;;) {
> > +      if (CurLine == Lines.end())
> > +        return false;
> > +      StringRef FunctionName = *CurLine++;
> > +      if (FunctionName.empty())
> > +        break;
> > +      OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '
> ';
> > +      if (!FunctionName.startswith("??"))
> > +        OS << FunctionName << ' ';
> > +      if (CurLine == Lines.end())
> > +        return false;
> > +      StringRef FileLineInfo = *CurLine++;
> > +      if (!FileLineInfo.startswith("??"))
> > +        OS << FileLineInfo;
> > +      else
> > +        OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) <<
> ")";
> > +      OS << "\n";
> > +    }
> > +  }
> > +  return true;
> > +}
> > +
> > // Include the platform-specific parts of this class.
> > #ifdef LLVM_ON_UNIX
> > #include "Unix/Signals.inc"
> >
> > Modified: llvm/trunk/lib/Support/Unix/Signals.inc
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Signals.inc?rev=252118&r1=252117&r2=252118&view=diff
> >
> ==============================================================================
> > --- llvm/trunk/lib/Support/Unix/Signals.inc (original)
> > +++ llvm/trunk/lib/Support/Unix/Signals.inc Wed Nov  4 19:07:54 2015
> > @@ -291,7 +291,8 @@ static int dl_iterate_phdr_cb(dl_phdr_in
> >
> > static bool findModulesAndOffsets(void **StackTrace, int Depth,
> >                                   const char **Modules, intptr_t
> *Offsets,
> > -                                  const char *MainExecutableName) {
> > +                                  const char *MainExecutableName,
> > +                                  StringSaver &StrPool) {
> >   DlIteratePhdrData data = {StackTrace, Depth,   true,
> >                             Modules,    Offsets, MainExecutableName};
> >   dl_iterate_phdr(dl_iterate_phdr_cb, &data);
> > @@ -304,92 +305,6 @@ static bool findModulesAndOffsets(void *
> >   return false;
> > }
> > #endif
> > -
> > -static bool printSymbolizedStackTrace(void **StackTrace, int Depth,
> > -                                      llvm::raw_ostream &OS) {
> > -  // FIXME: Subtract necessary number from StackTrace entries to turn
> return addresses
> > -  // into actual instruction addresses.
> > -  // Use llvm-symbolizer tool to symbolize the stack traces.
> > -  ErrorOr<std::string> LLVMSymbolizerPathOrErr =
> > -      sys::findProgramByName("llvm-symbolizer");
> > -  if (!LLVMSymbolizerPathOrErr)
> > -    return false;
> > -  const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
> > -  // We don't know argv0 or the address of main() at this point, but try
> > -  // to guess it anyway (it's possible on some platforms).
> > -  std::string MainExecutableName = sys::fs::getMainExecutable(nullptr,
> nullptr);
> > -  if (MainExecutableName.empty() ||
> > -      MainExecutableName.find("llvm-symbolizer") != std::string::npos)
> > -    return false;
> > -
> > -  std::vector<const char *> Modules(Depth, nullptr);
> > -  std::vector<intptr_t> Offsets(Depth, 0);
> > -  if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(),
> Offsets.data(),
> > -                             MainExecutableName.c_str()))
> > -    return false;
> > -  int InputFD;
> > -  SmallString<32> InputFile, OutputFile;
> > -  sys::fs::createTemporaryFile("symbolizer-input", "", InputFD,
> InputFile);
> > -  sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
> > -  FileRemover InputRemover(InputFile.c_str());
> > -  FileRemover OutputRemover(OutputFile.c_str());
> > -
> > -  {
> > -    raw_fd_ostream Input(InputFD, true);
> > -    for (int i = 0; i < Depth; i++) {
> > -      if (Modules[i])
> > -        Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
> > -    }
> > -  }
> > -
> > -  StringRef InputFileStr(InputFile);
> > -  StringRef OutputFileStr(OutputFile);
> > -  StringRef StderrFileStr;
> > -  const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr,
> > -                                  &StderrFileStr};
> > -  const char *Args[] = {"llvm-symbolizer", "--functions=linkage",
> "--inlining",
> > -                        "--demangle", nullptr};
> > -  int RunResult =
> > -      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
> > -  if (RunResult != 0)
> > -    return false;
> > -
> > -  auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
> > -  if (!OutputBuf)
> > -    return false;
> > -  StringRef Output = OutputBuf.get()->getBuffer();
> > -  SmallVector<StringRef, 32> Lines;
> > -  Output.split(Lines, "\n");
> > -  auto CurLine = Lines.begin();
> > -  int frame_no = 0;
> > -  for (int i = 0; i < Depth; i++) {
> > -    if (!Modules[i]) {
> > -      OS << format("#%d %p\n", frame_no++, StackTrace[i]);
> > -      continue;
> > -    }
> > -    // Read pairs of lines (function name and file/line info) until we
> > -    // encounter empty line.
> > -    for (;;) {
> > -      if (CurLine == Lines.end())
> > -        return false;
> > -      StringRef FunctionName = *CurLine++;
> > -      if (FunctionName.empty())
> > -        break;
> > -      OS << format("#%d %p ", frame_no++, StackTrace[i]);
> > -      if (!FunctionName.startswith("??"))
> > -        OS << format("%s ", FunctionName.str().c_str());
> > -      if (CurLine == Lines.end())
> > -        return false;
> > -      StringRef FileLineInfo = *CurLine++;
> > -      if (!FileLineInfo.startswith("??"))
> > -        OS << format("%s", FileLineInfo.str().c_str());
> > -      else
> > -        OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]);
> > -      OS << "\n";
> > -    }
> > -  }
> > -  return true;
> > -}
> > #endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
> >
> > // PrintStackTrace - In the case of a program crash or fault, print out
> a stack
> >
> > Modified: llvm/trunk/lib/Support/Windows/Signals.inc
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Signals.inc?rev=252118&r1=252117&r2=252118&view=diff
> >
> ==============================================================================
> > --- llvm/trunk/lib/Support/Windows/Signals.inc (original)
> > +++ llvm/trunk/lib/Support/Windows/Signals.inc Wed Nov  4 19:07:54 2015
> > @@ -135,6 +135,10 @@ typedef BOOL (WINAPI *fpSymGetLineFromAd
> >                       PDWORD, PIMAGEHLP_LINE64);
> > static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
> >
> > +typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64
> dwAddr,
> > +                                           PIMAGEHLP_MODULE64
> ModuleInfo);
> > +static fpSymGetModuleInfo64 fSymGetModuleInfo64;
> > +
> > typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
> > static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
> >
> > @@ -144,6 +148,9 @@ static fpSymSetOptions fSymSetOptions;
> > typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
> > static fpSymInitialize fSymInitialize;
> >
> > +typedef BOOL (WINAPI
> *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
> > +static fpEnumerateLoadedModules fEnumerateLoadedModules;
> > +
> > static bool load64BitDebugHelp(void) {
> >   HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
> >   if (hLib) {
> > @@ -155,10 +162,14 @@ static bool load64BitDebugHelp(void) {
> >                       ::GetProcAddress(hLib, "SymGetSymFromAddr64");
> >     fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
> >                       ::GetProcAddress(hLib, "SymGetLineFromAddr64");
> > +    fSymGetModuleInfo64 = (fpSymGetModuleInfo64)
> > +                      ::GetProcAddress(hLib, "SymGetModuleInfo64");
> >     fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
> >                      ::GetProcAddress(hLib, "SymFunctionTableAccess64");
> >     fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib,
> "SymSetOptions");
> >     fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib,
> "SymInitialize");
> > +    fEnumerateLoadedModules = (fpEnumerateLoadedModules)
> > +      ::GetProcAddress(hLib, "EnumerateLoadedModules64");
> >   }
> >   return fStackWalk64 && fSymInitialize && fSymSetOptions;
> > }
> > @@ -183,23 +194,106 @@ static PTOP_LEVEL_EXCEPTION_FILTER OldFi
> > static CRITICAL_SECTION CriticalSection;
> > static bool CriticalSectionInitialized = false;
> >
> > -static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE
> hProcess,
> > -                                     HANDLE hThread, STACKFRAME64
> &StackFrame,
> > -                                     CONTEXT *Context) {
> > -  DWORD machineType;
> > +enum {
> > #if defined(_M_X64)
> > -  machineType = IMAGE_FILE_MACHINE_AMD64;
> > +  NativeMachineType = IMAGE_FILE_MACHINE_AMD64
> > #else
> > -  machineType = IMAGE_FILE_MACHINE_I386;
> > +  NativeMachineType = IMAGE_FILE_MACHINE_I386
> > #endif
> > +};
> > +
> > +static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
> > +                                              HANDLE hProcess, HANDLE
> hThread,
> > +                                              STACKFRAME64
> &StackFrameOrig,
> > +                                              CONTEXT *ContextOrig) {
> > +  // StackWalk64 modifies the incoming stack frame and context, so copy
> them.
> > +  STACKFRAME64 StackFrame = StackFrameOrig;
> > +
> > +  // Copy the register context so that we don't modify it while we
> unwind. We
> > +  // could use InitializeContext + CopyContext, but that's only
> required to get
> > +  // at AVX registers, which typically aren't needed by StackWalk64.
> Reduce the
> > +  // flag set to indicate that there's less data.
> > +  CONTEXT Context = *ContextOrig;
> > +  Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
> > +
> > +  static void *StackTrace[256];
> > +  int Depth = 0;
> > +  while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
> > +                      &Context, 0, fSymFunctionTableAccess64,
> > +                      fSymGetModuleBase64, 0)) {
> > +    if (StackFrame.AddrFrame.Offset == 0)
> > +      break;
> > +    StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
> > +    if (Depth >= array_lengthof(StackTrace))
> > +      break;
> > +  }
> >
> > +  return printSymbolizedStackTrace(&StackTrace[0], Depth, OS);
> > +}
> > +
> > +namespace {
> > +struct FindModuleData {
> > +  void **StackTrace;
> > +  int Depth;
> > +  const char **Modules;
> > +  intptr_t *Offsets;
> > +  StringSaver *StrPool;
> > +};
> > +}
> > +
> > +static BOOL CALLBACK findModuleCallback(WIN32_ELMCB_PCSTR ModuleName,
> > +                                        DWORD64 ModuleBase, ULONG
> ModuleSize,
> > +                                        void *VoidData) {
> > +  FindModuleData *Data = (FindModuleData*)VoidData;
> > +  intptr_t Beg = ModuleBase;
> > +  intptr_t End = Beg + ModuleSize;
> > +  for (int I = 0; I < Data->Depth; I++) {
> > +    if (Data->Modules[I])
> > +      continue;
> > +    intptr_t Addr = (intptr_t)Data->StackTrace[I];
> > +    if (Beg <= Addr && Addr < End) {
> > +      Data->Modules[I] = Data->StrPool->save(ModuleName);
> > +      Data->Offsets[I] = Addr - Beg;
> > +    }
> > +  }
> > +  return TRUE;
> > +}
> > +
> > +static bool findModulesAndOffsets(void **StackTrace, int Depth,
> > +                                  const char **Modules, intptr_t
> *Offsets,
> > +                                  const char *MainExecutableName,
> > +                                  StringSaver &StrPool) {
> > +  if (!fEnumerateLoadedModules)
> > +    return false;
> > +  FindModuleData Data;
> > +  Data.StackTrace = StackTrace;
> > +  Data.Depth = Depth;
> > +  Data.Modules = Modules;
> > +  Data.Offsets = Offsets;
> > +  Data.StrPool = &StrPool;
> > +  fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback,
> &Data);
> > +  return true;
> > +}
> > +
> > +static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE
> hProcess,
> > +                                     HANDLE hThread, STACKFRAME64
> &StackFrame,
> > +                                     CONTEXT *Context) {
> >   // Initialize the symbol handler.
> >   fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
> >   fSymInitialize(hProcess, NULL, TRUE);
> >
> > +  // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with
> both PDBs
> > +  // and DWARF, so it should do a good job regardless of what debug
> info or
> > +  // linker is in use.
> > +  if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread,
> StackFrame,
> > +                                        Context)) {
> > +    return;
> > +  }
> > +
> >   while (true) {
> > -    if (!fStackWalk64(machineType, hProcess, hThread, &StackFrame,
> Context, 0,
> > -                      fSymFunctionTableAccess64, fSymGetModuleBase64,
> 0)) {
> > +    if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
> > +                      Context, 0, fSymFunctionTableAccess64,
> > +                      fSymGetModuleBase64, 0)) {
> >       break;
> >     }
> >
> > @@ -404,7 +498,6 @@ extern "C" VOID WINAPI RtlCaptureContext
> > #endif
> >
> > void llvm::sys::PrintStackTrace(raw_ostream &OS) {
> > -
> >   STACKFRAME64 StackFrame = {};
> >   CONTEXT Context = {};
> >   ::RtlCaptureContext(&Context);
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151105/d17547b6/attachment.html>


More information about the llvm-commits mailing list