11 #define PACKAGE "CppCommon"
12 #define PACKAGE_VERSION "1.0.0.0"
23 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
25 #if defined(LIBBFD_SUPPORT)
28 #if defined(LIBDL_SUPPORT)
32 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
34 #if defined(DBGHELP_SUPPORT)
37 #pragma warning(disable:4091)
51 std::ios_base::fmtflags flags = os.flags();
52 os <<
"0x" << std::hex << std::uppercase << std::setfill(
'0') << std::setw(2 *
sizeof(uintptr_t)) << (uintptr_t)frame.
address <<
": ";
55 os << (frame.
module.empty() ?
"<unknown>" : frame.
module) <<
'!';
59 os <<
'(' << frame.
line <<
')';
65 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
66 const int capacity = 1024;
70 int captured = backtrace(
frames, capacity);
72 int size = captured - index;
86 for (
int i = 0; i < size; ++i)
88 auto& frame = _frames[i];
91 frame.address =
frames[index + i];
93 #if defined(LIBDL_SUPPORT)
96 if (dladdr(
frames[index + i], &info) == 0)
100 if (info.dli_fname !=
nullptr)
102 const char* module = std::strrchr(info.dli_fname,
'/');
103 if (module !=
nullptr)
104 frame.module = module + 1;
108 if (info.dli_sname !=
nullptr)
112 char* demangled = abi::__cxa_demangle(info.dli_sname,
nullptr, 0, &status);
113 if ((status == 0) && (demangled !=
nullptr))
115 frame.function = demangled;
119 frame.function = info.dli_sname;
122 #if defined(LIBBFD_SUPPORT)
124 char** matching =
nullptr;
126 void* symsptr =
nullptr;
127 asymbol** syms =
nullptr;
128 unsigned int symsize;
131 const char* filename =
nullptr;
132 const char* functionname =
nullptr;
135 bfd_boolean found =
false;
138 if ((frame.address ==
nullptr) || (info.dli_fname ==
nullptr))
141 abfd = bfd_openr(info.dli_fname,
nullptr);
145 if (bfd_check_format(abfd, bfd_archive))
148 if (!bfd_check_format_matches(abfd, bfd_object, &matching))
151 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
154 symcount = bfd_read_minisymbols(abfd, FALSE, &symsptr, &symsize);
156 symcount = bfd_read_minisymbols(abfd, TRUE, &symsptr, &symsize);
159 syms = (asymbol**)symsptr;
161 pc = (bfd_vma)frame.address;
162 for (asection* section = abfd->sections; section !=
nullptr; section = section->next)
167 if ((bfd_section_flags(section) & SEC_ALLOC) == 0)
170 bfd_vma vma = bfd_section_vma(section);
174 bfd_size_type secsize = bfd_section_size(section);
175 if (pc >= vma + secsize)
178 found = bfd_find_nearest_line(abfd, section, syms, pc - vma, &filename, &functionname, &line);
184 if (filename !=
nullptr)
185 frame.filename = filename;
189 if (symsptr !=
nullptr)
196 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
197 const int capacity = 1024;
201 USHORT captured = CaptureStackBackTrace(skip + 1, capacity,
frames,
nullptr);
204 _frames.resize(captured);
211 for (
int i = 0; i < captured; ++i)
213 auto& frame = _frames[i];
216 frame.address =
frames[i];
218 #if defined(DBGHELP_SUPPORT)
220 HANDLE hProcess = GetCurrentProcess();
223 IMAGEHLP_MODULE64 module;
224 ZeroMemory(&module,
sizeof(module));
225 module.SizeOfStruct =
sizeof(module);
226 if (SymGetModuleInfo64(hProcess, (DWORD64)frame.address, &module))
228 const char* image = std::strrchr(module.ImageName,
'\\');
229 if (image !=
nullptr)
230 frame.module = image + 1;
234 char symbol[
sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
235 ZeroMemory(&symbol,
countof(symbol));
236 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbol;
237 pSymbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
238 pSymbol->MaxNameLen = MAX_SYM_NAME;
239 if (SymFromAddr(hProcess, (DWORD64)frame.address,
nullptr, pSymbol))
242 if (UnDecorateSymbolName(pSymbol->Name, buffer, (DWORD)
countof(buffer), UNDNAME_NAME_ONLY) > 0)
243 frame.function = buffer;
248 IMAGEHLP_LINE64 line;
249 ZeroMemory(&line,
sizeof(line));
250 line.SizeOfStruct =
sizeof(line);
251 if (SymGetLineFromAddr64(hProcess, (DWORD64)frame.address, &offset, &line))
253 if (line.FileName !=
nullptr)
254 frame.filename = line.FileName;
255 frame.line = line.LineNumber;
264 for (
const auto& frame : stack_trace.
frames())
265 os << frame << std::endl;
Critical section synchronization primitive.
Locker synchronization primitive.
Stack trace snapshot provider.
StackTrace(int skip=0)
Capture the current stack trace snapshot.
const std::vector< Frame > & frames() const noexcept
Get stack trace frames.
Static array countof definition.
Critical section synchronization primitive definition.
C++ Common project definitions.
std::ostream & operator<<(std::ostream &os, const uint128_t &value)
constexpr size_t countof(const T(&)[N]) noexcept
Count of elements in static array.
Stack trace snapshot provider definition.
std::string filename
Frame file name.
std::string function
Frame function.
int line
Frame line number.
std::string module
Frame module.
void * address
Frame address.