// during handling an actual signal because you can't safely call new in a
// signal handler.
*SignalsMutex;
-
+
// If the handlers are already registered, we're done.
if (NumRegisteredSignals != 0) return;
// memory.
std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) {
- // We rely on a std::string implementation for which repeated calls to
- // 'c_str()' don't allocate memory. We pre-call 'c_str()' on all of these
- // strings to try to ensure this is safe.
const char *path = FilesToRemoveRef[i].c_str();
// Get the status so we can determine if it's a file or directory. If we
// super-user permissions.
if (!S_ISREG(buf.st_mode))
continue;
-
+
// Otherwise, remove the file. We ignore any errors here as there is nothing
// else we can do.
unlink(path);
std::string* ErrMsg) {
{
sys::SmartScopedLock<true> Guard(*SignalsMutex);
- std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
- std::string *OldPtr =
- FilesToRemoveRef.empty() ? nullptr : &FilesToRemoveRef[0];
- FilesToRemoveRef.push_back(Filename);
-
- // We want to call 'c_str()' on every std::string in this vector so that if
- // the underlying implementation requires a re-allocation, it happens here
- // rather than inside of the signal handler. If we see the vector grow, we
- // have to call it on every entry. If it remains in place, we only need to
- // call it on the latest one.
- if (OldPtr == &FilesToRemoveRef[0])
- FilesToRemoveRef.back().c_str();
- else
- for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i)
- FilesToRemoveRef[i].c_str();
+ FilesToRemove->push_back(Filename);
}
RegisterHandlers();
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);
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