Fix `$stacktrace` to decode through internal-c++filt (#6985).
This commit is contained in:
parent
9083b238e5
commit
bb979a00c8
|
|
@ -528,6 +528,12 @@ $readmemb, $readmemh
|
|||
specification do not include support for readmem to multi-dimensional
|
||||
arrays.
|
||||
|
||||
$stacktrace
|
||||
The `$stacktrace` system call will show the C++ stack, not the Verilog
|
||||
call stack, though the function names typically correlate. To get
|
||||
symbolic names, the model must have debug symbols, e.g. compile with
|
||||
`-CFLAGS -ggdb -LDFLAGS -ggdb -LDFLAGS -rdynamic`.
|
||||
|
||||
$test$plusargs, $value$plusargs
|
||||
Supported, but the instantiating C++/SystemC wrapper must call
|
||||
|
||||
|
|
|
|||
|
|
@ -1102,6 +1102,7 @@ src
|
|||
srcdir
|
||||
srcfile
|
||||
sscanf
|
||||
stacktrace
|
||||
stderr
|
||||
stdin
|
||||
stdout
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
# include <direct.h> // mkdir
|
||||
#endif
|
||||
#ifdef __GLIBC__
|
||||
# include <cxxabi.h>
|
||||
# include <execinfo.h>
|
||||
# define _VL_HAVE_STACKTRACE
|
||||
#endif
|
||||
|
|
@ -1918,6 +1919,40 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi
|
|||
return read_count;
|
||||
}
|
||||
|
||||
#ifdef _VL_HAVE_STACKTRACE
|
||||
static std::string _vl_stacktrace_demangle(const std::string& input) {
|
||||
std::string result;
|
||||
result.reserve(input.size());
|
||||
|
||||
std::string word;
|
||||
for (const char c : input) {
|
||||
if (std::isalpha(c) || c == '_') {
|
||||
word += c;
|
||||
} else if (!word.empty() && std::isdigit(c)) {
|
||||
word += c;
|
||||
} else {
|
||||
if (!word.empty()) {
|
||||
// abi::__cxa_demangle mallocs demangled_name
|
||||
int status = 0;
|
||||
char* const demangled_name
|
||||
= abi::__cxa_demangle(word.c_str(), NULL, NULL, &status);
|
||||
if (status == 0) {
|
||||
result += std::string{demangled_name};
|
||||
std::free(demangled_name); // Free the allocated memory
|
||||
} else {
|
||||
result += word;
|
||||
}
|
||||
word.clear();
|
||||
}
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
// input requires final newline, so last word can't be symbol
|
||||
result += word;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string VL_STACKTRACE_N() VL_MT_SAFE {
|
||||
static VerilatedMutex s_stackTraceMutex;
|
||||
const VerilatedLockGuard lock{s_stackTraceMutex};
|
||||
|
|
@ -1935,8 +1970,12 @@ std::string VL_STACKTRACE_N() VL_MT_SAFE {
|
|||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (!strings) return "Unable to backtrace\n";
|
||||
|
||||
#ifdef _VL_HAVE_STACKTRACE
|
||||
std::string result = "Backtrace:\n";
|
||||
for (int j = 0; j < nptrs; ++j) result += std::string{strings[j]} + "\n"s;
|
||||
for (int j = 0; j < nptrs; ++j)
|
||||
result += _vl_stacktrace_demangle(std::string{strings[j]} + "\n"s);
|
||||
#endif
|
||||
|
||||
free(strings);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
test.compile(verilator_flags2=['-CFLAGS -ggdb -LDFLAGS -ggdb -LDFLAGS -rdynamic'])
|
||||
|
||||
test.execute()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,22 +6,22 @@
|
|||
|
||||
module t;
|
||||
|
||||
task automatic t;
|
||||
// verilator no_inline_task
|
||||
string trace;
|
||||
task automatic t;
|
||||
// verilator no_inline_task
|
||||
string trace;
|
||||
|
||||
$display("== Trace Func");
|
||||
trace = $stacktrace();
|
||||
if (trace == "") $stop;
|
||||
$display("%s", trace);
|
||||
$display("== Trace Func");
|
||||
trace = $stacktrace();
|
||||
if (trace == "") $stop;
|
||||
$display("%s", trace);
|
||||
|
||||
$display("== Trace Task");
|
||||
$stacktrace;
|
||||
$display("== Trace Task");
|
||||
$stacktrace;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
endtask
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
endtask
|
||||
|
||||
initial t();
|
||||
initial t();
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue