//----------------------------------------------------------------------------//
static void dumpBacktrace(size_t frames)
{

#if defined(__ANDROID__)

    // Not implemented yet.
    CEGUI_UNUSED(frames);

#else

#if defined(_DEBUG) || defined(DEBUG)
#if defined(_MSC_VER)
    SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES);

    if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
        return;

    HANDLE thread = GetCurrentThread();

    CONTEXT context;
    RtlCaptureContext(&context);

    STACKFRAME64 stackframe;
    ZeroMemory(&stackframe, sizeof(stackframe));
    stackframe.AddrPC.Mode = AddrModeFlat;
    stackframe.AddrStack.Mode = AddrModeFlat;
    stackframe.AddrFrame.Mode = AddrModeFlat;

#if _M_IX86
    stackframe.AddrPC.Offset = context.Eip;
    stackframe.AddrStack.Offset = context.Esp;
    stackframe.AddrFrame.Offset = context.Ebp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_I386;
#elif _M_X64
    stackframe.AddrPC.Offset = context.Rip;
    stackframe.AddrStack.Offset = context.Rsp;
    stackframe.AddrFrame.Offset = context.Rbp;
    DWORD machine_arch = IMAGE_FILE_MACHINE_AMD64;
#endif

    char symbol_buffer[1024];
    ZeroMemory(symbol_buffer, sizeof(symbol_buffer));
    PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(symbol_buffer);
    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = sizeof(symbol_buffer) - sizeof(SYMBOL_INFO);

    Logger& logger(Logger::getSingleton());
    logger.logEvent("========== Start of Backtrace ==========", Errors);

    size_t frame_no = 0;
    while (StackWalk64(machine_arch, GetCurrentProcess(), thread, &stackframe,
                       &context, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0) &&
           stackframe.AddrPC.Offset)
    {
        symbol->Address = stackframe.AddrPC.Offset;
        DWORD64 displacement = 0;
        char signature[256];

        if (SymFromAddr(GetCurrentProcess(), symbol->Address, &displacement, symbol))
            UnDecorateSymbolName(symbol->Name, signature, sizeof(signature), UNDNAME_COMPLETE);
        else
            sprintf_s(signature, sizeof(signature), "%p", ULongToPtr(symbol->Address));
 
        IMAGEHLP_MODULE64 modinfo;
        modinfo.SizeOfStruct = sizeof(modinfo);

        const BOOL have_image_name =
            SymGetModuleInfo64(GetCurrentProcess(), symbol->Address, &modinfo);

        char outstr[512];
        sprintf_s(outstr, sizeof(outstr), "#%d %s +%#llx (%s)",
                  frame_no, signature, displacement,
                  (have_image_name ? modinfo.LoadedImageName : "????"));

        logger.logEvent(outstr, Errors);

        if (++frame_no >= frames)
            break;

        if (!stackframe.AddrReturn.Offset)
            break;
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);

    SymCleanup(GetCurrentProcess());
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
    void* buffer[frames];
    const int received = backtrace(&buffer[0], frames);

    Logger& logger(Logger::getSingleton());

    logger.logEvent("========== Start of Backtrace ==========", Errors);

    for (int i = 0; i < received; ++i)
    {
        char outstr[512];
        Dl_info info;
        if (dladdr(buffer[i], &info))
        {
            if (!info.dli_sname)
                snprintf(outstr, 512, "#%d %p (%s)", i, buffer[i], info.dli_fname);
            else
            {
                ptrdiff_t offset = static_cast<char*>(buffer[i]) -
                                   static_cast<char*>(info.dli_saddr);

                int demangle_result = 0;
                char* demangle_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &demangle_result);
                snprintf(outstr, 512, "#%d %s +%#tx (%s)",
                         i, demangle_name ? demangle_name : info.dli_sname, offset, info.dli_fname);
                std::free(demangle_name);
            }
        }
        else
            snprintf(outstr, 512, "#%d --- error ---", i);

        logger.logEvent(outstr, Errors);
    }

    logger.logEvent("==========  End of Backtrace  ==========", Errors);

#else

    CEGUI_UNUSED(frames);
    
#endif

#else

    CEGUI_UNUSED(frames);

#endif

