void CodeProfile::report() { dataLogF("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber); // How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose. unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose(); ProfileTreeNode profile; // Walk through the sample buffer. size_t trace = 0; while (trace < m_samples.size()) { // All traces are zero or more 'EngineFrame's, followed by a non-'EngineFrame'. // Scan to find the last sample in the trace. size_t lastInTrace = trace; while (m_samples[lastInTrace].type == EngineFrame) ++lastInTrace; // We use the last sample type to look up a name (used as a bucket in the profiler). ProfileTreeNode* callbacks = profile.sampleChild(s_codeTypeNames[m_samples[lastInTrace].type]); // If there are any samples in C-code, add up to recursionLimit of them into the profile tree. size_t lastEngineFrame = lastInTrace; for (unsigned count = 0; lastEngineFrame > trace && count < recursionLimit; ++count) { --lastEngineFrame; ASSERT(m_samples[lastEngineFrame].type == EngineFrame); const char* name = "<unknown>"; auto demangled = StackTrace::demangle(m_samples[lastEngineFrame].pc); if (demangled) name = demangled->demangledName() ? demangled->demangledName() : demangled->mangledName(); callbacks = callbacks->sampleChild(name); if (truncateTrace(name)) break; } // Move on to the next trace. trace = lastInTrace + 1; ASSERT(trace <= m_samples.size()); } // Output the profile tree. dataLogF("Total samples: %lld\n", static_cast<long long>(profile.childCount())); profile.dump(); for (size_t i = 0 ; i < m_children.size(); ++i) m_children[i]->report(); dataLogF("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber); }
std::string Function::printableName() const { std::string s = "function " + StringUtility::addrToString(address()); const std::string &name = demangledName(); if (!name.empty()) s += " \"" + StringUtility::cEscape(name) + "\""; return s; }
void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack& callStack) { #if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK)) static const int framesToShow = 31; static const int framesToSkip = 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException. void* samples[framesToShow + framesToSkip]; int frames = framesToShow + framesToSkip; WTFGetBacktrace(samples, &frames); void** stack = samples + framesToSkip; int size = frames - framesToSkip; for (int i = 0; i < size; ++i) { auto demangled = StackTrace::demangle(stack[i]); if (demangled) callStack.append(ScriptCallFrame(demangled->demangledName() ? demangled->demangledName() : demangled->mangledName(), ASCIILiteral("[native code]"), noSourceID, 0, 0)); else callStack.append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), noSourceID, 0, 0)); } #else UNUSED_PARAM(callStack); #endif }
/** * @brief getStackTrace * 获得栈信息 * @return {string} */ string baseException::getStackTrace() const { if (_mStackTraceSize == 0) { return "<No stack trace>\n"; } char** strings = backtrace_symbols(_mStackTrace, 10); if (strings == NULL) { return "Unknown error: backtrace_symbols returned NULL>\n"; } string result; for (size_t i = 0; i < _mStackTraceSize; i++) { string mangledName = strings[i]; string::size_type begin = mangledName.find('('); string::size_type end = mangledName.find('+', begin); if (begin == string::npos || end == string::npos) { result += mangledName; result += '\n'; continue; } ++begin; int status; //获取函数类型 char* s = abi::__cxa_demangle(mangledName.substr(begin, end-begin).c_str(), NULL, 0, &status); if (status != 0) { result += mangledName; result += '\n'; continue; } string demangledName(s); free(s); result += mangledName.substr(0, begin); result += demangledName; result += mangledName.substr(end); result += '\n'; } free(strings); return result; }