See also imbind.cpp:DumpStackTrace and VM::DumpStackTrace()
| 476 | |
| 477 | // See also imbind.cpp:DumpStackTrace and VM::DumpStackTrace() |
| 478 | void VM::DumpStackTraceMemory(const string &err) { |
| 479 | if (fun_id_stack.empty()) { |
| 480 | // We don't have a stack trace. |
| 481 | return; |
| 482 | } |
| 483 | // We're going to be dumping as much as possible of the memory of the program along with |
| 484 | // the stack trace. To this end we're using the FlexBuffers dumper which already can deal with |
| 485 | // cycles etc, so it will output max 1 copy of each data structure. |
| 486 | ToFlexBufferContext fbc(*this, 1024 * 1024, flexbuffers::BUILDER_FLAG_SHARE_KEYS_AND_STRINGS); |
| 487 | fbc.cycle_detect = true; |
| 488 | fbc.max_depth = 64; |
| 489 | fbc.ignore_unsupported_types = true; |
| 490 | |
| 491 | #ifdef USE_EXCEPTION_HANDLING |
| 492 | try { |
| 493 | #endif |
| 494 | |
| 495 | DumperFun dumper = [&fbc](VM &vm, string_view_nt name, const TypeInfo &ti, Value *x) { |
| 496 | #if RTT_ENABLED |
| 497 | auto debug_type = x->type; |
| 498 | #else |
| 499 | auto debug_type = ti.t; |
| 500 | #endif |
| 501 | if (debug_type == RTT_NIL && !ti.is_nil) { |
| 502 | // Just skip, only useful in debug. |
| 503 | } else if (ti.t != debug_type && !RTIsStruct(ti.t)) { |
| 504 | // Just skip, only useful in debug. |
| 505 | } else { |
| 506 | fbc.builder.Key(name.data(), name.size()); |
| 507 | if (RTIsStruct(ti.t)) { |
| 508 | vm.StructToFlexBuffer(fbc, ti, x, false); |
| 509 | } else { |
| 510 | x->ToFlexBuffer(fbc, ti.t, {}, (type_elem_t)0); |
| 511 | } |
| 512 | } |
| 513 | }; |
| 514 | |
| 515 | auto vstart = fbc.builder.StartVector(); |
| 516 | fbc.builder.String(err); |
| 517 | auto cur_fileidx = last.fileidx; |
| 518 | auto cur_line = last.line; |
| 519 | for (auto &funstackelem : reverse(fun_id_stack)) { |
| 520 | auto vstart2 = fbc.builder.StartVector(); |
| 521 | auto [name, fip] = DumpStackFrameStart(funstackelem.funstartinfo, cur_fileidx, cur_line); |
| 522 | fbc.builder.String(name); |
| 523 | auto mstart = fbc.builder.StartMap(); |
| 524 | DumpStackFrame(fip, funstackelem.locals, dumper); |
| 525 | fbc.builder.EndMap(mstart); |
| 526 | fbc.builder.EndVector(vstart2, false, false); |
| 527 | cur_fileidx = funstackelem.fileidx; |
| 528 | cur_line = funstackelem.line; |
| 529 | } |
| 530 | fbc.builder.EndVector(vstart, false, false); |
| 531 | fbc.builder.Finish(); |
| 532 | auto fn = cat("crash_stack_trace_memory_dump_", GetDateTime(), ".flex"); |
| 533 | auto contents = |
| 534 | string_view((char *)fbc.builder.GetBuffer().data(), fbc.builder.GetBuffer().size()); |
| 535 | if (WriteFile(fn, true, contents, false)) { |
no test coverage detected