#endif
}
示例#2
0
文件: pex.cpp 项目: ashang/pepper
// Returns a formatted stack trace (with g++ only). Note that it should _not_ throw an exception!
// Credits go out to Timo Bingmann (http://idlebox.net/2008/0901-stacktrace-demangled/)
std::string PepperException::stackTrace()
{
#if defined(__GLIBC__) || defined(POS_DARWIN)
try {
	std::string str = "Stack trace:\n";

	// storage array for stack trace address data
	void* addrlist[60+1];
	// retrieve current stack addresses
	int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

	if (addrlen == 0) {
		str += "    <empty, possibly corrupt>\n";
		return str;
	}

	// resolve addresses into strings containing "filename(function+address)",
	// this array must be free()-ed
	char** symbollist = backtrace_symbols(addrlist, addrlen);

	// allocate string which will be filled with the demangled function name
	size_t funcnamesize = 256;
	char *funcname = new char[funcnamesize];

	// iterate over the returned symbol lines. skip the first, it is the
	// address of this function.
	for (int i = 1; i < addrlen; i++)
	{
		char *begin_name = 0, *begin_offset = 0, *end_offset = 0;

		// find parentheses and +address offset surrounding the mangled name:
		// ./module(function+0x15c) [0x8048a6d]
		for (char *p = symbollist[i]; *p; ++p)
		{
			if (*p == '(')
				begin_name = p;
			else if (*p == '+')
				begin_offset = p;
			else if (*p == ')' && begin_offset) {
				end_offset = p;
				break;
			}
		}

		if (begin_name && begin_offset && end_offset && begin_name < begin_offset)
		{
			*begin_name++ = '\0';
			*begin_offset++ = '\0';
			*end_offset = '\0';

			// mangled name is now in [begin_name, begin_offset) and caller
			// offset in [begin_offset, end_offset). now apply
			// __cxa_demangle():

			int status;
			char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
			if (status == 0) {
				funcname = ret; // use possibly realloc()-ed string
				str += "    ";
				str += std::string(symbollist[i])+": "+(const char *)funcname+"+"+(const char *)begin_offset;
			}
			else {
				// demangling failed. Output function name as a C function with
				// no arguments.
				str += "    ";
				str += std::string(symbollist[i])+": "+(const char *)begin_name+"()+"+(const char *)begin_offset;
			}
		}
		else
		{
			// couldn't parse the line? print the whole line.
			str += std::string("    ")+(const char *)symbollist[i];
		}
		str += '\n';
	}

	delete[] funcname;
	free(symbollist);
	return str;
} catch (...) {
	return std::string();
}
#else
	return std::string();
#endif
}
示例#3
0
// return 1: break (should stop being feed with debugger commands), 0: continue (can be feed with other debugger commands)
static int process_debug_cmd(char *cmdline) {
    char *cmd = strtok(cmdline, " \n\r");
    if (!cmd)
        return 0;

    if (!strcasecmp(cmd, "?") || !strcasecmp(cmd, "h")) {
        gui_debug_printf(
                    "Debugger commands:\n"
                    "b - stack backtrace\n"
                    "c - continue\n"
                    "d <address> - dump memory\n"
                    "k <address> <+r|+w|+x|-r|-w|-x> - add/remove breakpoint\n"
                    "k - show breakpoints\n"
                    "ln c - connect\n"
                    "ln s <file> - send a file\n"
                    "ln st <dir> - set target directory\n"
                    "mmu - dump memory mappings\n"
                    "n - continue until next instruction\n"
                    "pr <address> - port or memory read\n"
                    "pw <address> <value> - port or memory write\n"
                    "q - quit\n"
                    "r - show registers\n"
                    "rs <regnum> <value> - change register value\n"
                    "ss <address> <length> <string> - search a string\n"
                    "s - step instruction\n"
                    "t+ - enable instruction translation\n"
                    "t- - disable instruction translation\n"
                    "u[a|t] [address] - disassemble memory\n"
                    "wm <file> <start> <size> - write memory to file\n"
                    "wf <file> <start> [size] - write file to memory\n"
                    "exec <path> - exec file with ndless\n");
    } else if (!strcasecmp(cmd, "b")) {
        char *fp = strtok(NULL, " \n\r");
        backtrace(fp ? parse_expr(fp) : arm.reg[11]);
    } else if (!strcasecmp(cmd, "mmu")) {
        mmu_dump_tables();
    } else if (!strcasecmp(cmd, "r")) {
        int i, show_spsr;
        uint32_t cpsr = get_cpsr();
        const char *mode;
        for (i = 0; i < 16; i++) {
            int newline = ((1 << 5) | (1 << 11) | (1 << 15)) & (1 << i);
            gui_debug_printf("%3s=%08x%c", reg_name[i], arm.reg[i], newline ? '\n' : ' ');
        }
        switch (cpsr & 0x1F) {
            case MODE_USR: mode = "usr"; show_spsr = 0; break;
            case MODE_SYS: mode = "sys"; show_spsr = 0; break;
            case MODE_FIQ: mode = "fiq"; show_spsr = 1; break;
            case MODE_IRQ: mode = "irq"; show_spsr = 1; break;
            case MODE_SVC: mode = "svc"; show_spsr = 1; break;
            case MODE_ABT: mode = "abt"; show_spsr = 1; break;
            case MODE_UND: mode = "und"; show_spsr = 1; break;
            default:       mode = "???"; show_spsr = 0; break;
        }
        gui_debug_printf("cpsr=%08x (N=%d Z=%d C=%d V=%d Q=%d IRQ=%s FIQ=%s T=%d Mode=%s)",
                         cpsr,
                         arm.cpsr_n, arm.cpsr_z, arm.cpsr_c, arm.cpsr_v,
                         cpsr >> 27 & 1,
                         (cpsr & 0x80) ? "off" : "on ",
                         (cpsr & 0x40) ? "off" : "on ",
                         cpsr >> 5 & 1,
                         mode);
        if (show_spsr)
            gui_debug_printf(" spsr=%08x", get_spsr());
        gui_debug_printf("\n");
    } else if (!strcasecmp(cmd, "rs")) {
示例#4
0
void *utlMem_alloc(UINT32 size, UINT32 allocFlags)
{
    void *buf;
    UINT32 allocSize;

#ifdef UTL_MEM_LEAK_TRACING
    initAllocSeq();
#endif

    allocSize = REAL_ALLOC_SIZE(size);

    buf = osl_malloc(allocSize);
    if (buf)
    {
        mStats.bytesAllocd += size;
        mStats.numAllocs++;
    }


    if (buf != NULL)
    {
        UINTPTR *intBuf = (UINTPTR *) buf;
#ifdef UTL_MEM_DEBUG
        UINT32 intSize = allocSize / sizeof(UINTPTR);
#endif


        if (allocFlags & ALLOC_ZEROIZE)
        {
            memset(buf, 0, allocSize);
        }
#ifdef UTL_MEM_POISON_ALLOC_FREE
        else
        {
            /*
             * Set alloc'ed buffer to garbage to catch use-before-init.
             * But we also allocate huge buffers for storing image downloads.
             * Don't bother writing garbage to those huge buffers.
             */
            if (allocSize < 64 * 1024)
            {
                memset(buf, UTL_MEM_ALLOC_PATTERN, allocSize);
            }
        }
#endif

        /*
         * Record the allocFlags in the first word, and the 
         * size of user buffer in the next 2 words of the buffer.
         * Make 2 copies of the size in case one of the copies gets corrupted by
         * an underflow.  Make one copy the XOR of the other so that there are
         * not so many 0's in size fields.
         */
        intBuf[0] = allocFlags;
        intBuf[1] = size;
        intBuf[2] = intBuf[1] ^ UTL_MEM_HEADER_MASK;

        buf = &(intBuf[3]); /* this gets returned to user */

#ifdef UTL_MEM_DEBUG
        {
            UINT8 *charBuf = (UINT8 *) buf;
            UINT32 i, roundupSize = ROUNDUP(size);

            for (i=size; i < roundupSize; i++)
            {
                charBuf[i] = UTL_MEM_FOOTER_PATTERN & 0xff;
            }

            intBuf[intSize - 1] = UTL_MEM_FOOTER_PATTERN;
            intBuf[intSize - 2] = UTL_MEM_FOOTER_PATTERN;
        }
#endif

#ifdef UTL_MEM_LEAK_TRACING
        {
            AllocRecord *allocRec;
            if (!(allocRec = calloc(1, sizeof(AllocRecord))))
            {
                utlLog_error("could not malloc a record to track alloc");
            }
            else
            {
                allocRec->bufAddr = buf;
                allocRec->userSize = size;
                allocRec->seq = allocSeq++;
                backtrace(allocRec->stackAddr, NUM_STACK_ENTRIES);
                /*
                 * new allocs are placed at the beginning of the list, right after
                 * the head.
                 */
                dlist_append((struct dlist_node *)allocRec, &glbAllocRec);
            }

            /*
             * do periodic garbage collection on the allocRecs which point
             * to shmBuf's that has been freed by another app.
             */
            if ((allocSeq % 2000) == 0)
            {
                utlLog_debug("Starting allocRec garbage collection");
                garbageCollectAllocRec();
                utlLog_debug("garbage collection done");
            }
        }
#endif
    }
    return buf;
}
示例#5
0
/* This function is called when a segmentation fault is caught.  The system
   is in an unstable state now.  This means especially that malloc() might
   not work anymore.  */
static void
catch_segfault (int signal, SIGCONTEXT ctx)
{
  int fd, cnt, i;
  void **arr;
  struct sigaction sa;
  uintptr_t pc;

  /* This is the name of the file we are writing to.  If none is given
     or we cannot write to this file write to stderr.  */
  fd = 2;
  if (fname != NULL)
    {
      fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666);
      if (fd == -1)
	fd = 2;
    }

  WRITE_STRING ("*** ");
  write_strsignal (fd, signal);
  WRITE_STRING ("\n");

#ifdef REGISTER_DUMP
  REGISTER_DUMP;
#endif

  WRITE_STRING ("\nBacktrace:\n");

  /* Get the backtrace.  */
  arr = alloca (256 * sizeof (void *));
  cnt = backtrace (arr, 256);

  /* Now try to locate the PC from signal context in the backtrace.
     Normally it will be found at arr[2], but it might appear later
     if there were some signal handler wrappers.  Allow a few bytes
     difference to cope with as many arches as possible.  */
  pc = (uintptr_t) GET_PC (ctx);
  for (i = 0; i < cnt; ++i)
    if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
      break;

  /* If we haven't found it, better dump full backtrace even including
     the signal handler frames instead of not dumping anything.  */
  if (i == cnt)
    i = 0;

  /* Now generate nicely formatted output.  */
  __backtrace_symbols_fd (arr + i, cnt - i, fd);

#ifdef HAVE_PROC_SELF
  /* Now the link map.  */
  int mapfd = open ("/proc/self/maps", O_RDONLY);
  if (mapfd != -1)
    {
      write (fd, "\nMemory map:\n\n", 14);

      char buf[256];
      ssize_t n;

      while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0)
	TEMP_FAILURE_RETRY (write (fd, buf, n));

      close (mapfd);
    }
#endif

  /* Pass on the signal (so that a core file is produced).  */
  sa.sa_handler = SIG_DFL;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction (signal, &sa, NULL);
  raise (signal);
}
示例#6
0
void CExceptionHandler::WriteExceptionReport()
#endif
{
	// Get the current time and date
	time_t t = time(NULL);
	const struct tm * tm = localtime(&t);

	// Get the 'crashinfo' directory path
	String strPath(SharedUtility::GetAbsolutePath("crashinfo"));

	// Create the 'crashinfo' directory if needed
	if(!SharedUtility::Exists(strPath))
		SharedUtility::CreateDirectory(strPath);

	// Append the client or server string to the path
#ifdef _SERVER
	strPath.Append("/Server");
#else
	strPath.Append("/Client");
#endif

	// Append the operating system string to the path
	strPath.Append("-" OS_STRING);

	// Append the version, date and time to the path
	strPath.AppendF("-" MOD_VERSION_STRING "-%04d.%02d.%02d-%02d.%02d.%02d", (tm->tm_year + 1900), (tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

	// Get the log file path
	String strLogPath("%s.log", strPath.Get());

	// Open the log file
	FILE * fFile = fopen(strLogPath, "w");
	CLogFile::Printf(strLogPath);
	String reportData;

	// Did the log file open successfully?
	if(fFile)
	{
		// Write the unhandled exception report start notice to the log file
		fprintf(fFile, "-- Unhandled Exception Report Start --\n");

#ifdef WIN32
		// Write the exception code and exception code string to the log file
		fprintf(fFile, "Exception code: 0x%p (%s)\n", ExceptionInfo->ExceptionRecord->ExceptionCode, 
			ExceptionCodeToString(ExceptionInfo->ExceptionRecord->ExceptionCode));

		// Write the exception address to the log file
#ifndef _SERVER
		fprintf(fFile, "Exception address: 0x%p (0x%p)\n", ExceptionInfo->ExceptionRecord->ExceptionAddress, CGame::GetBase());
		fprintf(fFile, "Exception real-add: 0x%p / 0x%p\n", ((int)ExceptionInfo->ExceptionRecord->ExceptionAddress-CGame::GetBase()), (CGame::GetBase()-(int)ExceptionInfo->ExceptionRecord->ExceptionAddress));
#else
		fprintf(fFile, "Exception address: 0x%p\n", ExceptionInfo->ExceptionRecord->ExceptionAddress);
#endif
		// Create a tool help 32 process snapshot
		HANDLE hModuleSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());

		if(hModuleSnapShot)
		{
			MODULEENTRY32 ModuleEntry;
			ModuleEntry.dwSize = sizeof(ModuleEntry);

			if(Module32First(hModuleSnapShot, &ModuleEntry))
			{
				// Enumerate through all modules
				while(Module32Next(hModuleSnapShot, &ModuleEntry))
				{
					// See if exception was within this module
					if((ExceptionInfo->ContextRecord->Eip >= (DWORD)ModuleEntry.modBaseAddr) && (ExceptionInfo->ContextRecord->Eip <= ((DWORD)ModuleEntry.modBaseAddr + ModuleEntry.modBaseSize)))
					{
						fprintf(fFile, "Exception module: %s (+0x%p)\n", ModuleEntry.szModule, (ExceptionInfo->ContextRecord->Eip - (DWORD)ModuleEntry.modBaseAddr));
						break;
					}
				}
			}
		}
		fprintf(fFile, "--Unhandled Exception Report End --\n");

		fclose(fFile);
		// Print a message in the log file
		CLogFile::Printf("IV:MP has crashed. Please see %s for more information.", strLogPath.Get());


		FILE * pFile;

		pFile = fopen (strLogPath, "r");
		if (pFile != NULL)
		{
			fseek(pFile ,0 , SEEK_END);
			int lSize = ftell (pFile);
			char* buffer = (char*) malloc (sizeof(char)*lSize);
			if (buffer == NULL) {
				fclose(pFile);
			} else {
				fseek(pFile, 0, SEEK_SET);
				size_t result = fread (buffer, 1, lSize, pFile);
				reportData = buffer;
				fclose(pFile);
			}
		}

#ifdef WIN32
		WinExec((SharedUtility::GetAbsolutePath("crashreporter.exe ") + reportData).Get(), SW_SHOW);
		return;
#endif

		// Write the registers segment header
		fprintf(fFile, "Exception registers: \n");

		// If we have segments context information then write it to the log file
		if(ExceptionInfo->ContextRecord->ContextFlags & CONTEXT_SEGMENTS)
		{
			fprintf(fFile, "GS=0x%p FS=0x%p ES=0x%p DS=0x%p\n", ExceptionInfo->ContextRecord->SegGs, 
				ExceptionInfo->ContextRecord->SegFs, ExceptionInfo->ContextRecord->SegEs, 
				ExceptionInfo->ContextRecord->SegDs);
		}

		// If we have integer context information then write it to the log file
		if(ExceptionInfo->ContextRecord->ContextFlags & CONTEXT_INTEGER)
		{
			fprintf(fFile, "EDI=0x%p ESI=0x%p EBX=0x%p EDX=0x%p\n", ExceptionInfo->ContextRecord->Edi, 
				ExceptionInfo->ContextRecord->Esi, ExceptionInfo->ContextRecord->Ebx,
				ExceptionInfo->ContextRecord->Edx);
			fprintf(fFile, "ECX=0x%p EAX=0x%p\n", ExceptionInfo->ContextRecord->Ecx, 
				ExceptionInfo->ContextRecord->Eax);
		}

		// If we have control context information then write it to the log file
		if(ExceptionInfo->ContextRecord->ContextFlags & CONTEXT_CONTROL)
		{
			fprintf(fFile, "EBP=0x%p EIP=0x%p CS=0x%p EFLAGS=0x%p\n", ExceptionInfo->ContextRecord->Ebp, 
				ExceptionInfo->ContextRecord->Eip, ExceptionInfo->ContextRecord->SegCs, 
				ExceptionInfo->ContextRecord->EFlags);
			fprintf(fFile, "ESP=0x%p SS=0x%p\n", ExceptionInfo->ContextRecord->Esp, 
				ExceptionInfo->ContextRecord->SegSs);
		}
#else
		void * pArray[50];
		int size = backtrace(pArray, 50);
		char ** szMessages = backtrace_symbols(pArray, size);

		for(int i = 0; i < size && szMessages != NULL; i++)
			fprintf(fFile, "[Backtrace %d]: %s\n", szMessages[i]);
#endif

		// If we have a callback call it
		if(m_pfnCallback)
			m_pfnCallback(fFile);

		// Write the unhandled exception report end notice to the log file
		fprintf(fFile, "--Unhandled Exception Report End --\n");
		
#ifndef _SERVER
#ifdef _CLIENT_LOG_REPORT
		fprintf(fFile, "\n\n------------------------- Client Log -------------------------\n\n\n");
		FILE * pFile;
		String strClientLogOrgPath("%sClient.log",SharedUtility::GetAppPath());

		pFile = fopen (strClientLogOrgPath.Get(), "r");
		if (pFile != NULL)
		{
			fseek(pFile ,0 , SEEK_END);
			int lSize = ftell (pFile);
			char* buffer = (char*) malloc (sizeof(char)*lSize);
			if (buffer == NULL) {
				fclose(pFile);
			} else {
				fseek(pFile, 0, SEEK_SET);
				size_t result = fread (buffer, 1, lSize, pFile);

				fprintf(fFile, "%s\n\n", buffer);
				fprintf(fFile, "---------------------- Client Log End -----------------------\n");
				fclose(pFile);
			}
		}
#endif
#endif
	}

	// Close the log file
	fclose(fFile);

#ifdef WIN32
	// Get the minidump file path
	String strMiniDumpPath("%s.dmp", strPath.Get());

	// Open the minidump file
	HANDLE hFile = CreateFileA(strMiniDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL , NULL);

	// Did the minidump file open successfully?
	if(hFile)
	{
		// Create the minidump exception information
		MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
		exceptionInfo.ThreadId = GetCurrentThreadId();
		exceptionInfo.ExceptionPointers = ExceptionInfo;
		exceptionInfo.ClientPointers = FALSE;

		// Write the minidump to the minidump file
		bool bWritten = (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &exceptionInfo, NULL, NULL) != 0);

		// Close the minidump file
		CloseHandle(hFile);
	}
#endif

	// Print a message in the log file
	CLogFile::Printf("IV:MP has crashed. Please see %s for more information.", strLogPath.Get());

#ifdef WIN32
	CreateProcess(SharedUtility::GetAbsolutePath("crashreporter.exe"), (LPSTR)strPath.Get(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
#endif
}
// CmpErrLog::writeQueryInfo() writes the stack trace of the 
// compiler to the log file.
void CmpErrLog::writeStackTrace()
{
  fprintf(fp, "Process Stack Trace:\n");


  // This is a quick and dirty implementation for Linux. It is easy to
  // get the program counters for the stack trace, but is difficult to
  // look up the function name, line, and file number based off of the
  // program counter. For simplicity, this code just calls addr2line to
  // look up the information. This could be changed in the future if an
  // easy to use API becomes available.
  void *bt[20];
  size_t size = backtrace(bt, 20);

  pid_t myPID = getpid();

  // Write each level of the stack except for the top frame and the
  // bottom two frames, which aren't important here.
  Int32 i = 1;
  while (i < size - 2)
  {
    char buffer[128];  // Used for command-line + addr2line output.

    sprintf(buffer, "/usr/bin/addr2line -e /proc/%d/exe -f -C ", myPID);

    Int32 j;

    // Run addr2line on 5 addresses at a time.
    for (j = i; j < i+5 && j < size-2; j++)
    {
      char addrBuf[12];
      sprintf(addrBuf, " %p", bt[j]);
      strcat(buffer, addrBuf);
    }

    FILE *cmdFP = popen(buffer, "r");
    if (cmdFP == NULL)
    {
      fprintf(fp, "Error %d while popen() of %s\n", errno, buffer);
      break;
    }
    else
    {
      for (j = i; j < i+5 && j < size-2; j++)
      {
        // Read from the addr2line output
        fgets(buffer, sizeof(buffer), cmdFP);

        // Replace newline with null character
        size_t len = strlen(buffer);
        if (buffer[len-1] == '\n')
          buffer[len-1] = '\0';

        fprintf(fp, "%p: %s()\n", bt[j], buffer); 
        fgets(buffer, sizeof(buffer), cmdFP);
        fprintf(fp, "            %s", buffer); 
      }
      fclose(cmdFP);
    }
    i = j;
  }
  fputc('\n', fp);
}
示例#8
0
int write_log(log_type_t log_type, char *message) {
    if (created_logger == NULL) {
        perror("Logger is not initialized! There is not possible to write a message!\n");
        return -1;
    }

    if (message == NULL) {
        errno = EINVAL;
        perror("It is impossible to set file! Input message is wrong!\n");
        return -2;
    }

    if (log_type > Fatal) {
        perror("Log level is wrong!\n");
        return -3;
    }

    if (log_type < Debug) {
        return -4;
    }

    if (log_type == Fatal) {
        int i = 0;
        if(created_logger -> buffer -> num_of_circules == 0) {
            for (i = 0; i < created_logger -> buffer -> position_of_last_empty; i++) {
                fputs(created_logger -> buffer -> buffer[i], created_logger -> file_pointer);
                free(created_logger -> buffer -> buffer[i]);
                created_logger -> buffer -> buffer[i] = NULL;

            }
        } else {
            for (i = 0; i < BUFFER_SIZE; i++) {
                fputs(created_logger -> buffer -> buffer[i], created_logger -> file_pointer);
                free(created_logger -> buffer -> buffer[i]);
                created_logger -> buffer -> buffer[i] = NULL;
            }
        }
        int nptrs = backtrace(buffer_for_stack, SIZE);
        char **stack_interior;
        stack_interior = backtrace_symbols(buffer_for_stack, SIZE);
        for(i = 0; i < nptrs; i++) {
            printf("%s\n",stack_interior[i]);
        }
        logger_deinit();
        return -5;
    }

    if(log_type < Fatal) {
        if(created_logger -> buffer -> position_of_last_empty == BUFFER_SIZE) {
            created_logger -> buffer -> position_of_last_empty = 0;
            created_logger -> buffer -> num_of_circules += 1;
        }
        if(created_logger -> buffer -> num_of_circules != 0) {
            free(created_logger -> buffer -> buffer[created_logger -> buffer-> position_of_last_empty]);
            created_logger -> buffer -> buffer[created_logger -> buffer-> position_of_last_empty] = NULL;
        }
        created_logger -> buffer -> buffer[created_logger -> buffer-> position_of_last_empty] = formulate_message(log_type, message);
        created_logger -> buffer -> position_of_last_empty +=1;
        return 0;
    }
}
示例#9
0
void mybacktrace(void)
{
	ENTRY();

	void   *pointers[16];

	size_t	count;

	char  **functions;

	count = backtrace(pointers, 16);

	functions = backtrace_symbols(pointers, count);

	size_t	i;

	for(i = 1; i < count; ++i)
	{
		size_t	sz = 200;

		char   *function = static_cast<char *>(malloc(sz));
		char   *begin = 0;
		char   *end = 0;

	    // find the parentheses and address offset surrounding the mangled name

		for(char *j = functions[i]; *j; ++j)
		{
			if (*j == '(')
			{
				begin = j;
			}
	        else
			{
				if (*j == '+')
				{
					end = j;
				}
			}
		}

		if(begin && end)
		{
			*begin++ = '\0';
			*end = '\0';

			// found our mangled name, now in [begin, end)

			int		status;

			char   *ret = abi::__cxa_demangle(begin, function, &sz, &status);

			if(ret != NULL)
			{
				// return value may be a realloc() of the input

				function = ret;
			}
			else
			{
				// demangling failed, just pretend it's a C function with no args

				strncpy(function, begin, sz);
				strncat(function, "()", sz);

				function[sz - 1] = '\0';
			}

			PRINTF("%s:%s\n", functions[i], function);
		}
		else
		{
			// didn't find the mangled name, just print the whole line

			PRINTF("%s\n", functions[i]);
		}

		free(function);
	}

	free(functions);

	EXIT();
}
示例#10
0
    unsigned int flag;

    if ((flagStr = getenv(name)) == NULL)
        return 0;

    if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
        return 0;

    return flag;
}

#ifdef TEST_OOM_TRACE
static void virTestAllocHook(int nalloc ATTRIBUTE_UNUSED,
                             void *opaque ATTRIBUTE_UNUSED)
{
    ntestAllocStack = backtrace(testAllocStack, ARRAY_CARDINALITY(testAllocStack));
}
#endif

#ifdef TEST_OOM_TRACE
static void
virTestShowTrace(void)
{
    size_t j;
    for (j = 2; j < ntestAllocStack; j++) {
        Dl_info info;
        char *cmd;

        dladdr(testAllocStack[j], &info);
        if (info.dli_fname &&
            strstr(info.dli_fname, ".so")) {
示例#11
0
static int xbt_log_layout_format_doit(xbt_log_layout_t l,
                                      xbt_log_event_t ev,
                                      const char *msg_fmt)
{
  char *p = ev->buffer;
  int rem_size = ev->buffer_size;
  int precision = -1;
  int length = -1;
  char *q;

  for (q = l->data ; *q != '\0' ; q++) {
    if (*q == '%') {
      q++;
    handle_modifier:
      switch (*q) {
      case '\0':
        fprintf(stderr, "Layout format (%s) ending with %%\n", (char *)l->data);
        xbt_abort();
      case '%':
        *p = '%';
        check_overflow(1);
        break;
      case 'n':         /* platform-dependant line separator; LOG4J compliant */
        *p = '\n';
        check_overflow(1);
        break;
      case 'e':                 /* plain space; SimGrid extension */
        *p = ' ';
        check_overflow(1);
        break;
      case '.':                 /* precision specifier */
        precision = strtol(q + 1, &q, 10);
        goto handle_modifier;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':                 /* length modifier */
        length = strtol(q, &q, 10);
        goto handle_modifier;
      case 'c':                 /* category name; LOG4J compliant
                                   should accept a precision postfix to show the
                                   hierarchy */
        show_string(ev->cat->name);
        break;
      case 'p':                 /* priority name; LOG4J compliant */
        show_string(xbt_log_priority_names[ev->priority]);
        break;
      case 'h':                 /* host name; SimGrid extension */
        show_string(SIMIX_host_self_get_name());
        break;
      case 't':                 /* thread name; LOG4J compliant */
        show_string(xbt_thread_self_name());
        break;
      case 'P':                 /* process name; SimGrid extension */
        show_string(xbt_procname());
        break;
      case 'i':                 /* process PID name; SimGrid extension */
        show_int(xbt_getpid());
        break;
      case 'F':                 /* file name; LOG4J compliant */
        show_string(ev->fileName);
        break;
      case 'l': {               /* location; LOG4J compliant */
        int len, sz;
        set_sz_from_precision();
        len = snprintf(p, sz, "%s:%d", ev->fileName, ev->lineNum);
        check_overflow(MIN(sz, len));
        break;
      }
      case 'L':                 /* line number; LOG4J compliant */
        show_int(ev->lineNum);
        break;
      case 'M':                /* method (ie, function) name; LOG4J compliant */
        show_string(ev->functionName);
        break;
      case 'b':                 /* backtrace; called %throwable in LOG4J */
      case 'B':         /* short backtrace; called %throwable{short} in LOG4J */
#if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
        {
          xbt_ex_t e;

          e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
          e.bt_strings = NULL;
          e.msg = NULL;
          xbt_ex_setup_backtrace(&e);
          if (*q == 'B') {
            show_string(e.bt_strings[1] + 8);
          } else {
            xbt_strbuff_t buff = xbt_strbuff_new();
            int i;
            xbt_strbuff_append(buff, e.bt_strings[1] + 8);
            for (i = 2; i < e.used; i++) {
              xbt_strbuff_append(buff, "\n");
              xbt_strbuff_append(buff, e.bt_strings[i] + 8);
            }
            show_string(buff->data);
            xbt_strbuff_free(buff);
          }
          xbt_ex_free(e);
        }
#else
        show_string("(no backtrace on this arch)");
#endif
        break;
      case 'd':                 /* date; LOG4J compliant */
        show_double(surf_get_clock());
        break;
      case 'r':                 /* application age; LOG4J compliant */
        show_double(surf_get_clock() - format_begin_of_time);
        break;
      case 'm': {               /* user-provided message; LOG4J compliant */
        int len, sz;
        set_sz_from_precision();
        len = vsnprintf(p, sz, msg_fmt, ev->ap);
        check_overflow(MIN(sz, len));
        break;
      }
      default:
        fprintf(stderr, ERRMSG, *q, (char *)l->data);
        xbt_abort();
      }
    } else {
      *p = *q;
      check_overflow(1);
    }
  }
  *p = '\0';

  return 1;
}
示例#12
0
sci_backtrace_t *sci_backtrace_create(void)
{
#if defined(HAVE_GLIBC_BACKTRACE)

    sci_backtrace_t *bt = NULL;

    /* Create backtrace structure */

    bt = malloc(sizeof(sci_backtrace_t));

    if (bt != NULL)
    {

        void * tr_array[200];
        int tr_size = backtrace(tr_array, 200);
        int i = 0;
        Dl_info * infos = NULL;

        /* Create arrays; we use malloc() here instead of BFT_MALLOC, as a
          * backtrace is useful mainly in case of severe errors, so we avoid
          * higher level constructs as much as possible at this stage. */

        if (tr_size < 2)// || tr_strings == NULL)
        {
            free(bt);
            return NULL;
        }

        bt->size = tr_size;

        bt->s_file = malloc(tr_size * sizeof(char *));
        bt->s_func = malloc(tr_size * sizeof(char *));
        bt->s_addr = malloc(tr_size * sizeof(char *));

        /* If allocation has failed, free other allocated arrays, and return NULL */

        if (bt->s_file == NULL || bt->s_func == NULL || bt->s_addr == NULL)
        {

            if (bt->s_file != NULL)
            {
                free(bt->s_file);
            }
            if (bt->s_func != NULL)
            {
                free(bt->s_func);
            }
            if (bt->s_addr != NULL)
            {
                free(bt->s_addr);
            }

            free(bt);
            return NULL;

        }

        infos = (Dl_info *)MALLOC(sizeof(Dl_info));

        for (i = 0; i < bt->size; i++)
        {
            char buffer[32];
            void * p = tr_array[i];

            bt->s_file[i] = NULL;
            bt->s_func[i] = NULL;
            bt->s_addr[i] = NULL;

            if (dladdr(p, infos))
            {
                bt->s_func[i] = infos->dli_sname ? strdup(infos->dli_sname) : strdup(" ");
                bt->s_file[i] = infos->dli_fname ? strdup(infos->dli_fname) : strdup(" ");

                // we calculate the relative address in the library
                snprintf(buffer, 32, "%p", p - infos->dli_fbase);
                bt->s_addr[i] = strdup(buffer);
            }
        }

        FREE(infos);
        infos = NULL;
    }

    return bt;

#else /* defined(HAVE_GLIBC_BACKTRACE) */
    return NULL;
#endif
}
示例#13
0
文件: sig_segv.c 项目: hydrix1/tacacs
void catchsegv(int sig __attribute__ ((unused)))
#endif
{
    char buf[1024];
    FILE *g;

    logmsg("Catched SIGSEGV");
    logmsg("Apologies ... this shouldn't have happened. Please verify that");
    logmsg("you are running the most current version, downloadable from");
    logmsg("    http://www.pro-bono-publico.de/projects/");
    logmsg("If the version on that site doesn't equal");
    logmsg("    " VERSION);
    logmsg("please download, compile, install and check if you're");
    logmsg("still seeing the crash. After all, this bug may be already fixed.");
    logmsg("If the issue persists even with the most recent version:");
    logmsg("Reconfigure with --debug, recompile and reinstall. Then send");
    logmsg("a bug report to the mailing-list at");
    logmsg("    [email protected]");
    logmsg("and include the backtraces.");
    logmsg("Please do NOT mail bug reports it to the private mail address of");
    logmsg("the author, unless you have a pretty good reason for doing so.");
    logmsg("Thank you.");

    snprintf(buf, sizeof(buf), "CRASHPID=%lu", (long unsigned) getpid());
    putenv(buf);

#ifdef HAVE_EXECINFO_H
    {
	void *array[40];
	int len = backtrace(array, 40);
	char **c = backtrace_symbols(array, len);
	logmsg("EXECINFO: backtrace start");
	while (len-- > 0)
	    logmsg("EXECINFO: %d %s", len, c[len]);
	logmsg("EXECINFO: backtrace end");
    }
#endif				/* HAVE_EXECINFO_H */

    if (!gdbcmd)
	gdbcmd = "(printf 'bt\nq\n';sleep 3)|gdb -n -q -p $CRASHPID 2>/dev/null";
    g = popen(gdbcmd, "r");
    if (g) {
	logmsg("GDB: running: \"%s\"", gdbcmd);
	logmsg("GDB: backtrace start");
	while (fgets(buf, sizeof(buf), g))
	    logmsg("GDB: %s", buf);
	fclose(g);
	logmsg("GDB: backtrace end");
    }
#ifdef EXC_BAD_INSTRUCTION
    signal(EXC_BAD_INSTRUCTION, SIG_DFL);
#endif
#ifdef SIGBUS
    signal(SIGBUS, SIG_DFL);
#endif
    signal(SIGSEGV, SIG_DFL);

    if (coredumpdir) {
	struct rlimit rlim;
	char cdf[PATH_MAX];

	snprintf(cdf, sizeof(cdf), "%s/core.%.8lx", coredumpdir, (u_long) time(NULL));

	seteuid(getuid());
	setegid(getgid());

	if (getrlimit(RLIMIT_CORE, &rlim)) {
	    logerr("getrlimit (%s:%d)", __FILE__, __LINE__);
	    exit(EX_OSERR);
	}

	rlim.rlim_cur = rlim.rlim_max;
	setrlimit(RLIMIT_CORE, &rlim);

	if (chdir(coredumpdir)) {
	    logerr("SIGSEGV: chdir(%s) (%s:%d)", coredumpdir, __FILE__, __LINE__);
	    exit(EX_NOPERM);
	}

	rename("core", cdf);
	logmsg("SIGSEGV: Trying to dump core in %s", coredumpdir);

	if (gcorecmd) {
	    g = popen(gcorecmd, "r");
	    if (g) {
		while (fgets(buf, sizeof(buf), g))
		    logmsg("GCORE: %s", buf);
		fclose(g);
	    }
	} else
	    abort();
    }
    exit(EX_UNAVAILABLE);
}
示例#14
0
文件: mini-posix.c 项目: Alkarex/mono
static void
SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
{
	int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
	MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
	GET_CONTEXT;
	
	if (call_chain_depth == 0) {
		mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
	} else {
		MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
		int current_frame_index = 1;
		MonoContext mono_context;
		guchar *ips [call_chain_depth + 1];

		mono_arch_sigctx_to_monoctx (ctx, &mono_context);
		ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
		
		if (jit_tls != NULL) {
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
#if FULL_STAT_PROFILER_BACKTRACE
			guchar *current_frame;
			guchar *stack_bottom;
			guchar *stack_top;
			
			stack_bottom = jit_tls->end_of_stack;
			stack_top = MONO_CONTEXT_GET_SP (&mono_context);
			current_frame = MONO_CONTEXT_GET_BP (&mono_context);
			
			while ((current_frame_index <= call_chain_depth) &&
					(stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
					((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
				ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
				current_frame_index ++;
				stack_top = current_frame;
				current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
			}
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
#endif
			}
			
			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
#if GLIBC_PROFILER_BACKTRACE
				current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
#else
				call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
#endif
			}

			if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
				MonoDomain *domain = mono_domain_get ();
				if (domain != NULL) {
					MonoLMF *lmf = NULL;
					MonoJitInfo *ji;
					MonoJitInfo res;
					MonoContext new_mono_context;
					int native_offset;
					ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
							&new_mono_context, NULL, &lmf, &native_offset, NULL);
					while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
						ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
						current_frame_index ++;
						mono_context = new_mono_context;
						ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
								&new_mono_context, NULL, &lmf, &native_offset, NULL);
					}
				}
			}
		}
		
		mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
	}

	mono_chain_signal (SIG_HANDLER_PARAMS);
}
示例#15
0
文件: signals.c 项目: lye/yadifa
static void
signal_handler(int signo, siginfo_t* info, void* context)
{
    /*
    int status;
    int i;
    */

    /*    ------------------------------------------------------------    */

    switch(signo)
    {
    case SIGHUP:
    {
        signal_task_logger_handle_reopen_all();
        break;
    }
    case SIGUSR1:
    {
        /* write all (dirty) zones to disk */

        signal_task_database_save_all_zones_to_disk();

        break;
    }
    case SIGUSR2:
    {
        // Used to break a syscall (sync)
        break;
    }
    case SIGINT:
    case SIGTERM:
    {
        /*
         * We are shutting down : ignore other "command" signals
         */

        signal(SIGHUP, SIG_IGN);
        signal(SIGUSR1, SIG_IGN);
        signal(SIGINT, SIG_IGN);
        signal(SIGTERM, SIG_IGN);

        signal_task_shutdown();

        break;
    }
#if SIGNAL_HOOK_COREDUMP == 0
    case SIGBUS:
    case SIGFPE:
    case SIGILL:
    case SIGSEGV:
    {
        signal(signo, SIG_DFL);

        if(sigsegv_trytrace)
        {
            char filepath[1024];
            FILE *f;

            /* So if we crashed while trying to dump, we will not do it anymore */
            sigsegv_trytrace = FALSE;

            snprintf(filepath, sizeof(filepath), "%ssig%i.%i", config->log_path, signo, getpid());

            f = fopen(filepath, "a+");

            if(f == NULL)
            {
                snprintf(filepath, sizeof(filepath), "/tmp/yadifa.sig%i.%i", signo, getpid());

                f = fopen(filepath, "a+");
            }

            if(f != NULL)
            {

#if defined(__linux__)
                void* buffer[MAXTRACE];
                char** strings;
                int n = backtrace(buffer, MAXTRACE);
                int i;
                time_t now = time(NULL);

                fprintf(f, "Signal %i at time=%li for address %p\n", signo, now, info->si_addr);

                fflush(f);

                strings = backtrace_symbols(buffer, n);

                if(strings != NULL)
                {
                    for(i = 0; i < n; i++)
                    {
                        fprintf(f, "\t[%3i]: %s\n", i, strings[i]);
                    }
                }
                else
                {
                    fprintf(f, "No backtrace available (%s)\n", strerror(errno));
                }
                fflush(f);
                fprintf(f, "pid: %i\n", getpid());
                fprintf(f, "thread id: %d",  (u32)pthread_self());
#else
                fprintf(f, "Got signal %i.  No backtrace available\n", signo);
#endif
                fclose(f);
            }

            /**
             * Do NOT free(strings) :
             * If the memory is corrupted, this is one more chance to crash
             *
             */
        }

        /* There COULD be some relevant information in the logger */
        /* try to flush it */

        if(sigsegv_tryloggerflush)
        {
            sigsegv_tryloggerflush = FALSE;
            logger_flush();
            log_err("CRITICAL ERROR");
            logger_flush();
        }

        /* trigger the original signal (to dump a core if possible ) */

        raise(signo);

        /* should never be reached : Exit without disabling stuff (no atexit registered function called) */

        _exit(EXIT_CODE_SELFCHECK_ERROR);

        break;
    }
#endif

    /*
    case SIGUSR2:
    case SIGCHLD:
    */
    default:
    {
        break;
    }
    }
}
示例#16
0
static void 
traphandler(int sig, siginfo_t *si, void *UC)
{
  ucontext_t *uc = UC;

  if(extra_traphandler != NULL && !extra_traphandler(sig, si, UC))
    return;
    
  static void *frames[MAXFRAMES];
  char buf[256];
  int nframes = backtrace(frames, MAXFRAMES);
  const char *reason = NULL;

  TRAPMSG("Signal: %d in %s ", sig, line1);

  switch(sig) {
  case SIGSEGV:
    switch(si->si_code) {
    case SEGV_MAPERR:  reason = "Address not mapped"; break;
    case SEGV_ACCERR:  reason = "Access error"; break;
    }
    break;

  case SIGFPE:
    switch(si->si_code) {
    case FPE_INTDIV:  reason = "Integer division by zero"; break;
    }
    break;
  }

  addr2text(buf, sizeof(buf), si->si_addr);

  TRAPMSG("Fault address %s (%s)", buf, reason ?: "N/A");

  TRAPMSG("Loaded libraries: %s ", libs);

#if defined(__arm__) 
  TRAPMSG("   trap_no = %08lx", uc->uc_mcontext.trap_no);
  TRAPMSG("error_code = %08lx", uc->uc_mcontext.error_code);
  TRAPMSG("   oldmask = %08lx", uc->uc_mcontext.oldmask);
  TRAPMSG("        R0 = %08lx", uc->uc_mcontext.arm_r0);
  TRAPMSG("        R1 = %08lx", uc->uc_mcontext.arm_r1);
  TRAPMSG("        R2 = %08lx", uc->uc_mcontext.arm_r2);
  TRAPMSG("        R3 = %08lx", uc->uc_mcontext.arm_r3);
  TRAPMSG("        R4 = %08lx", uc->uc_mcontext.arm_r4);
  TRAPMSG("        R5 = %08lx", uc->uc_mcontext.arm_r5);
  TRAPMSG("        R6 = %08lx", uc->uc_mcontext.arm_r6);
  TRAPMSG("        R7 = %08lx", uc->uc_mcontext.arm_r7);
  TRAPMSG("        R8 = %08lx", uc->uc_mcontext.arm_r8);
  TRAPMSG("        R9 = %08lx", uc->uc_mcontext.arm_r9);
  TRAPMSG("       R10 = %08lx", uc->uc_mcontext.arm_r10);
  TRAPMSG("        FP = %08lx", uc->uc_mcontext.arm_fp);
  TRAPMSG("        IP = %08lx", uc->uc_mcontext.arm_ip);
  TRAPMSG("        SP = %08lx", uc->uc_mcontext.arm_sp);
  TRAPMSG("        LR = %08lx", uc->uc_mcontext.arm_lr);
  TRAPMSG("        PC = %08lx", uc->uc_mcontext.arm_pc);
  TRAPMSG("      CPSR = %08lx", uc->uc_mcontext.arm_cpsr);
  TRAPMSG("fault_addr = %08lx", uc->uc_mcontext.fault_address);

#else
  char tmpbuf[1024];
  snprintf(tmpbuf, sizeof(tmpbuf), "Register dump [%d]: ", NGREG);
  int i;
  for(i = 0; i < NGREG; i++) {
#if __WORDSIZE == 64
    sappend(tmpbuf, sizeof(tmpbuf), "%016llx ", uc->uc_mcontext.gregs[i]);
#else
    sappend(tmpbuf, sizeof(tmpbuf), "%08x ", uc->uc_mcontext.gregs[i]);
#endif
  }
  TRAPMSG("%s", tmpbuf);
#endif

  dumpstack(frames, nframes);
  _exit(8);
}
示例#17
0
/** Print a demangled stack backtrace of the caller function to FILE* out. */
static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) {
   pvStackTrace() << "stack trace:" << std::endl;

   // storage array for stack trace address data
   void *addrlist[max_frames+1];

   // retrieve current stack addresses
   int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

   if (addrlen == 0) {
      pvStackTrace() << "  <empty, possibly corrupt>" << std::endl;
      return;
   }

   // resolve addresses into strings containing "filename(function+address)",
   // this array must be free()-ed
   char** symbollist = backtrace_symbols(addrlist, addrlen);

   // allocate string which will be filled with the demangled function name
   size_t funcnamesize = 256;
   char* funcname = (char*) malloc(funcnamesize);

   // iterate over the returned symbol lines. skip the first, it is the
   // address of this function.
   for (int i = 1; i < addrlen; i++) {
      char *begin_name = 0, *begin_offset = 0, *end_offset = 0;

      // find parentheses and +address offset surrounding the mangled name:
      // ./module(function+0x15c) [0x8048a6d]
      for (char *p = symbollist[i]; *p; ++p) {
         if (*p == '(')
            begin_name = p;
         else if (*p == '+')
            begin_offset = p;
         else if (*p == ')' && begin_offset) {
            end_offset = p;
            break;
         }
      }

      if (begin_name && begin_offset && end_offset
          && begin_name < begin_offset)
      {
         *begin_name++ = '\0';
         *begin_offset++ = '\0';
         *end_offset = '\0';

         // mangled name is now in [begin_name, begin_offset) and caller
         // offset in [begin_offset, end_offset). now apply
         // __cxa_demangle():

         int status;
         char* ret = abi::__cxa_demangle(begin_name,
                                         funcname, &funcnamesize, &status);
         if (status == 0) {
            funcname = ret; // use possibly realloc()-ed string
            pvStackTrace() << "  " << symbollist[i] << " : " << funcname << "+" << begin_offset << std::endl;
         }
         else {
            // demangling failed. Output function name as a C function with
            // no arguments.
            pvStackTrace() << "  " << symbollist[i] << " : " << begin_name << "+" << begin_offset << std::endl;
         }
      }
      else
      {
         // couldn't parse the line? print the whole line.
         pvStackTrace() << "  " << symbollist[i] << std::endl;
      }
   }
   
   free(funcname);
   free(symbollist);
}
示例#18
0
void	print_fatal_info(int sig, siginfo_t *siginfo, void *context)
{
#ifdef	HAVE_SYS_UCONTEXT_H

	ucontext_t	*uctx = (ucontext_t *)context;

	/* look for GET_PC() macro in sigcontextinfo.h files */
	/* of glibc if you wish to add more CPU architectures */

#	if	defined(REG_EIP)	/* i386 */

#		define ZBX_GET_REG(uctx, reg)	(uctx)->uc_mcontext.gregs[reg]
#		define ZBX_GET_PC(uctx)		ZBX_GET_REG(uctx, REG_EIP)

#	elif	defined(REG_RIP)	/* x86_64 */

#		define ZBX_GET_REG(uctx, reg)	(uctx)->uc_mcontext.gregs[reg]
#		define ZBX_GET_PC(uctx)		ZBX_GET_REG(uctx, REG_RIP)

#	endif

#endif	/* HAVE_SYS_UCONTEXT_H */

#ifdef	HAVE_EXECINFO_H

#	define	ZBX_BACKTRACE_SIZE	60

	char	**bcktrc_syms;
	void	*bcktrc[ZBX_BACKTRACE_SIZE];
	int	bcktrc_sz;

#endif	/* HAVE_EXECINFO_H */

	int	i;
	FILE	*fd;

	zabbix_log(LOG_LEVEL_CRIT, "====== Fatal information: ======");

#ifdef	HAVE_SYS_UCONTEXT_H

#ifdef	ZBX_GET_PC
	zabbix_log(LOG_LEVEL_CRIT, "Program counter: %p", ZBX_GET_PC(uctx));
	zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
	for (i = 0; i < NGREG; i++)
		zabbix_log(LOG_LEVEL_CRIT, "%-7s = %16lx = %20lu = %20ld", get_register_name(i),
				ZBX_GET_REG(uctx, i), ZBX_GET_REG(uctx, i), ZBX_GET_REG(uctx, i));

#ifdef	REG_EBP	/* dump a bit of stack frame for i386 */
	zabbix_log(LOG_LEVEL_CRIT, "=== Stack frame: ===");
	for (i = 16; i >= 2; i--)
		zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x = %10u = %11d%s",
				i * ZBX_PTR_SIZE, i * ZBX_PTR_SIZE,
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + i * ZBX_PTR_SIZE),
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + i * ZBX_PTR_SIZE),
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + i * ZBX_PTR_SIZE),
				i == 2 ? " <--- call arguments" : "");
	zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x%28s<--- return address",
				ZBX_PTR_SIZE, ZBX_PTR_SIZE,
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + ZBX_PTR_SIZE), "");
	zabbix_log(LOG_LEVEL_CRIT, "     (%%ebp) = ebp      = %08x%28s<--- saved ebp value",
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP)), "");
	for (i = 1; i <= 16; i++)
		zabbix_log(LOG_LEVEL_CRIT, "-0x%02x(%%ebp) = ebp - %2d = %08x = %10u = %11d%s",
				i * ZBX_PTR_SIZE, i * ZBX_PTR_SIZE,
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - i * ZBX_PTR_SIZE),
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - i * ZBX_PTR_SIZE),
				*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - i * ZBX_PTR_SIZE),
				i == 1 ? " <--- local variables" : "");
