示例#1
0
Array stackTraceToBackTrace(const StackTrace& st) {
  std::vector<void*> bt_pointers;
  st.get(bt_pointers);
  Array ret;
  if (RuntimeOption::FullBacktrace) {
    for (unsigned int i = 0; i < bt_pointers.size(); i++) {
      StackTrace::FramePtr f = StackTrace::Translate(bt_pointers[i]);
      if (RuntimeOption::TranslateSource) {
        SourceInfo::TheSourceInfo.translate(f);
      }
      Array frame;
      frame.set("file",     String(f->filename));
      frame.set("line",     f->lineno);
      frame.set("function", String(f->funcname));
      frame.set("args",     "");
      frame.set("bt",       (int64)bt_pointers[i]);
      ret.append(frame);
    }
  } else {
    for (unsigned int i = 0; i < bt_pointers.size(); i++) {
      Array frame;
      frame.set("file",     "");
      frame.set("line",     0LL);
      frame.set("function", "");
      frame.set("args",     "");
      frame.set("bt",       (int64)bt_pointers[i]);
      ret.append(frame);
    }
    ret.set("bts", String(st.hexEncode()));
  }
  return ret;
}
示例#2
0
文件: Logger.cpp 项目: trasz/cbang
Logger::LogStream Logger::createStream(const string &_domain, int level,
                                       const std::string &_prefix) {
  string domain = simplifyDomain(_domain);

  if (enabled(domain, level)) {
    // Log date periodically
    uint64_t now = Time::now();
    if (logDatePeriodically && lastDate + logDatePeriodically <= now) {
      write(String::bar(Time(now, "Date: %Y-%m-%d").toString()) +
            (logCRLF ? "\r\n" : "\n"));
      lastDate = now;
    }

    string prefix = startColor(level) + getHeader(domain, level) + _prefix;
    string suffix = endColor(level);

    string trailer;
#ifdef HAVE_DEBUGGER
    if (domainTraces.find(domain) != domainTraces.end()) {
      StackTrace trace;
      Debugger::instance().getStackTrace(trace);
      for (int i = 0; i < 3; i++) trace.pop_front();
      trailer = SSTR(trace);
    }
#endif

    return new cb::LogStream(prefix, suffix, trailer);

  } else return new NullStream<>;
}
示例#3
0
static void LogStacktrace(const int logLevel, StackTrace& stacktrace)
{
	int colFileline = 0;
	const std::string& exe_path = Platform::GetProcessExecutablePath();
	const std::string& cwd_path = Platform::GetOrigCWD();
	for (auto fit = stacktrace.begin(); fit != stacktrace.end(); fit++) {
        for (auto eit = fit->entries.begin(); eit != fit->entries.end(); eit++) {
			eit->abbrev_funcname = eit->funcname;
			std::string fileline = eit->fileline;
			if (fileline[1] == '?') {  // case "??:?", ":?"
				fileline = fit->symbol;  // print raw backtrace_symbol
			}
			eit->abbrev_fileline = fileline;
			int abbrev_start = 0;
			if (fileline[0] == '/') { // See if we can shorten the file/line bit by removing the common path
				if (CommonStringLength(fileline, exe_path, &abbrev_start) > 1) { // i.e. one char for first '/'
					eit->abbrev_fileline = std::string(".../") + fileline.substr(abbrev_start, std::string::npos);
				} else if (CommonStringLength(fileline, cwd_path, &abbrev_start) > 1) {
					eit->abbrev_fileline = std::string("./") + fileline.substr(abbrev_start, std::string::npos);
				}
			}

			if (eit->abbrev_funcname.size() > 100) {
				eit->abbrev_funcname.resize(94);
				eit->abbrev_funcname.append(" [...]");
			}

			colFileline = std::max(colFileline, (int)eit->abbrev_fileline.length());
        }
    }

    bool hideSignalHandler = true;

    // Print out the translated StackTrace
    unsigned numLine = 0;
    unsigned hiddenLines = 0;
    while (numLine == 0) { // outer loop at most twice -- tries to find the signal handler once and if that doesn't work, then just print every frame
        for (auto fit = stacktrace.cbegin(); fit != stacktrace.cend(); fit++) {
            for (auto eit = fit->entries.begin(); eit != fit->entries.end(); eit++) {

                if (hideSignalHandler) {
                    hiddenLines++;
					if (eit->fileline.find("sigaction.c:?") == 0) {
                        hideSignalHandler = false;
                        LOG_I(logLevel, "(Signal handler calls suppressed [%d]. Inlined calls denoted by < > brackets.)", hiddenLines);
                    }
                    continue;
                }

                if (eit->inLine) {
					LOG_I(logLevel, "  <%02u> %*s  %s", fit->level, colFileline, eit->abbrev_fileline.c_str(), eit->abbrev_funcname.c_str());
                } else {
					LOG_I(logLevel, "[%02u]   %*s  %s", fit->level, colFileline, eit->abbrev_fileline.c_str(), eit->abbrev_funcname.c_str());
                }
                numLine++;
            }
        }
        hideSignalHandler = false;
    }
}
示例#4
0
String debug_string_backtrace(bool skip) {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt;
    StringBuffer buf;
    bt = g_vmContext->debugBacktrace(skip);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists(s_class)) {
        buf.append(frame->get(s_class).toString());
        buf.append(frame->get(s_type).toString());
      }
      buf.append(frame->get(s_function).toString());
      buf.append("()");
      if (frame.exists(s_file)) {
        buf.append(" called at [");
        buf.append(frame->get(s_file).toString());
        buf.append(':');
        buf.append(frame->get(s_line).toString());
        buf.append(']');
      }
      buf.append('\n');
    }
    return buf.detach();
  } else {
    StackTrace st;
    return String(st.toString());
  }
}
示例#5
0
void f_debug_print_backtrace() {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt = FrameInjection::GetBacktrace(true);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      StringBuffer buf;
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists("class")) {
        buf.append(frame->get("class").toString());
        buf.append(frame->get("type").toString());
      }
      buf.append(frame->get("function").toString());
      buf.append("()");
      if (frame.exists("file")) {
        buf.append(" called at [");
        buf.append(frame->get("file").toString());
        buf.append(':');
        buf.append(frame->get("line").toString());
        buf.append(']');
      }
      buf.append('\n');
      echo(buf.detach());
    }
  } else {
    StackTrace st;
    echo(String(st.toString()));
  }
}
示例#6
0
LONG WINAPI WindowsExceptionHandler(struct _EXCEPTION_POINTERS *exceptionInfo)
{
	LD_UNUSED_PARAMETER(exceptionInfo);

	LD_LOG(Platform, Error, "~~~~~~~~~~~~ UNHANDLED EXCEPTION OCCURRED ~~~~~~~~~~~");
	LD_LOG(Platform, Error, "Stack Trace:");

	StackTrace Trace;
	if (StackTrace::Generate(Trace, (void*)exceptionInfo).Failed())
	{
		LD_LOG(Platform, Error, "Failed to generate stack trace.");
		return 0;
	}
	else
	{
		for (int i = 0; i < Trace.FrameCount(); i++)
		{
			StackFrame Frame = Trace.GetFrame(i);
			if (Frame.Resolve().Failed())
			{
				LD_LOGF(Platform, Error, "[%i] 0x%p (Symbols Unresolved)", i, Frame.Address);
			}
			else
			{
				LD_LOGF(Platform, Error, "[%i] (%s:%i) %s", i, Frame.File.Data(), Frame.Line, Frame.Function.Data());
			}
		}
	}

	return EXCEPTION_EXECUTE_HANDLER;
}
示例#7
0
bool
ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
{
	TRACE_CONTROL("ThreadHandler::_HandleSingleStepStep(): ip: %llx\n",
		cpuState->InstructionPointer());

	switch (fStepMode) {
		case STEP_INTO:
		{
			// We continue stepping as long as we're in the statement.
			if (fStepStatement->ContainsAddress(cpuState->InstructionPointer())) {
				_SingleStepThread(cpuState->InstructionPointer());
				return true;
			}

			StackTrace* stackTrace = fThread->GetStackTrace();
			BReference<StackTrace> stackTraceReference(stackTrace);

			if (stackTrace == NULL && cpuState != NULL) {
				if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
						fThread->GetTeam(), this, cpuState, stackTrace) == B_OK) {
					stackTraceReference.SetTo(stackTrace, true);
				}
			}

			if (stackTrace != NULL) {
				StackFrame* frame = stackTrace->FrameAt(0);
				Image* image = frame->GetImage();
				ImageDebugInfo* info = NULL;
				if (GetImageDebugInfo(image, info) != B_OK)
					return false;

				BReference<ImageDebugInfo>(info, true);
				if (info->GetAddressSectionType(
						cpuState->InstructionPointer())
						== ADDRESS_SECTION_TYPE_PLT) {
					_SingleStepThread(cpuState->InstructionPointer());
					return true;
				}
			}
			return false;
		}

		case STEP_OVER:
		{
			// If we have stepped out of the statement, we're done.
			if (!fStepStatement->ContainsAddress(cpuState->InstructionPointer()))
				return false;
			return _DoStepOver(cpuState);
		}

		case STEP_OUT:
			// We never single-step in this case.
		default:
			return false;
	}
}
//! @brief is called when the app crashes
void SpringLobbyApp::OnFatalException()
{
	wxLogError("Fatal exception!");

	StackTrace stackTracer;
	stackTracer.WalkFromException();
	auto trace = stackTracer.GetStackTrace();

	wxLogError("Stack trace: " + trace);	
}
示例#9
0
void print_backtrace(std::size_t frames = 32)
{
    using namespace backward;
    StackTrace stackTrace;
    Printer printer;

    stackTrace.load_here(frames);
    printer.object = true;
    printer.color = true;
    printer.print(stackTrace, stdout);
}
示例#10
0
LockProfiler::~LockProfiler() {
  if (m_profiling) {
    timespec unlockTime;
    Timer::GetMonotonicTime(unlockTime);
    time_t dsec = unlockTime.tv_sec - m_lockTime.tv_sec;
    long dnsec = unlockTime.tv_nsec - m_lockTime.tv_nsec;
    int64_t dusec = dsec * 1000000 + dnsec / 1000;

    StackTrace st;
    s_pfunc_profile(st.hexEncode(3, 9), dusec);
  }
}
示例#11
0
status_t
DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output,
	::Thread* thread)
{
	AutoLocker< ::Team> locker;
	if (thread->State() != THREAD_STATE_STOPPED)
		return B_OK;

	StackTrace* trace = NULL;
	for (;;) {
		trace = thread->GetStackTrace();
		if (trace != NULL)
			break;

		locker.Unlock();
		status_t result = acquire_sem(fTeamDataSem);
		if (result != B_OK)
			return result;

		locker.Lock();
	}

	_output << "\t\tFrame\t\tIP\t\t\tFunction Name\n";
	_output << "\t\t-----------------------------------------------\n";
	BString data;
	for (int32 i = 0; StackFrame* frame = trace->FrameAt(i); i++) {
		char functionName[512];
		data.SetToFormat("\t\t%#08" B_PRIx64 "\t%#08" B_PRIx64 "\t%s\n",
			frame->FrameAddress(), frame->InstructionPointer(),
			UiUtils::FunctionNameForFrame(frame, functionName,
				sizeof(functionName)));

		_output << data;
	}

	_output << "\n\t\tRegisters:\n";

	CpuState* state = thread->GetCpuState();
	BVariant value;
	const Register* reg = NULL;
	for (int32 i = 0; i < fArchitecture->CountRegisters(); i++) {
		reg = fArchitecture->Registers() + i;
		state->GetRegisterValue(reg, value);

		char buffer[64];
		data.SetToFormat("\t\t\t%5s:\t%s\n", reg->Name(),
			UiUtils::VariantToString(value, buffer, sizeof(buffer)));
		_output << data;
	}

	return B_OK;
}
示例#12
0
	/**
	 *
     * This entry point is tailored for the Watchdog module.
     * Since the thread to be traced may be running, it requires a ThreadControls object in order to suspend/resume the thread.
     * @brief RemoteStacktrace
     */
    void SuspendedStacktrace(Threading::ThreadControls* ctls, const std::string& threadName)
    {
#if !(DEDICATED || UNIT_TEST)
        Watchdog::ClearTimer();
#endif
        assert(ctls != nullptr);
        assert(ctls->handle != 0);
        assert(threadName.size() > 0);

        LOG_L(L_WARNING, "Suspended-thread Stacktrace (%s) for Spring %s:", threadName.c_str(), (SpringVersion::GetFull()).c_str());

        LOG_L(L_DEBUG, "SuspendedStacktrace[1]");

        StackTrace stacktrace;

        // Get untranslated stacktrace symbols
        {
            // process and analyse the raw stack trace
            void* iparray[MAX_STACKTRACE_DEPTH];

			ctls->Suspend();

			const int numLines = thread_unwind(&ctls->ucontext, iparray, stacktrace);

			ctls->Resume();

            LOG_L(L_DEBUG, "SuspendedStacktrace[2]");

            if(numLines > MAX_STACKTRACE_DEPTH) {
                LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
            }
            char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

            ExtractSymbols(lines, stacktrace);
        }

        if (stacktrace.empty()) {
            LOG_L(L_WARNING, "  Unable to create suspended stacktrace");
            return;
        }

        LOG_L(L_DEBUG, "SuspendedStacktrace[3]");

        // Translate symbols into code line numbers
        TranslateStackTrace(NULL, stacktrace, LOG_LEVEL_WARNING);

        LOG_L(L_DEBUG, "SuspendedStacktrace[4]");

        // Print out the translated StackTrace
        LogStacktrace(LOG_LEVEL_WARNING, stacktrace);

    }
