#include <execinfo.h>
#include <string>
-#include <unordered_map>
-#include "../profiler/src/stackentry.h"
-
-// CoreCLR profiler will fill this up with the current managed stack.
-__thread StackEntry * g_shadowStack = nullptr;
/**
* @brief A libunwind based backtrace.
return m_data[m_skip + i];
}
- std::string getManagedName(int i) const
- {
- return m_managed_names[m_skip + i];
- }
-
int size() const
{
return m_size - m_skip;
}
- bool is_managed(int i) const
- {
- assert(i < size());
- return (i >= m_size - m_skip - m_managed_size);
- }
-
__attribute__((noinline))
bool fill(int skip)
{
- int size = backtrace(m_data + m_managed_size, MAX_SIZE);
+ int size = backtrace(m_data, MAX_SIZE);
// filter bogus frames at the end, which sometimes get returned by libunwind
// cf.: https://bugs.kde.org/show_bug.cgi?id=379082
while (size > 0 && !m_data[size - 1]) {
}
m_size = size;
m_skip = skip;
- m_managed_size = managed_backtrace(m_size, MAX_SIZE);
- m_size += m_managed_size;
return m_size > 0;
}
m_data[0] = addr;
m_data[1] = addr;
}
+
private:
int m_size = 0;
int m_skip = 0;
- int m_managed_size = 0;
- ip_t m_data[MAX_SIZE * 2];
- std::string m_managed_names[MAX_SIZE * 2];
-
- int managed_backtrace(int start_index, int max_size) {
- StackEntry *stackIter = g_shadowStack;
- int i = start_index;
-
- if (stackIter != nullptr && max_size > 0) {
- m_data[i] = (void*) 0xffffffff;
- m_managed_names[i] = "[Unmanaged->Managed]";
- ++i;
- --max_size;
- while (stackIter != nullptr && max_size > 0) {
- ip_t key = reinterpret_cast<ip_t>(stackIter->m_funcId);
- m_managed_names[i] = stackIter->m_className;
- m_managed_names[i].append("::");
- m_managed_names[i].append(stackIter->m_methodName);
- --max_size;
- m_data[i] = key;
- ++i;
- stackIter = stackIter->m_next;
- }
- }
- return i - start_index;
- }
+ ip_t m_data[MAX_SIZE];
};
#endif // TRACE_H
#include "trace.h"
-static std::unordered_set<Trace::ip_t> knownNames;
+#include "../profiler/src/stackentry.h"
+
+extern __thread StackEntry* g_shadowStack;
struct TraceEdge
{
{
uint32_t index = 0;
TraceEdge* parent = &m_root;
- for (int i = trace.size() - 1; i >= 0; --i) {
- const auto ip = trace[i];
- if (!ip) {
- continue;
- }
+
+ auto handleIP = [this, out, &parent, &index] (void *ip, bool isManaged) {
auto it =
std::lower_bound(parent->children.begin(), parent->children.end(), ip,
[](const TraceEdge& l, const Trace::ip_t ip) { return l.instructionPointer < ip; });
if (it == parent->children.end() || it->instructionPointer != ip) {
index = m_index++;
- if (trace.is_managed(i) && knownNames.find(ip) == knownNames.end()) {
- std::string managed_name = trace.getManagedName(i);
- fprintf(out, "n %" PRIxPTR " %s\n", reinterpret_cast<uintptr_t>(ip), managed_name.c_str());
- knownNames.insert(ip);
- }
it = parent->children.insert(it, {ip, index, {}});
- fprintf(out, "t %" PRIxPTR " %x %x\n", reinterpret_cast<uintptr_t>(ip), parent->index, trace.is_managed(i) ? 1 : 0);
+ fprintf(out, "t %" PRIxPTR " %x %x\n", reinterpret_cast<uintptr_t>(ip), parent->index, isManaged ? 1 : 0);
}
index = it->index;
parent = &(*it);
+ };
+
+ // process managed stack
+ StackEntry *stackIter = g_shadowStack;
+
+ if (stackIter != nullptr) {
+ void* managedStack[Trace::MAX_SIZE];
+ int managedStackSize = 0;
+
+ managedStack[managedStackSize++] = (void *) (uintptr_t) -1;
+
+ while (stackIter != nullptr && managedStackSize < Trace::MAX_SIZE) {
+ void *ip = reinterpret_cast<void *>(stackIter->m_funcId);
+
+ if (knownNames.find(ip) == knownNames.end()) {
+ std::string managed_name = stackIter->m_className;
+ managed_name.append("::");
+ managed_name.append(stackIter->m_methodName);
+
+ fprintf(out, "n %" PRIxPTR " %s\n", reinterpret_cast<uintptr_t>(ip), managed_name.c_str());
+
+ knownNames.insert(ip);
+ }
+
+ managedStack[managedStackSize++] = ip;
+
+ stackIter = stackIter->m_next;
+ }
+
+ for (int i = managedStackSize - 1; i >= 0; --i) {
+ handleIP(managedStack[i], true);
+ }
+ }
+
+ // process unmanaged stack
+ for (int i = trace.size() - 1; i >= 0; --i) {
+ const auto ip = trace[i];
+ if (!ip) {
+ continue;
+ }
+
+ handleIP(ip, false);
}
return index;
}
+ static std::unordered_set<Trace::ip_t> knownNames;
+
private:
TraceEdge m_root = {0, 0, {}};
uint32_t m_index = 1;