#endif	/* REG_EBP */

#else
	zabbix_log(LOG_LEVEL_CRIT, "program counter not available for this architecture");
	zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
	zabbix_log(LOG_LEVEL_CRIT, "register dump not available for this architecture");
#endif	/* ZBX_GET_PC */

#endif	/* HAVE_SYS_UCONTEXT_H */

	zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ===");

#ifdef	HAVE_EXECINFO_H

	bcktrc_sz = backtrace(bcktrc, ZBX_BACKTRACE_SIZE);
	bcktrc_syms = backtrace_symbols(bcktrc, bcktrc_sz);

	if (NULL == bcktrc_syms)
	{
		zabbix_log(LOG_LEVEL_CRIT, "error in backtrace_symbols(): [%s]", strerror(errno));

		for (i = 0; i < bcktrc_sz; i++)
			zabbix_log(LOG_LEVEL_CRIT, "%d: %p", bcktrc_sz - i - 1, bcktrc[i]);
	}
	else
	{
		for (i = 0; i < bcktrc_sz; i++)
			zabbix_log(LOG_LEVEL_CRIT, "%d: %s", bcktrc_sz - i - 1, bcktrc_syms[i]);

		zbx_free(bcktrc_syms);
	}
#else
	zabbix_log(LOG_LEVEL_CRIT, "backtrace not available for this platform");