示例#13
0
String debug_string_backtrace(bool skip, bool ignore_args /* = false */,
                              int limit /* = 0 */) {
  if (RuntimeOption::InjectedStackTrace) {
    Array bt;
    StringBuffer buf;
    bt = g_context->debugBacktrace(skip, false, false, nullptr,
                                     ignore_args, limit);
    int i = 0;
    for (ArrayIter it = bt.begin(); !it.end(); it.next(), i++) {
      Array frame = it.second().toArray();
      buf.append('#');
      buf.append(i);
      if (i < 10) buf.append(' ');
      buf.append(' ');
      if (frame.exists(s_class)) {
        buf.append(frame->get(s_class).toString());
        buf.append(frame->get(s_type).toString());
      }
      buf.append(frame->get(s_function).toString());
      buf.append("(");
      if (!ignore_args) {
        bool first = true;
        for (ArrayIter it = frame->get(s_args).begin(); !it.end(); it.next()) {
          if (!first) {
            buf.append(", ");
          } else {
            first = false;
          }
          try {
            buf.append(it.second().toString());
          } catch (FatalErrorException& fe) {
            buf.append(fe.getMessage());
          }
        }
      }
      buf.append(")");
      if (frame.exists(s_file)) {
        buf.append(" called at [");
        buf.append(frame->get(s_file).toString());
        buf.append(':');
        buf.append(frame->get(s_line).toString());
        buf.append(']');
      }
      buf.append('\n');
    }
    return buf.detach();
  } else {
    StackTrace st;
    return String(st.toString());
  }
}
示例#14
0
void HeapProfiler::malloc(void *ptr, size_t size, const StackTrace &trace){
	std::lock_guard<std::mutex> lk(mutex);
	fprintf(data.output, "+ %lx %lx %lx\n", size, trace.index(), reinterpret_cast<uintptr_t>(ptr));
	data.tick();
	// Store the stracktrace hash of this allocation in the pointers map.
	ptrs[ptr] = trace.hash;
}
示例#15
0
/**
 * Consumes (and frees) the lines produced by backtrace_symbols and puts these into the StackTrace fields
 */
