| 1060 | |
| 1061 | #if !defined(__ANDROID__) |
| 1062 | void debug_write_backtrace( std::ostream &out ) |
| 1063 | { |
| 1064 | #if defined(_WIN32) |
| 1065 | if( !sym_init_ ) { |
| 1066 | sym_init_ = std::make_unique<sym_init>(); |
| 1067 | } |
| 1068 | sym.SizeOfStruct = sizeof( SYMBOL_INFO ); |
| 1069 | sym.MaxNameLen = max_name_len; |
| 1070 | // libbacktrace's own backtrace capturing doesn't seem to work on Windows |
| 1071 | const USHORT num_bt = CaptureStackBackTrace( 0, bt_cnt, bt, nullptr ); |
| 1072 | const HANDLE proc = GetCurrentProcess(); |
| 1073 | for( USHORT i = 0; i < num_bt; ++i ) { |
| 1074 | DWORD64 off; |
| 1075 | out << "\n #" << i; |
| 1076 | out << "\n (dbghelp: "; |
| 1077 | if( SymFromAddr( proc, reinterpret_cast<DWORD64>( bt[i] ), &off, &sym ) ) { |
| 1078 | out << demangle( sym.Name ) << "+0x" << std::hex << off << std::dec; |
| 1079 | } |
| 1080 | out << "@" << bt[i]; |
| 1081 | const DWORD64 mod_base = SymGetModuleBase64( proc, reinterpret_cast<DWORD64>( bt[i] ) ); |
| 1082 | if( mod_base ) { |
| 1083 | out << "["; |
| 1084 | const DWORD mod_len = GetModuleFileName( reinterpret_cast<HMODULE>( mod_base ), mod_path, |
| 1085 | module_path_len ); |
| 1086 | // mod_len == module_path_len means insufficient buffer |
| 1087 | if( mod_len > 0 && mod_len < module_path_len ) { |
| 1088 | const char *mod_name = mod_path + mod_len; |
| 1089 | for( ; mod_name > mod_path && *( mod_name - 1 ) != '\\'; --mod_name ) { |
| 1090 | } |
| 1091 | out << mod_name; |
| 1092 | } else { |
| 1093 | out << "0x" << std::hex << mod_base << std::dec; |
| 1094 | } |
| 1095 | out << "+0x" << std::hex << reinterpret_cast<uintptr_t>( bt[i] ) - mod_base << |
| 1096 | std::dec << "]"; |
| 1097 | } |
| 1098 | out << "), "; |
| 1099 | #if defined(LIBBACKTRACE) |
| 1100 | backtrace_module_info_t bt_module_info; |
| 1101 | if( mod_base ) { |
| 1102 | const auto it = bt_module_info_map.find( mod_base ); |
| 1103 | if( it != bt_module_info_map.end() ) { |
| 1104 | bt_module_info = it->second; |
| 1105 | } else { |
| 1106 | const DWORD mod_len = GetModuleFileName( reinterpret_cast<HMODULE>( mod_base ), mod_path, |
| 1107 | module_path_len ); |
| 1108 | if( mod_len > 0 && mod_len < module_path_len ) { |
| 1109 | bt_module_info.state = bt_create_state( mod_path, 0, |
| 1110 | // error callback |
| 1111 | [&out]( const char *const msg, const int errnum ) { |
| 1112 | out << "\n (backtrace_create_state failed: errno = " << errnum |
| 1113 | << ", msg = " << ( msg ? msg : "[no msg]" ) << "),"; |
| 1114 | } ); |
| 1115 | bt_module_info.image_base = get_image_base( mod_path ); |
| 1116 | if( bt_module_info.image_base == 0 ) { |
| 1117 | out << "\n (cannot locate image base),"; |
| 1118 | } |
| 1119 | } else { |