[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