Revise macOS print backtrace logic
This commit is contained in:
parent
3c5b7e0918
commit
10099ec99d
|
@ -16,7 +16,7 @@
|
|||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <regex>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "tgl.h"
|
||||
|
@ -65,7 +65,7 @@ static const char *filenameOnly(const char *path) {
|
|||
//-----------------------------------------------------------------------------
|
||||
static QString obfuscateUsername(QString path) {
|
||||
QString username = TSystem::getUserName();
|
||||
QString newPath = path;
|
||||
QString newPath = path;
|
||||
newPath.replace("/" + username + "/", "/USER/");
|
||||
newPath.replace("\\" + username + "\\", "\\USER\\");
|
||||
return newPath;
|
||||
|
@ -307,41 +307,13 @@ static bool sh(std::string &out, const char *cmd) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool addr2line(std::string &out, const char *exepath, const char *addr) {
|
||||
static bool addr2line(std::string &out, const char *exepath, const size_t addr,
|
||||
const size_t laddr) {
|
||||
char cmd[512];
|
||||
#ifdef MACOSX
|
||||
std::string exe;
|
||||
uintptr_t loadaddr;
|
||||
int c = _dyld_image_count();
|
||||
bool libFound = false;
|
||||
for (int i = 0; i < c; i++) {
|
||||
const char *image_name = _dyld_get_image_name(i);
|
||||
|
||||
const char *moduleName = strstr(image_name, exepath);
|
||||
if (!moduleName)
|
||||
continue;
|
||||
|
||||
exe = std::string(image_name);
|
||||
const struct mach_header *header = _dyld_get_image_header(i);
|
||||
loadaddr = (uintptr_t) header;
|
||||
libFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!libFound)
|
||||
return false;
|
||||
|
||||
if (exe.find("Tahoma2D.app/Contents/MacOS") != std::string::npos) {
|
||||
std::string dsym = exe;
|
||||
int pos = dsym.find("Contents");
|
||||
dsym.replace(pos, 14, "DSYM/Contents/Resources/DWARF");
|
||||
TFilePath file(dsym);
|
||||
if(TFileStatus(file).doesExist()) exe = dsym;
|
||||
}
|
||||
|
||||
sprintf(cmd, "atos -o \"%.400s\" -l %p %s 2>&1", exe.c_str(), loadaddr, addr);
|
||||
sprintf(cmd, "atos -o \"%.400s\" -l %p %p 2>&1", exepath, laddr, addr);
|
||||
#else
|
||||
sprintf(cmd, "addr2line -f -p -e \"%.400s\" %s 2>&1", exepath, addr);
|
||||
sprintf(cmd, "addr2line -f -p -e \"%.400s\" %p 2>&1", exepath, addr);
|
||||
#endif
|
||||
return sh(out, cmd);
|
||||
}
|
||||
|
@ -355,11 +327,16 @@ static bool generateMinidump(TFilePath dumpFile) { return false; }
|
|||
#define HAS_MODULES
|
||||
static void printModules(std::string &out) {
|
||||
#ifdef MACOSX
|
||||
char str[512];
|
||||
int c = _dyld_image_count();
|
||||
for (int i = 0; i < c; i++) {
|
||||
const char *image_name = _dyld_get_image_name(i);
|
||||
const char *image_name = _dyld_get_image_name(i);
|
||||
const struct mach_header *header = _dyld_get_image_header(i);
|
||||
uintptr_t loadaddr = (uintptr_t)header;
|
||||
sprintf(str, "%p", loadaddr);
|
||||
|
||||
QString path = obfuscateUsername(QString(image_name));
|
||||
out.append(path.toStdString());
|
||||
out.append(std::string(str) + " - " + path.toStdString());
|
||||
out.append("\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -375,59 +352,51 @@ static void printBacktrace(std::string &out) {
|
|||
const int size = 256;
|
||||
void *buffer[size];
|
||||
|
||||
// Get executable path
|
||||
char exepath[512];
|
||||
memset(exepath, 0, 512);
|
||||
#ifndef MACOSX
|
||||
if (readlink("/proc/self/exe", exepath, 512) < 0)
|
||||
fprintf(stderr, "Couldn't get exe path\n");
|
||||
#endif
|
||||
|
||||
// Back trace
|
||||
int nptrs = backtrace(buffer, size);
|
||||
char **bts = backtrace_symbols(buffer, nptrs);
|
||||
std::regex re("\\[(.+)\\]");
|
||||
if (bts) {
|
||||
for (int i = 0; i < nptrs; ++i) {
|
||||
// Skip first frames since they point to this function
|
||||
if (frameStack++ < frameSkip) continue;
|
||||
char numStr[32];
|
||||
memset(numStr, 0, sizeof(numStr));
|
||||
sprintf(numStr, "%3i> ", frameStack - frameSkip);
|
||||
out.append(numStr);
|
||||
int nptrs = backtrace(buffer, size);
|
||||
for (int i = 0; i < nptrs; ++i) {
|
||||
// Skip first frames since they point to this function
|
||||
if (frameStack++ < frameSkip) continue;
|
||||
char numStr[32];
|
||||
memset(numStr, 0, sizeof(numStr));
|
||||
sprintf(numStr, "%3i> ", frameStack - frameSkip);
|
||||
out.append(numStr);
|
||||
|
||||
std::string sym = bts[i];
|
||||
std::string line;
|
||||
std::smatch ms;
|
||||
std::string frame;
|
||||
std::string module;
|
||||
std::string addr;
|
||||
std::string line;
|
||||
std::string sym = "??? at ??:?";
|
||||
std::string module = "???";
|
||||
size_t addr = (size_t)buffer[i];
|
||||
|
||||
bool found = false;
|
||||
bool found = false;
|
||||
|
||||
Dl_info info;
|
||||
int infoFound = dladdr(buffer[i], &info);
|
||||
|
||||
if (infoFound) module = std::string(info.dli_fname);
|
||||
|
||||
#ifdef MACOSX
|
||||
QString sym2 = QString::fromStdString(sym);
|
||||
QStringList strlst = sym2.split(" ");
|
||||
strlst.removeAll({});
|
||||
|
||||
module = strlst[1].toStdString();
|
||||
addr = strlst[2].toStdString();
|
||||
#else
|
||||
module = std::string(exepath);
|
||||
if (std::regex_search(sym, ms, re))
|
||||
addr = ms[1];
|
||||
#endif
|
||||
if (addr2line(line, module.c_str(), addr.c_str())) {
|
||||
found = (line.rfind("??", 0) != 0) &&
|
||||
(line.find("cannot load symbol", 0) != 0) &&
|
||||
(line.find("command not found") != 0);
|
||||
}
|
||||
|
||||
out.append(found ? line : (sym + "\n"));
|
||||
if (module.find("Tahoma2D.app/Contents/MacOS") != std::string::npos) {
|
||||
std::string dsym = module;
|
||||
int pos = dsym.find("Contents");
|
||||
dsym.replace(pos, 14, "DSYM/Contents/Resources/DWARF");
|
||||
TFilePath file(dsym);
|
||||
if (TFileStatus(file).doesExist()) module = dsym;
|
||||
}
|
||||
}
|
||||
|
||||
free(bts);
|
||||
char addrstr[512];
|
||||
sprintf(addrstr, "%p", addr);
|
||||
sym = std::string(addrstr) + " (in " + module + ")";
|
||||
#endif
|
||||
|
||||
if (infoFound &&
|
||||
addr2line(line, module.c_str(), addr, (size_t)info.dli_fbase)) {
|
||||
found = (line.rfind("??", 0) != 0) &&
|
||||
(line.find("cannot load symbol", 0) != 0) &&
|
||||
(line.find("command not found") != 0);
|
||||
}
|
||||
|
||||
out.append(found ? line : (sym + "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void signalHandler(int sig) {
|
||||
|
@ -632,7 +601,7 @@ bool CrashHandler::trigger(const QString reason, bool showDialog) {
|
|||
bool minidump = generateMinidump(fpDump, s_exceptionPtr);
|
||||
#else
|
||||
bool minidump = generateMinidump(fpDump);
|
||||
#endif;
|
||||
#endif
|
||||
|
||||
// Generate report
|
||||
try {
|
||||
|
@ -669,9 +638,11 @@ bool CrashHandler::trigger(const QString reason, bool showDialog) {
|
|||
std::wstring sceneName = currentScene->getSceneName();
|
||||
|
||||
out.append("\nApplication Dir: ");
|
||||
out.append(obfuscateUsername(QCoreApplication::applicationDirPath()).toStdString());
|
||||
out.append(obfuscateUsername(QCoreApplication::applicationDirPath())
|
||||
.toStdString());
|
||||
out.append("\nStuff Dir: ");
|
||||
out.append(obfuscateUsername(TEnv::getStuffDir().getQString()).toStdString());
|
||||
out.append(
|
||||
obfuscateUsername(TEnv::getStuffDir().getQString()).toStdString());
|
||||
out.append("\n");
|
||||
out.append("\nProject Name: ");
|
||||
out.append(currentProject->getName().getQString().toStdString());
|
||||
|
|
Loading…
Reference in a new issue