MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
backtrace.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef BACKTRACE_H_
8#define BACKTRACE_H_
9
10#include <iostream>
11#include <sstream>
12#include "INCLUDE/maiatypes.h"
13#include "compiler_config.h"
14
15#ifdef MAIA_GCC_COMPILER
16// Needed for stack trace
17#include <cxxabi.h>
18#include <execinfo.h>
19#endif
20
21// General backtrace macro
22#if defined(ENABLE_BACKTRACE)
23#include "llvm/Support/Signals.h"
24#ifndef __STDC_LIMIT_MACROS
25#define __STDC_LIMIT_MACROS
26#endif
27#ifndef __STDC_CONSTANT_MACROS
28#define __STDC_CONSTANT_MACROS
29#endif
30#include "llvm/Support/raw_ostream.h"
31
32#define BACKTRACE() \
33 do { \
34 maia::debug::backtrace(); \
35 } while(false)
36#else
37#define BACKTRACE() \
38 do { \
39 } while(false)
40#endif
41
42
43namespace maia {
44namespace debug {
45
57#if defined(ENABLE_BACKTRACE)
58inline void backtrace() {
59 llvm::errs() << "Backtrace (line numbers may be too large by 1-3 lines):\n";
60 llvm::sys::PrintStackTrace(llvm::errs());
61}
62#endif
63
76#ifdef MAIA_GCC_COMPILER
77inline void backtrace_gcc(const MString& fileName, const MInt noFramesOmitted = 1) {
78 // Get trace
79 const int maxNoTraces = 128;
80 void* trace[maxNoTraces];
81 int noTraces = ::backtrace(trace, maxNoTraces);
82
83 // Get messages (i.e. function names)
84 char** messages = backtrace_symbols(trace, noTraces);
85
86 // Create stream and char buffer for single-flush printing
87 std::stringstream s;
88 const MInt maxLineLength = 1024;
89 MChar line[maxLineLength];
90
91 // Print out messages one by one
92 const MInt maxCmdSize = 1024;
93 MInt frameId = 0;
94 const MInt noFrames = noTraces - noFramesOmitted;
95 const MInt width = noFrames ? floor(log10(noFrames)) + 1 : 1;
96 s << "\nBacktrace (line numbers are usually too large, typically by 1-3 "
97 "lines):\n";
98 for(MInt i = noFramesOmitted; i < noTraces; i++) {
99 // Get demangled function name
100 MString mangled(messages[i]);
101 mangled = mangled.substr(mangled.find("(") + 1);
102 mangled = mangled.substr(0, mangled.find("+"));
103 int status;
104 char* demangledChar = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
105
106 // Only use demangled name if demangling worked
107 const MString demangled = (status == 0) ? demangledChar : messages[i];
108 free(demangledChar);
109
110 // Get filename/line number using addr2line
111 char cmd[maxCmdSize];
112 std::sprintf(cmd, "addr2line %p -s -e %s", trace[i], fileName.c_str());
113 MString fileline;
114 FILE* pipe = popen(cmd, "r");
115 if(!pipe) {
116 fileline = "n/a";
117 } else {
118 char buffer[128];
119 while(!feof(pipe)) {
120 if(fgets(buffer, 128, pipe) != nullptr) {
121 fileline += buffer;
122 }
123 }
124 }
125 pclose(pipe);
126
127 // Parse output of addr2line to skip newline and possible discriminator
128 // information
129 fileline = fileline.substr(0, fileline.length() - 1);
130 fileline = fileline.substr(0, fileline.find(" "));
131
132 // Print function names + filename:lineno
133 std::sprintf(line, "#%-*d 0x%016lx in %s at %s\n", width, frameId++, reinterpret_cast<uintptr_t>(trace[i]),
134 demangled.c_str(), fileline.c_str());
135 line[maxLineLength - 1] = '\0';
136 s << line;
137 }
138 std::cout << s.str() << std::endl;
139}
140#else
141inline void backtrace_gcc(const MString& NotUsed(fileName), MInt NotUsed(noFramesOmitted)) {
142 std::cout << "Not using GCC - backtrace disabled." << std::endl;
143}
144#endif
145
146} // namespace debug
147} // namespace maia
148
149#endif // ifndef BACKTRACE_H_
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
char MChar
Definition: maiatypes.h:56
void backtrace_gcc(const MString &fileName, const MInt noFramesOmitted=1)
Prints a backtrace of the function call path if possible.
Definition: backtrace.h:77
void backtrace()
Prints a backtrace of the function call path if possible.
Definition: backtrace.h:58
Namespace for auxiliary functions/classes.
void free(void *)
Definition: nvhpcbugfix.cpp:11