#endif	/* HAVE_EXECINFO_H */

	zabbix_log(LOG_LEVEL_CRIT, "=== Memory map: ===");

	if (NULL != (fd = fopen("/proc/self/maps", "r")))
	{
		char line[1024];

		while (NULL != fgets(line, sizeof(line), fd))
		{
			if (line[0] != '\0')
				line[strlen(line) - 1] = '\0'; /* remove trailing '\n' */

			zabbix_log(LOG_LEVEL_CRIT, "%s", line);
		}

		zbx_fclose(fd);
	}
	else
		zabbix_log(LOG_LEVEL_CRIT, "memory map not available for this platform");

#ifdef	ZBX_GET_PC
	zabbix_log(LOG_LEVEL_CRIT, "================================");
	zabbix_log(LOG_LEVEL_CRIT, "Please consider attaching a disassembly listing to your bug report.");
	zabbix_log(LOG_LEVEL_CRIT, "This listing can be produced with, e.g., objdump -D -S %s.", progname);
#endif

	zabbix_log(LOG_LEVEL_CRIT, "================================");
}
示例#19
0
文件: trap.c 项目: Ferni7/tvheadend
static void 
traphandler(int sig, siginfo_t *si, void *UC)
{
#ifdef NGREG
  ucontext_t *uc = UC;
#endif
#if ENABLE_EXECINFO
  char buf[200];
  static void *frames[MAXFRAMES];
  int nframes = backtrace(frames, MAXFRAMES);
  Dl_info dli;
#endif
#if defined(NGREG) || ENABLE_EXECINFO
  int i;
#endif
  const char *reason = NULL;

  tvhlog_spawn(LOG_ALERT, "CRASH", "Signal: %d in %s ", sig, line1);

  switch(sig) {
  case SIGSEGV:
    switch(si->si_code) {
    case SEGV_MAPERR:  reason = "Address not mapped"; break;
    case SEGV_ACCERR:  reason = "Access error"; break;
    }
    break;

  case SIGFPE:
    switch(si->si_code) {
    case FPE_INTDIV:  reason = "Integer division by zero"; break;
    }
    break;
  }

  tvhlog_spawn(LOG_ALERT, "CRASH", "Fault address %p (%s)",
	       si->si_addr, reason ?: "N/A");

  tvhlog_spawn(LOG_ALERT, "CRASH", "Loaded libraries: %s ", libs);
#ifdef NGREG
  snprintf(tmpbuf, sizeof(tmpbuf), "Register dump [%d]: ", (int)NGREG);

  for(i = 0; i < NGREG; i++) {
    sappend(tmpbuf, sizeof(tmpbuf), "%016" PRIx64, uc->uc_mcontext.gregs[i]);
  }
#endif
  tvhlog_spawn(LOG_ALERT, "CRASH", "%s", tmpbuf);

#if ENABLE_EXECINFO
  tvhlog_spawn(LOG_ALERT, "CRASH", "STACKTRACE");

  for(i = 0; i < nframes; i++) {

    
    if(dladdr(frames[i], &dli)) {

      if(dli.dli_sname != NULL && dli.dli_saddr != NULL) {
      	tvhlog_spawn(LOG_ALERT, "CRASH", "%s+0x%tx  (%s)",
		     dli.dli_sname,
		     frames[i] - dli.dli_saddr,
		     dli.dli_fname);
	continue;
      }

      if(self[0] && !add2lineresolve(self, frames[i], buf, sizeof(buf))) {
	tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p", buf, frames[i]);
	continue;
      }

      if(dli.dli_fname != NULL && dli.dli_fbase != NULL) {
      	tvhlog_spawn(LOG_ALERT, "CRASH", "%s %p",
 		     dli.dli_fname,
		     frames[i]);
	continue;
      }


      tvhlog_spawn(LOG_ALERT, "CRASH", "%p", frames[i]);
    }
  }
#endif
}
示例#20
0
inline void DCU_createStackTrace(DCU_ConstPointer stack[DCU_STACK_TRACE_SIZE])
{
	memset(stack, 0, sizeof(stack));
	backtrace((void**)(stack), DCU_STACK_TRACE_SIZE);
}
示例#21
0
// This uses glibc's basic built-in stack-trace functions together with
// ELFIO's ability to parse the .symtab ELF section for better symbol
// extraction without exporting symbols (which'd cause subtle, fatal bugs).
static inline BOOL do_elfio_glibc_backtrace()
{
	void *array[MAX_STACK_TRACE_DEPTH];
	size_t btsize;
	char **strings;
	BOOL success = FALSE;

	std::string appfilename = gDirUtilp->getExecutablePathAndName();

	std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
	llinfos << "Opening stack trace file " << strace_filename << llendl;
	LLFILE* StraceFile = LLFile::fopen(strace_filename, "w");		// Flawfinder: ignore
        if (!StraceFile)
	{
		llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl;
		StraceFile = stderr;
	}

	// get backtrace address list and basic symbol info
	btsize = backtrace(array, MAX_STACK_TRACE_DEPTH);
	strings = backtrace_symbols(array, btsize);

	// create ELF reader for our app binary
	IELFI* pReader;
	const IELFISection* pSec = NULL;
	IELFISymbolTable* pSymTbl = 0;
	if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) ||
	    ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) ||
	    // find symbol table, create reader-object
	    NULL == (pSec = pReader->GetSection( ".symtab" )) ||
	    ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) )
	{
		// Failed to open our binary and read its symbol table somehow
		llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl;
		if (StraceFile != stderr)
			fclose(StraceFile);
		// note that we may be leaking some of the above ELFIO
		// objects now, but it's expected that we'll be dead soon
		// and we want to tread delicately until we get *some* kind
		// of useful backtrace.
		return do_basic_glibc_backtrace();
	}

	// iterate over trace and symtab, looking for plausible symbols
	std::string   name;
	Elf32_Addr    value;
	Elf32_Word    ssize;
	unsigned char bind;
	unsigned char type;
	Elf32_Half    section;
	int nSymNo = pSymTbl->GetSymbolNum();
	size_t btpos;
	for (btpos = 0; btpos < btsize; ++btpos)
	{
		fprintf(StraceFile, "%d:\t", btpos);
		int symidx;
		for (symidx = 0; symidx < nSymNo; ++symidx)
		{
			if (ERR_ELFIO_NO_ERROR ==
			    pSymTbl->GetSymbol(symidx, name, value, ssize,
					       bind, type, section))
			{
				// check if trace address within symbol range
				if (uintptr_t(array[btpos]) >= value &&
				    uintptr_t(array[btpos]) < value+ssize)
				{
					char *demangled_str = NULL;
					int demangle_result = 1;
					demangled_str =
						abi::__cxa_demangle
						(name.c_str(), NULL, NULL,
						 &demangle_result);
					if (0 == demangle_result &&
					    NULL != demangled_str) {
						fprintf(StraceFile,
							"ELF(%s", demangled_str);
						free(demangled_str);
					}
					else // failed demangle; print it raw
					{
						fprintf(StraceFile,
							"ELF(%s", name.c_str());
					}
					// print offset from symbol start
					fprintf(StraceFile,
						"+0x%lx) [%p]\n",
						uintptr_t(array[btpos]) -
						value,
						array[btpos]);
					goto got_sym; // early escape
				}
			}
		}
		// Fallback:
		// Didn't find a suitable symbol in the binary - it's probably
		// a symbol in a DSO; use glibc's idea of what it should be.
		fprintf(StraceFile, "%s\n", strings[btpos]);
	got_sym:;
	}
	
	if (StraceFile != stderr)
		fclose(StraceFile);

	pSymTbl->Release();
	pSec->Release();
	pReader->Release();

	free(strings);

	llinfos << "Finished generating stack trace." << llendl;

	success = TRUE;
	return success;
}
示例#22
0
void DCU_initialize()
{
	if (DCU_STATE(DCU_INITIALIZED))
	{
		return;
	}

	if (DCU_STATE(DCU_MUTEX_INITED))
	{
		DCU_MutexScopedLock lock(DCU_mutex);
		if (DCU_STATE(DCU_INITIALIZED))
		{
			return;
		}
		else
		{
			fprintf(DCU_FALLBACK_STREAM, "DynamicCheckUp Concurrency error.\n");
			_exit(1);
		}
	}

	if (pthread_mutex_init(&DCU_mutex, 0) < 0)
	{
		fprintf(DCU_FALLBACK_STREAM, "DynamicCheckUp unable to initialize mutex\n");
		_exit(1);
	}
	else
	{
		DCU_SET_FLAG(DCU_MUTEX_INITED);
	}


	{
		DCU_MutexScopedLock lock(DCU_mutex);

		memory_space = create_mspace(0, 0);
		DCU_SET_FLAG(DCU_INITIALIZED);

		//
		// init backtrace so it wont recursively call malloc
		//
		DCU_Pointer stack[DCU_STACK_TRACE_SIZE];
		backtrace(stack, DCU_STACK_TRACE_SIZE);

		//
		// Init Tracing data
		//

		DCU_stream = DCU_FALLBACK_STREAM;
		memset(DCU_memory_stats, 0, sizeof(DCU_MemoryStats) * DCU_DYNAMIC_OPERATION_TYPES);
		memset(&DCU_memory_stats_new, 0, sizeof(DCU_MemoryStats));
		memset(&DCU_memory_stats_new_array, 0, sizeof(DCU_MemoryStats));
		memset(&DCU_memory_stats_c, 0, sizeof(DCU_MemoryStats));
		memset(DCU_null_stack, 0, sizeof(DCU_null_stack));

		//
		// Operations HashTable
		//
		DCU_memory = (DCU_OperationInfo**) DCU_malloc( DCU_HASH_TABLE_SIZE * sizeof(DCU_OperationInfo*) );
		memset(DCU_memory, 0, DCU_HASH_TABLE_SIZE * sizeof(DCU_OperationInfo*));

		//
		// Problems Linked-List
		//
		DCU_problems = 0;

		//
		// Open Log File
		//
		DCU_stream = fopen(DCU_OUTPUT_FILE, "w");
		if (DCU_stream < 0)
		{
			fprintf(DCU_FALLBACK_STREAM, "DynamicCheckUp: Unable to open %s: %m\n", DCU_OUTPUT_FILE);
			DCU_stream = DCU_FALLBACK_STREAM;
		}
		else
		{
			int flags = fcntl(fileno(DCU_stream), F_GETFD, 0);
			if (flags >= 0)
			{
				flags |= FD_CLOEXEC;
				fcntl(fileno(DCU_stream), F_SETFD, flags);
			}

			setvbuf(DCU_stream, stream_trace_buffer, _IOFBF, DCU_STREAM_BUFFER_SIZE);
		}

		DCU_SET_FLAG(DCU_TRACING);
	}

	DCU_write("DynamicCheckUp Started\n");
}
示例#23
0
/**
 * Prints a stack backtrace for the current thread to the specified ostream.
 *
 * Does not malloc, does not throw.
 *
 * The format of the backtrace is:
 *
 * ----- BEGIN BACKTRACE -----
 * JSON backtrace
 * Human-readable backtrace
 * -----  END BACKTRACE  -----
 *
 * The JSON backtrace will be a JSON object with a "backtrace" field, and optionally others.
 * The "backtrace" field is an array, whose elements are frame objects.  A frame object has a
 * "b" field, which is the base-address of the library or executable containing the symbol, and
 * an "o" field, which is the offset into said library or executable of the symbol.
 *
 * The JSON backtrace may optionally contain additional information useful to a backtrace
 * analysis tool.  For example, on Linux it contains a subobject named "somap", describing
 * the objects referenced in the "b" fields of the "backtrace" list.
 *
 * @param os    ostream& to receive printed stack backtrace
 */
