void StackTrace( const TargetInfo& ti, SymbolManager *symbol, target_ptr_t fp, // Frame pointer (or STG Sp register when we're in Haskell code) target_ptr_t ip) // Instruction pointer { std::printf("ghd: Stack Trace\n"); // Frame pointer x86 stack traversal struct StackFrame { target_ptr_t next; target_ptr_t ret; }; StackFrame frame = { fp, ip }; target_ptr_t old_fp = fp - 1; for (unsigned int depth=1; depth<64; depth++) { uint16_t file_name_id, line_number; const uint32_t sym_id = symbol->AddressToSymbolID(frame.ret, &file_name_id, &line_number); // Are we in Haskell code now? if (IsHaskellSymbol(ti, symbol, sym_id, file_name_id)) { Indent(depth); std::printf("0x%x <%s> [Haskell%s]\n", frame.ret, symbol->SymbolIDToName(sym_id), ti.m_profiling_rts ? ", switching to CCS" : ", switching to STG stack"); if (ti.m_profiling_rts) { // We have a CCS, pick it up from the Sp in the frame const target_ptr_t ccs = CCSPtrFromTopOfStack(ti, frame.next); if (ccs == 0) { Indent(depth + 1); std::printf("(Can't access CCS from STG stack at Sp = 0x%x)\n", frame.next); } else DumpCCS(ti, ccs, depth + 1); } else { // No profiling RTS, proceed with the STG stack DumpSTG(ti, symbol, frame.next, depth + 1); } break; // Done, we don't handle any potential Haskell -> C transition yet } // Current frame's function Indent(depth); std::printf("0x%x <%s> from %s (%s:%i)\n", frame.ret, symbol->SymbolIDToName(sym_id), symbol->SymbolIDToModule(sym_id), symbol->FileIDToName(file_name_id), line_number); // Some sanity checks for the frame link pointer bool stop_traversal = false; if (frame.next < 1024) { Indent(depth + 1); std::printf("(Next frame near zero)\n"); stop_traversal = true; } if (frame.next % sizeof(void *) != 0) // IIRC, OS X actually requires 16b alignment { Indent(depth + 1); std::printf("(Next frame improperly aligned)\n"); stop_traversal = true; } if (frame.next == old_fp) { Indent(depth + 1); std::printf("(Next frame identical to current)\n"); stop_traversal = true; } if (frame.next < old_fp) { Indent(depth + 1); std::printf("(Next frame before current)\n"); stop_traversal = true; } if (frame.next - old_fp > 32 * 1024 * 1024) { Indent(depth + 1); std::printf("(Next frame >32MB away from current)\n"); stop_traversal = true; } // Next frame old_fp = frame.next; if (ti.ReadMemoryArg(frame.next, sizeof(StackFrame), &frame) == false) { // Likely a bad address, stop traversing Indent(depth + 1); std::printf("(Can't access next frame)\n"); stop_traversal = true; } if (stop_traversal) break; } }