'Generic Commit'
This commit is contained in:
parent
db3a4dfa81
commit
040e258b9e
@ -109,8 +109,24 @@ std::vector<SourceInfo> get_source_info_batch(const char* executable, const std:
|
||||
return results;
|
||||
}
|
||||
|
||||
// Helper function to get the program counter (return address) in a portable way
|
||||
inline void* get_pc() {
|
||||
void* pc;
|
||||
#if defined(__aarch64__) || defined(__arm__)
|
||||
// For ARM/AArch64, we can use the link register (x30 on AArch64, r14 on ARM)
|
||||
#if defined(__aarch64__)
|
||||
asm volatile ("mov %0, x30" : "=r" (pc));
|
||||
#else
|
||||
asm volatile ("mov %0, lr" : "=r" (pc));
|
||||
#endif
|
||||
#else
|
||||
// For x86/x86_64, use __builtin_return_address
|
||||
pc = __builtin_return_address(0);
|
||||
#endif
|
||||
return pc;
|
||||
}
|
||||
|
||||
void print_stacktrace() {
|
||||
// Simple stacktrace implementation that doesn't segfault
|
||||
std::cerr << colors::yellow << "Stack trace:" << colors::reset << "\n";
|
||||
|
||||
char exe_path[1024] = {0};
|
||||
@ -121,19 +137,29 @@ void print_stacktrace() {
|
||||
exe_path[count] = '\0';
|
||||
}
|
||||
|
||||
// Get just a couple of stack frames safely
|
||||
std::vector<void*> addresses;
|
||||
|
||||
void* addr1 = __builtin_return_address(1); // assert_failed
|
||||
void* addr2 = __builtin_return_address(2); // caller of ASSERT
|
||||
// Get current frame pointer and return address
|
||||
void* frame_ptr = __builtin_frame_address(0);
|
||||
void* return_addr = get_pc();
|
||||
|
||||
// Adjust addresses to point to call site instead of return address
|
||||
// Subtract a small offset to get the call instruction instead of the return address
|
||||
if (addr1) {
|
||||
addresses.push_back(static_cast<char*>(addr1) - 1);
|
||||
// Add current return address
|
||||
if (return_addr) {
|
||||
addresses.push_back(return_addr);
|
||||
}
|
||||
if (addr2) {
|
||||
addresses.push_back(static_cast<char*>(addr2) - 1);
|
||||
|
||||
// Try to walk up the stack if we have a valid frame pointer
|
||||
if (frame_ptr) {
|
||||
void** frame = static_cast<void**>(frame_ptr);
|
||||
// Limit the number of frames to prevent potential issues
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
// The return address is typically at frame[1]
|
||||
if (frame[1] == nullptr) break;
|
||||
addresses.push_back(frame[1]);
|
||||
// Move to the next frame
|
||||
if (frame[0] == nullptr) break;
|
||||
frame = static_cast<void**>(frame[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (addresses.empty()) {
|
||||
@ -144,18 +170,55 @@ void print_stacktrace() {
|
||||
// Get source info
|
||||
std::vector<SourceInfo> results = get_source_info_batch(exe_path, addresses);
|
||||
|
||||
// Filter out frames from assert.hpp
|
||||
results.erase(std::remove_if(results.begin(), results.end(),
|
||||
[](const SourceInfo& frame) {
|
||||
if (frame.file.empty()) return false;
|
||||
std::string_view file(frame.file);
|
||||
return file.find("assert.hpp") != std::string_view::npos;
|
||||
}),
|
||||
results.end()
|
||||
);
|
||||
|
||||
if (results.empty()) {
|
||||
std::cerr << " " << colors::red << "[no user frames available]" << colors::reset << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// First pass: find the maximum function name length for alignment
|
||||
size_t max_func_length = 0;
|
||||
for (const auto& frame : results) {
|
||||
size_t length = frame.function.empty()
|
||||
? strlen("[unknown function]")
|
||||
: frame.function.length();
|
||||
if (length > max_func_length) {
|
||||
max_func_length = length;
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: print with aligned output
|
||||
for (size_t i = 0; i < results.size(); ++i) {
|
||||
const auto& frame = results[i];
|
||||
std::cerr << " ";
|
||||
|
||||
// Print function name with alignment
|
||||
size_t current_length;
|
||||
if (!frame.function.empty()) {
|
||||
std::cerr << colors::green << frame.function << colors::reset;
|
||||
current_length = frame.function.length();
|
||||
} else {
|
||||
std::cerr << colors::red << "[unknown function]" << colors::reset;
|
||||
current_length = strlen("[unknown function]");
|
||||
}
|
||||
|
||||
// Add padding to align the file/line text
|
||||
if (!frame.file.empty() && frame.line > 0) {
|
||||
std::cerr << " at " << colors::blue << frame.file << colors::reset
|
||||
// Calculate padding (minimum 1 space)
|
||||
size_t padding = (max_func_length > current_length)
|
||||
? (max_func_length - current_length + 1)
|
||||
: 1;
|
||||
std::cerr << std::string(padding, ' ')
|
||||
<< " " << colors::blue << frame.file << colors::reset
|
||||
<< ":" << colors::magenta << frame.line << colors::reset;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user