void printStackTrace(std::ostream& os) {
    static const char unknownFileName[] = "???";
    void* addresses[maxBackTraceFrames];
    Dl_info dlinfoForFrames[maxBackTraceFrames];

    ////////////////////////////////////////////////////////////
    // Get the backtrace addresses.
    ////////////////////////////////////////////////////////////

    const int addressCount = backtrace(addresses, maxBackTraceFrames);
    if (addressCount == 0) {
        const int err = errno;
        os << "Unable to collect backtrace addresses (errno: " << err << ' ' << strerror(err) << ')'
           << std::endl;
        return;
    }

    ////////////////////////////////////////////////////////////
    // Collect symbol information for each backtrace address.
    ////////////////////////////////////////////////////////////

    os << std::hex << std::uppercase << '\n';
    for (int i = 0; i < addressCount; ++i) {
        Dl_info& dlinfo(dlinfoForFrames[i]);
        if (!dladdr(addresses[i], &dlinfo)) {
            dlinfo.dli_fname = unknownFileName;
            dlinfo.dli_fbase = NULL;
            dlinfo.dli_sname = NULL;
            dlinfo.dli_saddr = NULL;
        }
        os << ' ' << addresses[i];
    }

    os << "\n----- BEGIN BACKTRACE -----\n";

    ////////////////////////////////////////////////////////////
    // Display the JSON backtrace
    ////////////////////////////////////////////////////////////

    os << "{\"backtrace\":[";
    for (int i = 0; i < addressCount; ++i) {
        const Dl_info& dlinfo = dlinfoForFrames[i];
        const uintptr_t fileOffset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase);
        if (i)
            os << ',';
        os << "{\"b\":\"" << uintptr_t(dlinfo.dli_fbase) << "\",\"o\":\"" << fileOffset;
        if (dlinfo.dli_sname) {
            os << "\",\"s\":\"" << dlinfo.dli_sname;
        }
        os << "\"}";
    }
    os << ']';

    if (soMapJson)
        os << ",\"processInfo\":" << *soMapJson;
    os << "}\n";

    ////////////////////////////////////////////////////////////
    // Display the human-readable trace
    ////////////////////////////////////////////////////////////
    for (int i = 0; i < addressCount; ++i) {
        Dl_info& dlinfo(dlinfoForFrames[i]);
        os << ' ';
        if (dlinfo.dli_fbase) {
            os << getBaseName(dlinfo.dli_fname) << '(';
            if (dlinfo.dli_sname) {
                const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_saddr);
                os << dlinfo.dli_sname << "+0x" << offset;
            } else {
                const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase);
                os << "+0x" << offset;
            }
            os << ')';
        } else {
            os << unknownFileName;
        }
        os << " [" << addresses[i] << ']' << std::endl;
    }

    os << std::dec << std::nouppercase;
    os << "-----  END BACKTRACE  -----" << std::endl;
}
示例#24
0
    void Signals::collect_callstack(size_t skipLevels, bool makeFunctionNamesStandOut, const std::function<void(const std::string&)>& write)
    {


        write("\n[CALL STACK]\n");

#ifdef _WIN32
        static const int MAX_CALLERS = 62;
        static const unsigned short MAX_CALL_STACK_DEPTH = 20;

        // RtlCaptureStackBackTrace() is a kernel API without default binding, we must manually determine its function pointer.
        if(RtlCaptureStackBackTrace_func == nullptr)
            RtlCaptureStackBackTrace_func  = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace"));
        if (RtlCaptureStackBackTrace_func == nullptr) // failed somehow
            return write("Failed to generate CALL STACK. GetProcAddress(\"RtlCaptureStackBackTrace\") failed with error " + utf8(FormatWin32Error(GetLastError())) + "\n");

        HANDLE process = GetCurrentProcess();
        if (!SymInitialize(process, nullptr, TRUE))
            return write("Failed to generate CALL STACK. SymInitialize() failed with error " + utf8(FormatWin32Error(GetLastError())) + "\n");

        // get the call stack
        void* callStack[MAX_CALLERS];
        unsigned short frames;
        frames = RtlCaptureStackBackTrace_func(0, MAX_CALLERS, callStack, nullptr);

        SYMBOL_INFO* symbolInfo = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); // this is a variable-length structure, can't use vector easily
        symbolInfo->MaxNameLen = 255;
        symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
        frames = std::min(frames, MAX_CALL_STACK_DEPTH);

        // format and emit
        size_t firstFrame = skipLevels + 1; // skip CollectCallStack()
        for (size_t i = firstFrame; i < frames; i++)
        {
            if (i == firstFrame)
                write("    > ");
            else
                write("    - ");

            if (SymFromAddr(process, (DWORD64)(callStack[i]), 0, symbolInfo))
            {
                write(makeFunctionNamesStandOut ? MakeFunctionNameStandOut(symbolInfo->Name) : symbolInfo->Name);
                write("\n");
            }
            else
            {
                DWORD error = GetLastError();
                char buf[17];
                sprintf_s(buf, "%p", callStack[i]);
                write(buf);
                write(" (SymFromAddr() error: " + utf8(FormatWin32Error(error)) + ")\n");
            }
        }

        write("\n");

        free(symbolInfo);

        SymCleanup(process);