static void ExtractSymbols(char** lines, StackTrace& stacktrace)
{
	int l=0;
	auto fit = stacktrace.begin();
	while (fit != stacktrace.end()) {
		LOG_L(L_DEBUG, "backtrace_symbols: %s", lines[l]);
		if (strncmp(lines[l], "[(nil)]", 20) != 0) {
			fit->symbol = lines[l];
			fit++;
		} else {
			fit = stacktrace.erase(fit);
		}
		l++;
	}
	free(lines);
}
示例#16
0
void RequestError::segfault(Request* request, Exceptions::Segfault& e)
{
	std::cerr << std::endl
	          << "        \033[31;1m******** SEGMENTATION FAULT ********\033[0m"
	          << std::endl << std::endl
	          << "WebCpp received a SIGSEGV signal: segmentation fault."
	          << std::endl << std::endl
	          << "This should never happen. Please file a bug to the WebCpp's "
	          << std::endl << "developers on <http://bugs.webcpp.org/>."
	          << std::endl << std::endl
	          << "\033[33;1m*** STACK TRACE ***\033[0m" << std::endl << std::endl;

	StackTrace* trace = new StackTrace(2);
	List<StackTrace::Frame> frames = trace->stackFrames();
	int i = 0, iLen = std::ceil(std::log10(frames.count()));
	for (const StackTrace::Frame& frame : frames)
	{
		std::cerr << "  " << std::setw(iLen) << i++ << ". "
		          << "\033[34;1m" << frame.function << "\033[0m"
		          << " + 0x" << String::fromNumber(frame.functionOffset, 16)
		          << " @ 0x" << String::fromNumber(frame.address, 16)
		          << std::endl << std::setw(iLen + 6) << " "
		          << "Sources/System.cpp line 112"
		          << " (from " << frame.object.absolutePath() << ")" << std::endl;
	}
	delete trace;
	std::cerr << std::endl;

	try
	{
		View tpl = new Template("Sys::Segfault.html", nullptr, request);

		tpl["webcppVersion"] = System::get()->version();
		tpl["serverName"] = request->env("SERVER_NAME", "");
		loadStackTrace(e, dynamic_cast<Template*>(*tpl));

		if (!request->headersSent())
			request->setStatus(500);
		tpl->render();
	}
	catch (const Exception& e2)
	{ fallbackErrorPage(request, e, e2.type()); }
	catch (const std::exception& e2)
	{ fallbackErrorPage(request, e2, typeid(e2).name()); }
}
示例#17
0
    /**
     * This stack trace is tailored for the SIGSEGV / SIGILL / SIGFPE etc signal handler.
     * The thread to be traced is usually in a halted state, but the signal handler can provide siginfo_t and ucontext_t structures to help produce the trace using libunwind.
     * @brief PrepareStacktrace
     */
    void HaltedStacktrace(const std::string& errstr, siginfo_t* siginfo, ucontext_t* ucontext)
    {
        LOG_L(L_ERROR, "Halted Stacktrace for Spring %s using libunwind:", (SpringVersion::GetFull()).c_str());

        assert(siginfo != nullptr);
        assert(ucontext != nullptr);

        StackTrace stacktrace;

        LOG_L(L_DEBUG, "HaltedStacktrace[1]");

        // Get untranslated stacktrace symbols
        {
            // process and analyse the raw stack trace
            void* iparray[MAX_STACKTRACE_DEPTH];

            const int numLines = thread_unwind(nullptr, iparray, stacktrace);

            LOG_L(L_DEBUG, "HaltedStacktrace[2]");

            if(numLines > MAX_STACKTRACE_DEPTH) {
                LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
            }

            char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

            ExtractSymbols(lines, stacktrace);
        }

        LOG_L(L_DEBUG, "HaltedStacktrace[3]");

        if (stacktrace.empty()) {
            LOG_I(LOG_LEVEL_ERROR, "  Unable to create stacktrace");
            return;
        }

        // Translate it
        TranslateStackTrace(NULL, stacktrace, LOG_LEVEL_ERROR);

        LOG_L(L_DEBUG, "HaltedStacktrace[4]");

        // Print out the translated StackTrace. Ignore the frames that occur inside the signal handler (before its line in the trace) -- they are likely some kind of padding or just garbage.
        LogStacktrace(LOG_LEVEL_ERROR, stacktrace);
    }
