Skip to content

Commit

Permalink
Parse OSX stack dump format in order to demangle it correctly (#473)
Browse files Browse the repository at this point in the history
* Parse OSX format  mangled stack trace correctly
Co-authored-by: Grzegorz Glowacki <grzegorz.glowacki@avid.com>
  • Loading branch information
gglowacki authored Feb 4, 2023
1 parent 16bb6f7 commit 09317e3
Showing 1 changed file with 32 additions and 25 deletions.
57 changes: 32 additions & 25 deletions src/crashhandler_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,50 +145,57 @@ namespace g3 {
if (nullptr != rawdump && !std::string(rawdump).empty()) {
return {rawdump};
}

const size_t max_dump_size = 50;
void* dump[max_dump_size];
size_t size = backtrace(dump, max_dump_size);
const size_t size = backtrace(dump, max_dump_size);
char** messages = backtrace_symbols(dump, static_cast<int>(size)); // overwrite sigaction with caller's address

// dump stack: skip first frame, since that is here
std::ostringstream oss;
for (size_t idx = 1; idx < size && messages != nullptr; ++idx) {
char* mangled_name = 0, *offset_begin = 0, *offset_end = 0;
// find parentheses and +address offset surrounding mangled name
for (char* p = messages[idx]; *p; ++p) {
if (*p == '(') {
mangled_name = p;
} else if (*p == '+') {
offset_begin = p;
} else if (*p == ')') {
offset_end = p;
break;
}
std::string strMessage{messages[idx]};
std::string mangled_name, offset;

/// first look for format that includes brackets "(mangled_name+offset)""
const auto firstBracket = strMessage.find_last_of('(');
const auto secondBracket = strMessage.find_last_of(')');
if (firstBracket != strMessage.npos && secondBracket != strMessage.npos)
{
const auto betweenBrackets = strMessage.substr(firstBracket + 1, secondBracket - firstBracket - 1);
const auto plusSign = betweenBrackets.find_first_of('+');
if (plusSign != betweenBrackets.npos)
{
mangled_name = betweenBrackets.substr(0, plusSign);
offset = betweenBrackets.substr(plusSign + 1, betweenBrackets.npos);
}
}
else
{
/// we did not found brackets, looking for "_mangled_name + offset"
const auto plusSign = strMessage.find_first_of('+');
const auto lastUnderscore = strMessage.rfind(" _");
if (plusSign != strMessage.npos && lastUnderscore != strMessage.npos)
{
mangled_name = strMessage.substr(lastUnderscore + 1, plusSign - lastUnderscore - 2);
offset = strMessage.substr(plusSign + 2, strMessage.npos);
}
}

// if the line could be processed, attempt to demangle the symbol
if (mangled_name && offset_begin && offset_end &&
mangled_name < offset_begin) {
*mangled_name++ = '\0';
*offset_begin++ = '\0';
*offset_end++ = '\0';

if (!mangled_name.empty() && !offset.empty()) {
int status;
char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
char* real_name = abi::__cxa_demangle(mangled_name.c_str(), 0, 0, &status);
// if demangling is successful, output the demangled function name
if (status == 0) {
oss << "\n\tstack dump [" << idx << "] " << messages[idx] << " : " << real_name << "+";
oss << offset_begin << offset_end << std::endl;
oss << "\tstack dump [" << idx << "] " << real_name << " + " << offset<< std::endl;
}// otherwise, output the mangled function name
else {
oss << "\tstack dump [" << idx << "] " << messages[idx] << mangled_name << "+";
oss << offset_begin << offset_end << std::endl;
oss << "\tstack dump [" << idx << "] " << mangled_name << " + " << offset<< std::endl;
}
free(real_name); // mallocated by abi::__cxa_demangle(...)
} else {
// no demangling done -- just dump the whole line
oss << "\tstack dump [" << idx << "] " << messages[idx] << std::endl;
oss << "\tstack dump [" << idx << "] " << strMessage << std::endl;
}
} // END: for(size_t idx = 1; idx < size && messages != nullptr; ++idx)
free(messages);
Expand Down

0 comments on commit 09317e3

Please sign in to comment.