#else // Linux

        unsigned int MAX_NUM_FRAMES = 1024;
        void* backtraceAddresses[MAX_NUM_FRAMES];
        unsigned int numFrames = backtrace(backtraceAddresses, MAX_NUM_FRAMES);
        char** symbolList = backtrace_symbols(backtraceAddresses, numFrames);

        for (size_t i = skipLevels; i < numFrames; i++)
        {
            char* beginName    = NULL;
            char* beginOffset  = NULL;
            char* beginAddress = NULL;

            // Find parentheses and +address offset surrounding the mangled name
            for (char* p = symbolList[i]; *p; ++p)
            {
                if (*p == '(')      // function name begins here
                    beginName = p;
                else if (*p == '+') // relative address ofset
                    beginOffset = p;
                else if ((*p == ')') && (beginOffset || beginName)) // absolute address
                    beginAddress = p;
            }
            const int buf_size = 1024;
            char buffer[buf_size];

            if (beginName && beginAddress && (beginName < beginAddress))
            {
                *beginName++ = '\0';
                *beginAddress++ = '\0';
                if (beginOffset) // has relative address
                    *beginOffset++ = '\0';

                // Mangled name is now in [beginName, beginOffset) and caller offset in [beginOffset, beginAddress).
                int status = 0;
                unsigned int MAX_FUNCNAME_SIZE = 4096;
                size_t funcNameSize = MAX_FUNCNAME_SIZE;
                char funcName[MAX_FUNCNAME_SIZE]; // working buffer
                const char* ret = abi::__cxa_demangle(beginName, funcName, &funcNameSize, &status);
                std::string fName;
                if (status == 0)
                    fName = makeFunctionNamesStandOut ? MakeFunctionNameStandOut(ret) : ret; // make it a bit more readable
                else
                    fName = beginName; // failed: fall back

                // name of source file--not printing since it is not super-useful
                //string sourceFile = symbolList[i];
                //static const size_t sourceFileWidth = 20;
                //if (sourceFile.size() > sourceFileWidth)
                //    sourceFile = "..." + sourceFile.substr(sourceFile.size() - (sourceFileWidth-3));
                while (*beginAddress == ' ') // eat unnecessary space
                    beginAddress++;
                std::string pcOffset = beginOffset ? std::string(" + ") + beginOffset : std::string();
                snprintf(buffer, buf_size, "%-20s%-50s%s\n", beginAddress, fName.c_str(), pcOffset.c_str());
            }
            else // Couldn't parse the line. Print the whole line as it came.
                snprintf(buffer, buf_size, "%s\n", symbolList[i]);

            write(buffer);
        }

        free(symbolList);