示例#18
0
void
CliStackTraceCommand::Execute(int argc, const char* const* argv,
	CliContext& context)
{
	// get the current thread
	Team* team = context.GetTeam();
	AutoLocker<Team> teamLocker(team);
	Thread* thread = context.CurrentThread();
	if (thread == NULL) {
		printf("no current thread\n");
		return;
	}

	if (thread->State() != THREAD_STATE_STOPPED) {
		printf("Current thread is not stopped. Can't get stack trace.\n");
		return;
	}

	// get its stack trace
	StackTrace* stackTrace = thread->GetStackTrace();
	while (stackTrace == NULL) {
		context.WaitForEvents(CliContext::EVENT_THREAD_STACK_TRACE_CHANGED);
		if (context.IsTerminating())
			return;
		stackTrace = thread->GetStackTrace();
	}
	BReference<StackTrace> stackTraceReference(stackTrace);
		// hold a reference until we're done

	teamLocker.Unlock();

	// print the stack trace
	int32 frameCount = stackTrace->CountFrames();
	for (int32 i = 0; i < frameCount; i++) {
		StackFrame* frame = stackTrace->FrameAt(i);
		printf("%3" B_PRId32 "  %#" B_PRIx64 "  %#" B_PRIx64, i,
			(uint64)frame->FrameAddress(), (uint64)frame->InstructionPointer());

		char functionName[512];
		UiUtils::FunctionNameForFrame(frame, functionName,
			sizeof(functionName));
		printf("  %s\n", functionName);
	}
}
示例#19
0
static inline bool
get_frame_reg(StackTrace& trace, size_t regIndex, reg_t& r)
{
    switch (regIndex)
    {
    case PT_R1:
        r = CHKPTR(trace.selection())->stack_pointer();
        return true;

    case PT_R31:
        r = CHKPTR(trace.selection())->frame_pointer();
        return true;

    case PT_NIP:
        r = CHKPTR(trace.selection())->program_count();
        return true;
    }
    return false;
}
示例#20
0
void StructuredLogEntry::setStackTrace(folly::StringPiece key,
                                       const StackTrace& st) {
  std::vector<folly::StringPiece> stackFrames;
  folly::split("\n", st.toString(), stackFrames);
  for (auto& frame : stackFrames) {
    const char* p = frame.begin();
    while (*p == '#' || *p == ' ' || (*p >= '0' && *p <= '9')) ++p;
    frame = folly::StringPiece(p, frame.end());
  }
  setVec(key, stackFrames);
}
示例#21
0
void SimpleCounter::Count(const string &name) {
  if (Enabled) {
    int count = ++s_counter->m_counters[name];
    if (SampleStackCount > 0) {
      assert(StackTrace::Enabled);
      vector<string> &stackVec = s_counter->m_stacks[name];
      if ((int)stackVec.size() < SampleStackCount ||
          f_rand(0, count - 1) < SampleStackCount) {
        StackTrace st;
        if ((int)stackVec.size() < SampleStackCount) {
          // skip StackTrace methods and the Count() call.
          stackVec.push_back(st.hexEncode(3, 3 + SampleStackDepth));
        } else {
          // skip StackTrace methods and the Count() call.
          stackVec[f_rand(0, SampleStackCount - 1)] =
            st.hexEncode(3, 3 + SampleStackDepth);
        }
      }
    }
  }
}
示例#22
0
void StackTraceImpl::copy_symbols(const StackTrace& other)
{
    // todo: work it from the bottom, and break out of
    // the loop as soon as the frames don't match

    const size_t n = std::min(frames_.size(), other.size());

    for (size_t i = 0; i != n; ++i)
    {
        Frame* f = other.frame(i);
        Frame* g = frames_[i].get();

        if (f->program_count() != g->program_count())
        {
            continue;
        }

        if (Symbol* sym = f->function(no_symbol))
        {
            g->function(sym);
        }
    }
}
示例#23
0
	static void Stacktrace(bool* aiCrash, pthread_t* hThread = NULL, const char* threadName = NULL, const int logLevel = LOG_LEVEL_ERROR)
	{
#if !(DEDICATED || UNIT_TEST)
		Watchdog::ClearTimer();
#endif

		if (threadName != NULL) {
			LOG_I(logLevel, "Stacktrace (%s) for Spring %s:", threadName, (SpringVersion::GetFull()).c_str());
		} else {
			LOG_I(logLevel, "Stacktrace for Spring %s:", (SpringVersion::GetFull()).c_str());
		}

		StackTrace stacktrace;

		// Get untranslated stacktrace symbols
		{
			// process and analyse the raw stack trace
			void* iparray[MAX_STACKTRACE_DEPTH];
			int numLines = thread_unwind(nullptr, iparray, stacktrace);
			if (numLines > MAX_STACKTRACE_DEPTH) {
				LOG_L(L_ERROR, "thread_unwind returned more lines than we allotted space for!");
			}
			char** lines = backtrace_symbols(iparray, numLines); // give them meaningfull names

			ExtractSymbols(lines, stacktrace);
		}

		if (stacktrace.empty()) {
			LOG_I(logLevel, "  Unable to create stacktrace");
			return;
		}

		// Translate it
		TranslateStackTrace(aiCrash, stacktrace, logLevel);

		LogStacktrace(logLevel, stacktrace);
	}
