30 # include <execinfo.h>
45 #include <mach/mach.h>
53 static RETSIGTYPE SignalHandler(
int Sig);
58 static void (*InterruptFunction)() =
nullptr;
67 static const int IntSigs[] = {
68 SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
73 static const int KillSigs[] = {
74 SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
89 static unsigned NumRegisteredSignals = 0;
93 } RegisteredSignalInfo[(
sizeof(IntSigs)+
sizeof(KillSigs))/
sizeof(KillSigs[0])];
96 static void RegisterHandler(
int Signal) {
97 assert(NumRegisteredSignals <
98 sizeof(RegisteredSignalInfo)/
sizeof(RegisteredSignalInfo[0]) &&
99 "Out of space for signal handlers!");
101 struct sigaction NewHandler;
103 NewHandler.sa_handler = SignalHandler;
104 NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND;
105 sigemptyset(&NewHandler.sa_mask);
108 sigaction(Signal, &NewHandler,
109 &RegisteredSignalInfo[NumRegisteredSignals].SA);
110 RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal;
111 ++NumRegisteredSignals;
114 static void RegisterHandlers() {
122 if (NumRegisteredSignals != 0)
return;
124 for (
auto S : IntSigs) RegisterHandler(S);
125 for (
auto S : KillSigs) RegisterHandler(S);
128 static void UnregisterHandlers() {
130 for (
unsigned i = 0, e = NumRegisteredSignals; i != e; ++i)
131 sigaction(RegisteredSignalInfo[i].SigNo,
132 &RegisteredSignalInfo[i].SA,
nullptr);
133 NumRegisteredSignals = 0;
141 static void RemoveFilesToRemove() {
144 if (!FilesToRemove.isConstructed())
149 std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
150 for (
unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) {
154 const char *path = FilesToRemoveRef[i].c_str();
159 if (stat(path, &buf) != 0)
165 if (!S_ISREG(buf.st_mode))
175 static RETSIGTYPE SignalHandler(
int Sig) {
180 UnregisterHandlers();
184 sigfillset(&SigMask);
185 sigprocmask(SIG_UNBLOCK, &SigMask,
nullptr);
189 RemoveFilesToRemove();
193 if (InterruptFunction) {
194 void (*IF)() = InterruptFunction;
196 InterruptFunction =
nullptr;
208 if (CallBacksToRun.isConstructed()) {
209 auto &CallBacksToRunRef = *CallBacksToRun;
210 for (
unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
211 CallBacksToRunRef[i].first(CallBacksToRunRef[i].second);
219 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
226 RemoveFilesToRemove();
232 InterruptFunction = IF;
239 std::string* ErrMsg) {
242 std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
243 std::string *OldPtr =
244 FilesToRemoveRef.empty() ?
nullptr : &FilesToRemoveRef[0];
245 FilesToRemoveRef.push_back(Filename);
252 if (OldPtr == &FilesToRemoveRef[0])
253 FilesToRemoveRef.back().c_str();
255 for (
unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i)
256 FilesToRemoveRef[i].
c_str();
266 std::vector<std::string>::reverse_iterator RI =
267 std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
268 std::vector<std::string>::iterator
I = FilesToRemove->end();
269 if (RI != FilesToRemove->rend())
270 I = FilesToRemove->erase(RI.base()-1);
276 for (std::vector<std::string>::iterator E = FilesToRemove->end(); I != E; ++
I)
284 CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
288 #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
290 #if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \
291 defined(__FreeBSD_kernel__) || defined(__NetBSD__))
292 struct DlIteratePhdrData {
296 const char **modules;
298 const char *main_exec_name;
301 static int dl_iterate_phdr_cb(dl_phdr_info *
info,
size_t size,
void *arg) {
302 DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
303 const char *
name = data->first ? data->main_exec_name : info->dlpi_name;
305 for (
int i = 0; i < info->dlpi_phnum; i++) {
306 const auto *phdr = &info->dlpi_phdr[i];
309 intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
311 for (
int j = 0; j < data->depth; j++) {
312 if (data->modules[j])
315 if (beg <= addr && addr < end) {
316 data->modules[j] =
name;
317 data->offsets[j] = addr - info->dlpi_addr;
324 static bool findModulesAndOffsets(
void **StackTrace,
int Depth,
326 const char *MainExecutableName) {
327 DlIteratePhdrData data = {StackTrace, Depth,
true,
328 Modules,
Offsets, MainExecutableName};
329 dl_iterate_phdr(dl_iterate_phdr_cb, &data);
333 static bool findModulesAndOffsets(
void **StackTrace,
int Depth,
335 const char *MainExecutableName) {
340 static bool printSymbolizedStackTrace(
void **StackTrace,
int Depth,
347 if (!LLVMSymbolizerPathOrErr)
349 const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
353 if (MainExecutableName.empty() ||
354 MainExecutableName.find(
"llvm-symbolizer") != std::string::npos)
357 std::vector<const char *> Modules(Depth,
nullptr);
358 std::vector<intptr_t>
Offsets(Depth, 0);
359 if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(),
Offsets.data(),
360 MainExecutableName.c_str()))
371 for (
int i = 0; i < Depth; i++) {
373 Input << Modules[i] <<
" " << (
void*)
Offsets[i] <<
"\n";
380 const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr,
382 const char *Args[] = {
"llvm-symbolizer",
"--functions=linkage",
"--inlining",
383 "--demangle",
nullptr};
392 StringRef Output = OutputBuf.get()->getBuffer();
394 Output.
split(Lines,
"\n");
395 auto CurLine = Lines.
begin();
397 for (
int i = 0; i < Depth; i++) {
399 OS <<
format(
"#%d %p\n", frame_no++, StackTrace[i]);
405 if (CurLine == Lines.
end())
408 if (FunctionName.
empty())
410 OS <<
format(
"#%d %p ", frame_no++, StackTrace[i]);
412 OS <<
format(
"%s ", FunctionName.
str().c_str());
413 if (CurLine == Lines.
end())
417 OS <<
format(
"%s", FileLineInfo.
str().c_str());
425 #endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
433 #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
434 static void* StackTrace[256];
436 int depth = backtrace(StackTrace,
438 if (printSymbolizedStackTrace(StackTrace, depth, OS))
440 #if HAVE_DLFCN_H && __GNUG__
442 for (
int i = 0; i < depth; ++i) {
444 dladdr(StackTrace[i], &dlinfo);
445 const char* name = strrchr(dlinfo.dli_fname,
'/');
448 if (!name) nwidth = strlen(dlinfo.dli_fname);
449 else nwidth = strlen(name) - 1;
451 if (nwidth > width) width = nwidth;
454 for (
int i = 0; i < depth; ++i) {
456 dladdr(StackTrace[i], &dlinfo);
460 const char* name = strrchr(dlinfo.dli_fname,
'/');
461 if (!name) OS <<
format(
" %-*s", width, dlinfo.dli_fname);
462 else OS <<
format(
" %-*s", width, name+1);
464 OS <<
format(
" %#0*lx", (
int)(
sizeof(
void*) * 2) + 2,
465 (
unsigned long)StackTrace[i]);
467 if (dlinfo.dli_sname !=
nullptr) {
471 char* d = abi::__cxa_demangle(dlinfo.dli_sname,
nullptr,
nullptr, &res);
475 if (!d) OS << dlinfo.dli_sname;
482 OS <<
format(
" + %u",(
unsigned)((
char*)StackTrace[i]-
483 (
char*)dlinfo.dli_saddr));
488 backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
493 static void PrintStackTraceSignalHandler(
void *) {
504 #if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES)
506 if (DisableCrashReporting || getenv(
"LLVM_DISABLE_CRASH_REPORT")) {
507 mach_port_t
self = mach_task_self();
509 exception_mask_t mask = EXC_MASK_CRASH;
511 kern_return_t ret = task_set_exception_ports(
self,
514 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
530 #if defined(__APPLE__) && defined(ENABLE_CRASH_OVERRIDES)
536 return pthread_kill(pthread_self(), sig);
539 void __assert_rtn(
const char *func,
544 fprintf(stderr,
"Assertion failed: (%s), function %s, file %s, line %d.\n",
545 expr, func, file, line);
547 fprintf(stderr,
"Assertion failed: (%s), file %s, line %d.\n",
const_iterator end(StringRef path)
Get end iterator over path.
void PrintStackTraceOnErrorSignal(bool DisableCrashReporting=false)
When an error signal (such as SIBABRT or SIGSEGV) is delivered to the process, print a stack trace an...
Represents either an error or a value T.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
std::string str() const
str - Get the contents as an std::string.
void DisableSystemDialogsOnCrash()
Disable all system dialog boxes that appear when the process crashes.
const_iterator begin(StringRef path)
Get begin iterator over path.
FileRemover - This class is a simple object meant to be stack allocated.
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths=ArrayRef< StringRef >())
Find the first executable file Name in Paths.
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If Reload the main corpus periodically to get new units discovered by other processes Read the given input file
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
int ExecuteAndWait(StringRef Program, const char **args, const char **env=nullptr, const StringRef **redirects=nullptr, unsigned secondsToWait=0, unsigned memoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr)
This function executes the program using the arguments provided.
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
LLVM_CONSTEXPR size_t array_lengthof(T(&)[N])
Find the length of an array.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void PrintStackTrace(raw_ostream &OS)
Print the stack trace using the given raw_ostream object.
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
A pared-down imitation of std::unique_lock from C++11.
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
A raw_ostream that writes to a file descriptor.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
void SetInterruptFunction(void(*IF)())
This function registers a function to be called when the user "interrupts" the program (typically by ...
void AddSignalHandler(void(*FnPtr)(void *), void *Cookie)
AddSignalHandler - Add a function to be called when an abort/kill signal is delivered to the process...
bool empty() const
empty - Check if the string is empty.