#endif
    }
示例#25
0
文件: tmain.c 项目: Ken2713/sigram
void print_backtrace (void) {
  void *buffer[255];
  const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *));
  backtrace_symbols_fd (buffer, calls, 1);
}
示例#26
0
CStackTraceImpl::CStackTraceImpl(void)
{
    m_Stack.resize(CStackTrace::s_GetStackTraceMaxDepth());
    m_Stack.resize(backtrace(&m_Stack[0], m_Stack.size()));
}
示例#27
0
/*
 * Wrapped call to libc backtrace function
 */
uintptr_t
protectedBacktrace(struct OMRPortLibrary *port, void *arg)
{
	struct frameData *addresses = (struct frameData *) arg;
	return backtrace(addresses->address_array, addresses->capacity);
}
示例#28
0
  static void segv_handler(int sig) {
    static int crashing = 0;
    void* array[64];
    size_t size;

    // So we don't recurse!
    if(crashing) exit(101);

    crashing = 1;

    int fd = 2;

    if(getenv("RBX_PAUSE_ON_CRASH")) {
      std::cerr << "\n========== CRASH (" << getpid();
      std::cerr << "), pausing for 60 seconds to attach debugger\n";
      sleep(60);
    }

    // If there is a report_path setup..
    if(report_path[0]) {
      fd = open(report_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
      // If we can't open this path, use stderr.
      if(fd == -1) fd = 2;
    }

    // print out all the frames to stderr
    static const char header[] = 
      "Rubinius Crash Report #rbxcrashreport\n\n"
      "Error: signal ";

    safe_write(fd, header, sizeof(header));
    write_sig(fd, sig);

    safe_write(fd, "\n\n[[Backtrace]]\n");

    // get void*'s for all entries on the stack
    size = backtrace(array, 64);

    backtrace_symbols_fd(array, size, fd);

    // Try to get the output to flush...
    safe_write(fd, "\n[[System Info]]\n");
    safe_write(fd, "sysname: ");
    safe_write(fd, machine_info.sysname);
    safe_write(fd, "\n");
    safe_write(fd, "nodename: ");
    safe_write(fd, machine_info.nodename);
    safe_write(fd, "\n");
    safe_write(fd, "release: ");
    safe_write(fd, machine_info.release);
    safe_write(fd, "\n");
    safe_write(fd, "version: ");
    safe_write(fd, machine_info.version);
    safe_write(fd, "\n");
    safe_write(fd, "machine: ");
    safe_write(fd, machine_info.machine);
    safe_write(fd, "\n");

    // If we didn't write to stderr, then close the file down and
    // write info to stderr about reporting the error.
    if(fd != 2) {
      close(fd);
      safe_write(2, "\n---------------------------------------------\n");
      safe_write(2, "CRASH: A fatal error has occured.\n\nBacktrace:\n");
      backtrace_symbols_fd(array, size, 2);
      safe_write(2, "\n\n");
      safe_write(2, "Wrote full error report to: ");
      safe_write(2, report_path);
      safe_write(2, "\nRun 'rbx report' to submit this crash report!\n");
    }

    exit(100);
  }
示例#29
0
文件: bsys.c 项目: janstadler/bareos
void stack_trace()
{
   int ret, i;
   bool demangled_symbol;
   size_t stack_depth;
   size_t sz = 200; /* Just a guess, template names will go much wider */
   const size_t max_depth = 100;
   void *stack_addrs[100];
   char **stack_strings, *begin, *end, *j, *function;

   stack_depth = backtrace(stack_addrs, max_depth);
   stack_strings = backtrace_symbols(stack_addrs, stack_depth);

   for (i = 1; i < stack_depth; i++) {
      function = (char *)actuallymalloc(sz);
      begin = end = 0;
      /*
       * Find the single quote and address offset surrounding the mangled name
       */
      for (j = stack_strings[i]; *j; ++j) {
         if (*j == '\'') {
            begin = j;
         } else if (*j == '+') {
            end = j;
         }
      }
      if (begin && end) {
         *begin++ = '\0';
         *end = '\0';
         /*
          * Found our mangled name, now in [begin, end)
          */
         demangled_symbol = false;
         while (!demangled_symbol) {
            ret = cplus_demangle(begin, function, sz);
            switch (ret) {
            case DEMANGLE_ENAME:
               /*
                * Demangling failed, just pretend it's a C function with no args
                */
               strcat(function, "()");
               function[sz - 1] = '\0';
               demangled_symbol = true;
               break;
            case DEMANGLE_ESPACE:
               /*
                * Need more space for demangled function name.
                */
               actuallyfree(function);
               sz = sz * 2;
               function = (char *)actuallymalloc(sz);
               continue;
            default:
               demangled_symbol = true;
               break;
            }
         }
         Pmsg2(000, "    %s:%s\n", stack_strings[i], function);
      } else {
         /*
          * Didn't find the mangled name, just print the whole line
          */
         Pmsg1(000, "    %s\n", stack_strings[i]);
      }
      actuallyfree(function);
   }
   actuallyfree(stack_strings); /* malloc()ed by backtrace_symbols */
}
示例#30
0
//==============================================================================
std::vector <std::string>
getStackBacktrace()
{
    std::vector <std::string> result;

#if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD
    assert(false); // sorry, not implemented yet!

#elif BEAST_WINDOWS
    HANDLE process = GetCurrentProcess();
    SymInitialize (process, nullptr, TRUE);

    void* stack[128];
    int frames = (int) CaptureStackBackTrace (0,
        std::distance(std::begin(stack), std::end(stack)),
        stack, nullptr);

    // Allow symbols that are up to 1024 characters long.
    std::size_t constexpr nameLength = 1024;

    alignas(SYMBOL_INFO) unsigned char symbuf[
        sizeof(SYMBOL_INFO) + nameLength * sizeof(SYMBOL_INFO::Name)];

    auto symbol = reinterpret_cast<SYMBOL_INFO*>(symbuf);

    for (int i = 0; i < frames; ++i)
    {
        DWORD64 displacement = 0;

        std::memset (symbol, 0, sizeof(symbuf));

        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbol->MaxNameLen = nameLength;

        if (SymFromAddr (process, (DWORD64)stack[i], &displacement, symbol))
        {
            std::string frame;

            frame.append (std::to_string (i) + ": ");

            IMAGEHLP_MODULE64 moduleInfo { sizeof(moduleInfo) };

            if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
            {
                frame.append (moduleInfo.ModuleName);
                frame.append (": ");
            }

            frame.append (symbol->Name);

            if (displacement)
            {
                frame.append ("+");
                frame.append (std::to_string (displacement));
            }

            result.push_back (frame);
        }
    }

#else
    void* stack[128];
    int frames = backtrace (stack,
        std::distance(std::begin(stack), std::end(stack)));

    std::unique_ptr<char*[], decltype(std::free)*> frame {
        backtrace_symbols (stack, frames), std::free };

    for (int i = 0; i < frames; ++i)
        result.push_back (frame[i]);
#endif

    return result;
}