示例#24
0
LockProfiler::~LockProfiler() {
  if (m_profiling) {
#if defined(__APPLE__)
    timeval unlockTime;
    unlockTime.tv_sec = 0;
    unlockTime.tv_usec = 0;
    gettimeofday(&unlockTime, NULL);
    time_t dsec = unlockTime.tv_sec - m_lockTime.tv_sec;
    long dnsec = unlockTime.tv_usec - m_lockTime.tv_usec;
    int64 dusec = dsec * 1000000 + dnsec;
#else
    timespec unlockTime;
    unlockTime.tv_sec = 0;
    unlockTime.tv_nsec = 0;
    clock_gettime(CLOCK_MONOTONIC, &unlockTime);
    time_t dsec = unlockTime.tv_sec - m_lockTime.tv_sec;
    long dnsec = unlockTime.tv_nsec - m_lockTime.tv_nsec;
    int64 dusec = dsec * 1000000 + dnsec / 1000;
#endif

    StackTrace st;
    s_pfunc_profile(st.hexEncode(3, 9), dusec);
  }
}
示例#25
0
    void CrashReport::GenerateReport(EXCEPTION_POINTERS* p)
#endif
{
    wxLogMessage( _T( "Report generated in " ) );
	CwdGuard cwgGuard( wxFileName::GetTempDir() );
	NetDebugReport* report = new NetDebugReport( "http://debug.springlobby.info/upload" ) ;
//	NetDebugReport* report = new NetDebugReport( "http://localhost/upload" ) ;

	// add all standard files: currently this means just a minidump and an
	// XML file with system info and stack trace
	report->AddAll(  );

	wxString dir = report->GetDirectory();

	wxString SystemInfos;

	SystemInfos += _T( "SpringLobby version " ) + TowxString(GetSpringLobbyVersion()) + _T( "\n" ) ;
	SystemInfos += _T( "Built from " ) + wxString( wxVERSION_STRING ) + _T(" on ") + wxPlatformInfo::Get().GetOperatingSystemIdName() + _T( "\n" ) ;

	report->AddText( _T( "SystemInfos.txt" ), SystemInfos, _( "System informations" ) );
#if wxUSE_STD_IOSTREAM
	report->AddText( _T( "AppLog.txt" ), TowxString( crashlog.str() ), _( "Application verbose log" ) );
#endif
    wxString script_file = TowxString(SlPaths::GetDataDir()) + wxFileName::GetPathSeparator() + _T("script.txt");
    if ( wxFile::Exists( script_file ) )
        report->AddFile( script_file, _( "Last generated spring launching script" ) );

#if wxUSE_STACKWALKER && !__WXMSW__
    StackTrace stacktrace;
	stacktrace.Walk( 3, 20 );
	report->AddText( _T( "stacktrace.txt" ), _T("Call stack:\n") + stacktrace.GetStackTrace(), _( "StackTrace" ) );
#else
	wxString report_fn = ( wxGetCwd() + wxFileName::GetPathSeparator() + _T("stacktrace.txt") );
	if ( wxFile::Exists( report_fn ) )
		wxRemoveFile( report_fn );
	wxCharBuffer report_fn_char = report_fn.mb_str();
	DrMingwGenerateStacktrace( p, (const char*)report_fn_char );
	report->AddFile( report_fn, _( "StackTrace" ) );
#endif

	wxString SlBuildFlags;
	#ifdef DISABLE_SOUND
		SlBuildFlags += _T("sound=0");
	#else
		SlBuildFlags += _T("sound=1");
	#endif
	report->AddText( _T("buildflags.txt"), SlBuildFlags, _T("BuildFlags") );

	report->AddText( _T("nick.txt"),
		sett().GetServerAccountNick( sett().GetDefaultServer() ), _T("Nick") );

	wxDebugReportPreviewStd* bkl = new wxDebugReportPreviewStd();
	// calling Show() is not mandatory, but is more polite
	if ( bkl->Show( *report ) ) {
		if ( report->Process() ) {
			wxLogMessage( _T( "Report successfully uploaded." ) );
		}
		else {
				wxLogMessage( _T( "Report generated in \"%s\", but failed to upload" ), report->GetCompressedFileName().c_str() );
				report->Reset();
				wxLogMessage( _T("report reset") );
		}
	}
	//else: user cancelled the report

	delete report;
	wxLogMessage( _T("deleted report") );
}
示例#26
0
	/**
	 * This is used to obtain the list of symbols using a ucontext_t structure.
	 * So, it is used by both the HaltedStacktrace and the SuspendedStacktrace.
	 * Since this method is pure implementation, it's
	 */
	int thread_unwind(ucontext_t* uc, void** iparray, StackTrace& stacktrace)
	{
		assert(iparray != nullptr);
		assert(&stacktrace != nullptr);

		unw_cursor_t cursor;
		// Effective ucontext_t. If uc not supplied, use unw_getcontext locally. This is appropriate inside signal handlers.
#if defined(__APPLE__)
		unw_context_t thisctx;
		unw_getcontext(&thisctx);
#else
		ucontext_t thisctx;
		if (uc == nullptr) {
			unw_getcontext(&thisctx);
			uc = &thisctx;
		}
#endif
		const int BUFR_SZ = 1000;
		char procbuffer[BUFR_SZ];
		stacktrace.clear();
		stacktrace.reserve(120);
		/*
		 * Note: documentation seems to indicate that uc_link contains a pointer to a "successor" context
		 * that is to be resumed after the current one (as you might expect in a signal handler).
		 * In practice however, the Linux OS seems to re-use the existing context of a thread, and so this approach
		 * does not work. The uc_link is sometimes non-NULL however, but I do not know what the relation is to the
		 * target context (uc).
		 *
		while (uc->uc_link) {
			uc = uc->uc_link;
			LOG_L(L_DEBUG, "Dereferencing uc_link");
		}
		*/
#if defined(__APPLE__)
		int err = unw_init_local(&cursor, &thisctx);
#else
		int err = unw_init_local(&cursor, uc);
#endif
		if (err) {
			LOG_L(L_ERROR, "unw_init_local returned %d", err);
			return 0;
		}
		int i=0;
		while (i < MAX_STACKTRACE_DEPTH && unw_step(&cursor)) {
			StackFrame frame;
			unw_word_t ip;
			unw_word_t offp;
			unw_get_reg(&cursor, UNW_REG_IP, &ip);
			frame.ip = reinterpret_cast<void*>(ip);
			frame.level = i;
			iparray[i] = frame.ip;
			if (!unw_get_proc_name(&cursor, procbuffer, BUFR_SZ-1, &offp)) {
				frame.mangled = std::string(procbuffer);
			} else {
				frame.mangled = std::string("UNW_ENOINFO");
			}
			stacktrace.push_back(frame);
			i++;
		}
		stacktrace.resize(i);
		LOG_L(L_DEBUG, "thread_unwind returned %d frames", i);
		return i;
	}
示例#27
0
status_t
Architecture::CreateStackTrace(Team* team,
                               ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
                               StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace)
{
    BReference<CpuState> cpuStateReference(cpuState);

    StackTrace* stackTrace = NULL;
    ObjectDeleter<StackTrace> stackTraceDeleter;
    StackFrame* frame = NULL;

    if (useExistingTrace)
        stackTrace = _stackTrace;
    else {
        // create the object
        stackTrace = new(std::nothrow) StackTrace;
        if (stackTrace == NULL)
            return B_NO_MEMORY;
        stackTraceDeleter.SetTo(stackTrace);
    }

    // if we're passed an already existing partial stack trace,
    // attempt to continue building it from where it left off.
    if (stackTrace->CountFrames() > 0) {
        frame = stackTrace->FrameAt(stackTrace->CountFrames() - 1);
        cpuState = frame->GetCpuState();
    }

    while (cpuState != NULL) {
        // get the instruction pointer
        target_addr_t instructionPointer = cpuState->InstructionPointer();
        if (instructionPointer == 0)
            break;

        // get the image for the instruction pointer
        AutoLocker<Team> teamLocker(team);
        Image* image = team->ImageByAddress(instructionPointer);
        BReference<Image> imageReference(image);
        teamLocker.Unlock();

        // get the image debug info
        ImageDebugInfo* imageDebugInfo = NULL;
        if (image != NULL)
            imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
        BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo,
                true);

        // get the function
        teamLocker.Lock();
        FunctionInstance* function = NULL;
        FunctionDebugInfo* functionDebugInfo = NULL;
        if (imageDebugInfo != NULL) {
            function = imageDebugInfo->FunctionAtAddress(instructionPointer);
            if (function != NULL)
                functionDebugInfo = function->GetFunctionDebugInfo();
        }
        BReference<FunctionInstance> functionReference(function);
        teamLocker.Unlock();

        // If the CPU state's instruction pointer is actually the return address
        // of the next frame, we let the architecture fix that.
        if (frame != NULL
                && frame->ReturnAddress() == cpuState->InstructionPointer()) {
            UpdateStackFrameCpuState(frame, image,
                                     functionDebugInfo, cpuState);
        }

        // create the frame using the debug info
        StackFrame* previousFrame = NULL;
        CpuState* previousCpuState = NULL;
        if (function != NULL) {
            status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
                             ->CreateFrame(image, function, cpuState, previousFrame,
                                           previousCpuState);
            if (error != B_OK && error != B_UNSUPPORTED)
                break;
        }

        // If we have no frame yet, let the architecture create it.
        if (previousFrame == NULL) {
            status_t error = CreateStackFrame(image, functionDebugInfo,
                                              cpuState, frame == NULL, previousFrame, previousCpuState);
            if (error != B_OK)
                break;
        }

        cpuStateReference.SetTo(previousCpuState, true);

        previousFrame->SetImage(image);
        previousFrame->SetFunction(function);

        if (!stackTrace->AddFrame(previousFrame)) {
            delete previousFrame;
            return B_NO_MEMORY;
        }

        frame = previousFrame;
        cpuState = previousCpuState;
        if (--maxStackDepth == 0)
            break;
    }

    stackTraceDeleter.Detach();
    _stackTrace = stackTrace;
    return B_OK;
}
示例#28
0
void
ThreadHandler::HandleThreadAction(uint32 action, target_addr_t address)
{
	AutoLocker<Team> locker(fThread->GetTeam());

	if (fThread->State() == THREAD_STATE_UNKNOWN)
		return;

	// When stop is requested, thread must be running, otherwise stopped.
	if (action == MSG_THREAD_STOP
			? fThread->State() != THREAD_STATE_RUNNING
			: fThread->State() != THREAD_STATE_STOPPED) {
		return;
	}

	// When stepping we need a stack trace. Save it before unsetting the state.
	CpuState* cpuState = fThread->GetCpuState();
	StackTrace* stackTrace = fThread->GetStackTrace();
	BReference<CpuState> cpuStateReference(cpuState);
	BReference<StackTrace> stackTraceReference(stackTrace);

	if (action == MSG_THREAD_SET_ADDRESS) {
		_HandleSetAddress(cpuState, address);
		return;
	}

	// When continuing the thread update thread state before actually issuing
	// the command, since we need to unlock.
	if (action != MSG_THREAD_STOP) {
		_SetThreadState(THREAD_STATE_RUNNING, NULL, THREAD_STOPPED_UNKNOWN,
			BString());
	}

	locker.Unlock();

	switch (action) {
		case MSG_THREAD_RUN:
			fStepMode = address != 0 ? STEP_UNTIL : STEP_NONE;
			if (address != 0)
				_InstallTemporaryBreakpoint(address);
			_RunThread(0);
			return;
		case MSG_THREAD_STOP:
			fStepMode = STEP_NONE;
			if (fDebuggerInterface->StopThread(ThreadID()) == B_OK)
				fThread->SetStopRequestPending();
			return;
		case MSG_THREAD_STEP_OVER:
		case MSG_THREAD_STEP_INTO:
		case MSG_THREAD_STEP_OUT:
			break;
	}

	TRACE_CONTROL("ThreadHandler::HandleThreadAction(MSG_THREAD_STEP_*)\n");

	// We want to step. We need a stack trace for that purpose. If we don't
	// have one yet, get it. Start with the CPU state.
	if (stackTrace == NULL && cpuState == NULL) {
		if (fDebuggerInterface->GetCpuState(fThread->ID(), cpuState) == B_OK)
			cpuStateReference.SetTo(cpuState, true);
	}

	if (stackTrace == NULL && cpuState != NULL) {
		if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
				fThread->GetTeam(), this, cpuState, stackTrace, NULL, 1,
				false, false) == B_OK) {
			stackTraceReference.SetTo(stackTrace, true);
		}
	}

	if (stackTrace == NULL || stackTrace->CountFrames() == 0) {
		_StepFallback();
		return;
	}

	StackFrame* frame = stackTrace->FrameAt(0);

	TRACE_CONTROL("  ip: %#" B_PRIx64 "\n", frame->InstructionPointer());

	target_addr_t frameIP = frame->GetCpuState()->InstructionPointer();
	// When the thread is in a syscall, do the same for all step kinds: Stop it
	// when it returns by means of a breakpoint.
	if (frame->Type() == STACK_FRAME_TYPE_SYSCALL) {
		// set a breakpoint at the CPU state's instruction pointer (points to
		// the return address, unlike the stack frame's instruction pointer)
// TODO: This is doesn't work correctly anymore. When stepping over a "syscall"
// instruction the thread is stopped twice. The after the first step the PC is
// incorrectly shown at the "syscall" instruction. Then we step again and are
// stopped at the temporary breakpoint after the "syscall" instruction. There
// are two problems. The first one is that we don't (cannot?) discriminate
// between the thread being in a syscall (like in a blocking syscall) and the
// thread having been stopped (or singled-stepped) at the end of the syscall.
// The second issue is that the temporary breakpoint is probably not necessary
// anymore, since single-stepping over "syscall" instructions should just work
// as expected.
		status_t error = _InstallTemporaryBreakpoint(frameIP);
		if (error != B_OK) {
			_StepFallback();
			return;
		}

		fStepMode = STEP_OUT;
		_RunThread(frameIP);
		return;
	}

	// For "step out" just set a temporary breakpoint on the return address.
	if (action == MSG_THREAD_STEP_OUT) {
		status_t error = _InstallTemporaryBreakpoint(frame->ReturnAddress());
		if (error != B_OK) {
			_StepFallback();
			return;
		}
		fPreviousInstructionPointer = frameIP;
		fPreviousFrameAddress = frame->FrameAddress();
		fStepMode = STEP_OUT;
		_RunThread(frameIP);
		return;
	}

	// For "step in" and "step over" we also need the source code statement at
	// the current instruction pointer.
	fStepStatement = _GetStatementAtInstructionPointer(frame);
	if (fStepStatement == NULL) {
		_StepFallback();
		return;
	}

	TRACE_CONTROL("  statement: %#" B_PRIx64 " - %#" B_PRIx64 "\n",
		fStepStatement->CoveringAddressRange().Start(),
		fStepStatement->CoveringAddressRange().End());

	if (action == MSG_THREAD_STEP_INTO) {
		// step into
		fStepMode = STEP_INTO;
		_SingleStepThread(frameIP);
	} else {
		fPreviousFrameAddress = frame->FrameAddress();
		// step over
		fStepMode = STEP_OVER;
		if (!_DoStepOver(frame->GetCpuState()))
			_StepFallback();
	}
}
bool BacktraceDebugger::getStackTrace(StackTrace &trace) {
  init(); // Might set enabled false
  if (!enabled) return false;

  void *stack[maxStack];
  int n = backtrace(stack, maxStack);
  SmartPointer<char *>::Malloc symbols = backtrace_symbols(stack, n);

#ifdef VALGRIND_MAKE_MEM_DEFINED
  (void)VALGRIND_MAKE_MEM_DEFINED(stack, n * sizeof(void *));
#endif // VALGRIND_MAKE_MEM_DEFINED

  SmartLock lock(this);

  for (int i = 0; i < n; i++) {
    bfd_vma pc = (bfd_vma)stack[i];

    const char *filename = 0;
    const char *function = 0;
    unsigned line = 0;

    // Find section
    asection *section = 0;
    for (asection *s = p->abfd->sections; s; s = s->next) {
      if ((bfd_get_section_flags(p->abfd, s) & SEC_CODE) == 0)
        continue;

      bfd_vma vma = bfd_get_section_vma(p->abfd, s);
      if (pc < vma) {
        section = s->prev;
        break;
      }
    }

    if (section) {
      bfd_vma vma = bfd_get_section_vma(p->abfd, section);
      bfd_find_nearest_line(p->abfd, section, p->syms, pc - vma,
                            &filename, &function, &line);

#ifdef VALGRIND_MAKE_MEM_DEFINED
      if (filename) (void)VALGRIND_MAKE_MEM_DEFINED(filename, strlen(filename));
      if (function) (void)VALGRIND_MAKE_MEM_DEFINED(function, strlen(function));
      (void)VALGRIND_MAKE_MEM_DEFINED(&line, sizeof(line));
#endif // VALGRIND_MAKE_MEM_DEFINED
    }

    // Fallback to backtrace symbols
    if ((!function || !filename) && symbols.get()) {
      char *sym = symbols[i];

      // Parse symbol string
      // Expected format: <module>(<function>+0x<offset>)
      char *ptr = sym;
      while (*ptr && *ptr != '(') ptr++;
      if (*ptr == '(') {
        *ptr++ = 0;
        if (!filename) filename = sym; // Not really the source file

        if (!function) {
          function = ptr;
          while (*ptr && *ptr != '+') ptr++;

          if (*ptr) {
            *ptr++ = 0;
            char *offset = ptr;
            while (*ptr && *ptr != ')') ptr++;
            if (*ptr == ')') *ptr = 0;

            int save_errno = errno;
            errno = 0;
            line = strtol(offset, 0, 0); // Byte offset not line number
            if (errno) line = 0;
            errno = save_errno;
          }
        }
      }
    }

    // Filename
    if (!filename) filename = "";
    else if (0 <= parents) {
      const char *ptr = filename + strlen(filename);
      for (int j = 0; j <= parents; j++)
        while (filename < ptr && *--ptr != '/') continue;

      if (*ptr == '/') filename = ptr + 1;
    }

    // Function name
    char *demangled = 0;
    if (!function) function = "";
    else {
      int status = 0;
      demangled = abi::__cxa_demangle(function, 0, 0, &status);
      if (!status && demangled) function = demangled;
    }

    trace.push_back
      (StackFrame(stack[i], FileLocation(filename, function, line)));

    if (demangled) free(demangled);
  }

  return true;
}
示例#30
0
bool
ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
{
	// in any case uninstall the temporary breakpoint
	_UninstallTemporaryBreakpoint();

	switch (fStepMode) {
		case STEP_OVER:
		{
			StackTrace* stackTrace = fThread->GetStackTrace();
			BReference<StackTrace> stackTraceReference(stackTrace);

			if (stackTrace == NULL && cpuState != NULL) {
				if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
						fThread->GetTeam(), this, cpuState, stackTrace, NULL,
						1, false, false) == B_OK) {
					stackTraceReference.SetTo(stackTrace, true);
				}
			}
			if (stackTrace != NULL) {
				StackFrame* frame = stackTrace->FrameAt(0);
				// If we're not in the same frame we started in,
				// keep executing.
				if (frame != NULL && fPreviousFrameAddress
						!= frame->FrameAddress()) {
					status_t error = _InstallTemporaryBreakpoint(
						cpuState->InstructionPointer());
					if (error != B_OK)
						_StepFallback();
					else
						_RunThread(cpuState->InstructionPointer());
					return true;
				}
			}

			if (fPreviousFrameAddress != 0 && fSteppedOverFunctionAddress
					!= cpuState->InstructionPointer()) {
				TRACE_CONTROL("STEP_OVER: called function address %#" B_PRIx64
					", previous frame address: %#" B_PRIx64 ", frame address: %#"
					B_PRIx64 ", adding return info\n", fSteppedOverFunctionAddress,
					fPreviousFrameAddress, stackTrace->FrameAt(0)->FrameAddress());
				ReturnValueInfo* returnInfo = new(std::nothrow) ReturnValueInfo(
					fSteppedOverFunctionAddress, cpuState);
				if (returnInfo == NULL)
					return false;

				BReference<ReturnValueInfo> returnInfoReference(returnInfo, true);

				if (fThread->AddReturnValueInfo(returnInfo) != B_OK)
					return false;

				returnInfoReference.Detach();
				fSteppedOverFunctionAddress = 0;
			}

			// If we're still in the statement, we continue single-stepping,
			// otherwise we're done.
			if (fStepStatement->ContainsAddress(
					cpuState->InstructionPointer())) {
				if (!_DoStepOver(cpuState))
					_StepFallback();
				return true;
			}
			fPreviousFrameAddress = 0;
			return false;
		}

		case STEP_INTO:
			// Should never happen -- we don't set a breakpoint in this case.
			return false;

		case STEP_OUT:
		{
			// That's the return address, so we're done in theory,
			// unless we're a recursive function. Check if we've actually
			// exited the previous stack frame or not
			if (!_HasExitedFrame(cpuState->StackFramePointer())) {
				status_t error = _InstallTemporaryBreakpoint(
					cpuState->InstructionPointer());
				if (error != B_OK)
					_StepFallback();
				else
					_RunThread(cpuState->InstructionPointer());
				return true;
			}

			if (fPreviousFrameAddress == 0)
				return false;

			TRACE_CONTROL("ThreadHandler::_HandleBreakpointHitStep() - "
				"frame pointer 0x%#" B_PRIx64 ", previous: 0x%#" B_PRIx64
				" - step out adding return value\n", cpuState
					->StackFramePointer(), fPreviousFrameAddress);
			ReturnValueInfo* info = new(std::nothrow) ReturnValueInfo(
				fPreviousInstructionPointer, cpuState);
			if (info == NULL)
				return false;
			BReference<ReturnValueInfo> infoReference(info, true);
			if (fThread->AddReturnValueInfo(info) != B_OK)
				return false;

			infoReference.Detach();
			fPreviousFrameAddress = 0;
		}

		default:
			return false;
	}
}