|
|
|
@@ -47,324 +47,325 @@
|
|
|
|
|
using namespace Shared::Util;
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
namespace Shared{ namespace Platform{
|
|
|
|
|
namespace Shared {
|
|
|
|
|
namespace Platform {
|
|
|
|
|
string PlatformExceptionHandler::application_binary="";
|
|
|
|
|
bool PlatformExceptionHandler::disableBacktrace = false;
|
|
|
|
|
|
|
|
|
|
string PlatformExceptionHandler::application_binary="";
|
|
|
|
|
bool PlatformExceptionHandler::disableBacktrace = false;
|
|
|
|
|
const char * getDialogCommand() {
|
|
|
|
|
|
|
|
|
|
const char * getDialogCommand() {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (::system(NULL)) {
|
|
|
|
|
if (::system("which gdialog") == 0)
|
|
|
|
|
return "gdialog";
|
|
|
|
|
else if (::system("which kdialog") == 0)
|
|
|
|
|
return "kdialog";
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
FILE *file;
|
|
|
|
|
char file_string [100];
|
|
|
|
|
|
|
|
|
|
file = popen("which zenity","r");
|
|
|
|
|
//printf("File #1 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "zenity";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file = popen("which kdialog","r");
|
|
|
|
|
//printf("File #2 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "kdialog";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file = popen("which yad","r");
|
|
|
|
|
//printf("File #3 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "yad";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file = popen("which gdialog","r");
|
|
|
|
|
//printf("File #4 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "gdialog";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool showMessage(std::string warning,const string &writepath) {
|
|
|
|
|
bool guiMessage = false;
|
|
|
|
|
const char * dialogCommand = getDialogCommand();
|
|
|
|
|
if (dialogCommand) {
|
|
|
|
|
std::string command = dialogCommand;
|
|
|
|
|
|
|
|
|
|
string text_file = writepath + "/mg_dialog_text.txt";
|
|
|
|
|
{
|
|
|
|
|
FILE *fp = fopen(text_file.c_str(),"wt");
|
|
|
|
|
if (fp != NULL) {
|
|
|
|
|
fputs(warning.c_str(),fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
/*
|
|
|
|
|
if (::system(NULL)) {
|
|
|
|
|
if (::system("which gdialog") == 0)
|
|
|
|
|
return "gdialog";
|
|
|
|
|
else if (::system("which kdialog") == 0)
|
|
|
|
|
return "kdialog";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
FILE *file;
|
|
|
|
|
char file_string [100];
|
|
|
|
|
|
|
|
|
|
//command += " --title \"Error\" --msgbox \"`printf \"" + warning + "\"`\"";
|
|
|
|
|
command += " --title \"Error\" ";
|
|
|
|
|
|
|
|
|
|
if (!strcmp(dialogCommand, "kdialog")) {
|
|
|
|
|
command += "--textbox " + text_file + " 640 360";
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp(dialogCommand, "yad")) {
|
|
|
|
|
command += "--text-info --center --wrap --width 640 --height 360 --filename=" + text_file;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
command += "--text-info --width 640 --height 360 --filename=" + text_file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//printf("\n\n\nzenity command [%s]\n\n\n",command.c_str());
|
|
|
|
|
|
|
|
|
|
FILE *fp = popen(command.c_str(),"r");
|
|
|
|
|
if (fp != 0) {
|
|
|
|
|
guiMessage = true;
|
|
|
|
|
pclose(fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return guiMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void message(const string &message, bool isNonGraphicalModeEnabled,const string &writepath) {
|
|
|
|
|
std::cerr << "\n\n\n";
|
|
|
|
|
std::cerr << "******************************************************\n";
|
|
|
|
|
std::cerr << " " << message << "\n";
|
|
|
|
|
std::cerr << "******************************************************\n";
|
|
|
|
|
std::cerr << "\n\n\n";
|
|
|
|
|
|
|
|
|
|
if(isNonGraphicalModeEnabled == false) {
|
|
|
|
|
showMessage(message,writepath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void exceptionMessage(const exception &excp) {
|
|
|
|
|
std::cerr << "Exception: " << excp.what() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(HAS_GCC_BACKTRACE)
|
|
|
|
|
static int getFileAndLine(char *function, void *address, char *file, size_t flen) {
|
|
|
|
|
int line=-1;
|
|
|
|
|
if(PlatformExceptionHandler::application_binary != "") {
|
|
|
|
|
const int maxbufSize = 8096;
|
|
|
|
|
char buf[maxbufSize+1]="";
|
|
|
|
|
|
|
|
|
|
// prepare command to be executed
|
|
|
|
|
// our program need to be passed after the -e parameter
|
|
|
|
|
#if __APPLE_CC__
|
|
|
|
|
snprintf(buf, 8096,"xcrun atos -v -o %s %p",PlatformExceptionHandler::application_binary.c_str(),address);
|
|
|
|
|
fprintf(stderr,"> %s\n",buf);
|
|
|
|
|
#else
|
|
|
|
|
snprintf(buf, 8096,"addr2line -C -e %s -f -i %p",PlatformExceptionHandler::application_binary.c_str(),address);
|
|
|
|
|
#endif
|
|
|
|
|
FILE* f = popen (buf, "r");
|
|
|
|
|
if (f == NULL) {
|
|
|
|
|
perror (buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#if __APPLE_CC__
|
|
|
|
|
//### TODO Will: still working this out
|
|
|
|
|
int len = fread(buf,1,maxbufSize,f);
|
|
|
|
|
pclose(f);
|
|
|
|
|
buf[len] = 0;
|
|
|
|
|
fprintf(stderr,"< %s",buf);
|
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
|
|
|
|
for(;function != NULL && function[0] != '\0';) {
|
|
|
|
|
// get function name
|
|
|
|
|
char *ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
//printf("Looking for [%s] Found [%s]\n",function,ret);
|
|
|
|
|
if(strstr(ret,function) != NULL) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// get file and line
|
|
|
|
|
ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strlen(buf) > 0 && buf[0] != '?') {
|
|
|
|
|
//int l;
|
|
|
|
|
char *p = buf;
|
|
|
|
|
// file name is until ':'
|
|
|
|
|
while(*p != 0 && *p != ':') {
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
// after file name follows line number
|
|
|
|
|
strcpy (file , buf);
|
|
|
|
|
sscanf (p,"%10d", &line);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
strcpy (file,"unknown");
|
|
|
|
|
line = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get file and line
|
|
|
|
|
char *ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
file = popen("which zenity","r");
|
|
|
|
|
//printf("File #1 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "zenity";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(strlen(buf) > 0 && buf[0] != '?') {
|
|
|
|
|
//int l;
|
|
|
|
|
char *p = buf;
|
|
|
|
|
file = popen("which kdialog","r");
|
|
|
|
|
//printf("File #2 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "kdialog";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// file name is until ':'
|
|
|
|
|
while(*p != 0 && *p != ':') {
|
|
|
|
|
p++;
|
|
|
|
|
file = popen("which yad","r");
|
|
|
|
|
//printf("File #3 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "yad";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
file = popen("which gdialog","r");
|
|
|
|
|
//printf("File #4 [%p]\n",file);
|
|
|
|
|
if (file != NULL) {
|
|
|
|
|
if (fgets(file_string, 100, file) != NULL ) {
|
|
|
|
|
pclose(file);
|
|
|
|
|
return "gdialog";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pclose(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool showMessage(std::string warning,const string &writepath) {
|
|
|
|
|
bool guiMessage = false;
|
|
|
|
|
const char * dialogCommand = getDialogCommand();
|
|
|
|
|
if (dialogCommand) {
|
|
|
|
|
std::string command = dialogCommand;
|
|
|
|
|
|
|
|
|
|
string text_file = writepath + "/mg_dialog_text.txt";
|
|
|
|
|
{
|
|
|
|
|
FILE *fp = fopen(text_file.c_str(),"wt");
|
|
|
|
|
if (fp != NULL) {
|
|
|
|
|
fputs(warning.c_str(),fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
// after file name follows line number
|
|
|
|
|
strcpy (file , buf);
|
|
|
|
|
sscanf (p,"%10d", &line);
|
|
|
|
|
//command += " --title \"Error\" --msgbox \"`printf \"" + warning + "\"`\"";
|
|
|
|
|
command += " --title \"Error\" ";
|
|
|
|
|
|
|
|
|
|
if (!strcmp(dialogCommand, "kdialog")) {
|
|
|
|
|
command += "--textbox " + text_file + " 640 360";
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp(dialogCommand, "yad")) {
|
|
|
|
|
command += "--text-info --center --wrap --width 640 --height 360 --filename=" + text_file;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
command += "--text-info --width 640 --height 360 --filename=" + text_file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//printf("\n\n\nzenity command [%s]\n\n\n",command.c_str());
|
|
|
|
|
|
|
|
|
|
FILE *fp = popen(command.c_str(),"r");
|
|
|
|
|
if (fp != 0) {
|
|
|
|
|
guiMessage = true;
|
|
|
|
|
pclose(fp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
strcpy (file,"unknown");
|
|
|
|
|
line = 0;
|
|
|
|
|
|
|
|
|
|
return guiMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void message(const string &message, bool isNonGraphicalModeEnabled,const string &writepath) {
|
|
|
|
|
std::cerr << "\n\n\n";
|
|
|
|
|
std::cerr << "******************************************************\n";
|
|
|
|
|
std::cerr << " " << message << "\n";
|
|
|
|
|
std::cerr << "******************************************************\n";
|
|
|
|
|
std::cerr << "\n\n\n";
|
|
|
|
|
|
|
|
|
|
if(isNonGraphicalModeEnabled == false) {
|
|
|
|
|
showMessage(message,writepath);
|
|
|
|
|
}
|
|
|
|
|
pclose(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
void exceptionMessage(const exception &excp) {
|
|
|
|
|
std::cerr << "Exception: " << excp.what() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string PlatformExceptionHandler::getStackTrace() {
|
|
|
|
|
string errMsg = "\nStack Trace:\n";
|
|
|
|
|
if(PlatformExceptionHandler::disableBacktrace == true) {
|
|
|
|
|
errMsg += "disabled...";
|
|
|
|
|
return errMsg;
|
|
|
|
|
}
|
|
|
|
|
#if defined(HAS_GCC_BACKTRACE)
|
|
|
|
|
static int getFileAndLine(char *function, void *address, char *file, size_t flen) {
|
|
|
|
|
int line=-1;
|
|
|
|
|
if(PlatformExceptionHandler::application_binary != "") {
|
|
|
|
|
const int maxbufSize = 8096;
|
|
|
|
|
char buf[maxbufSize+1]="";
|
|
|
|
|
|
|
|
|
|
#if defined(HAS_GCC_BACKTRACE)
|
|
|
|
|
// if(disableBacktrace == false && sdl_quitCalled == false) {
|
|
|
|
|
//errMsg = "\nStack Trace:\n";
|
|
|
|
|
//errMsg += "To find line #'s use:\n";
|
|
|
|
|
//errMsg += "readelf --debug-dump=decodedline %s | egrep 0xaddress-of-stack\n";
|
|
|
|
|
// prepare command to be executed
|
|
|
|
|
// our program need to be passed after the -e parameter
|
|
|
|
|
#if __APPLE_CC__
|
|
|
|
|
snprintf(buf, 8096,"xcrun atos -v -o %s %p",PlatformExceptionHandler::application_binary.c_str(),address);
|
|
|
|
|
fprintf(stderr,"> %s\n",buf);
|
|
|
|
|
#else
|
|
|
|
|
snprintf(buf, 8096,"addr2line -C -e %s -f -i %p",PlatformExceptionHandler::application_binary.c_str(),address);
|
|
|
|
|
#endif
|
|
|
|
|
FILE* f = popen (buf, "r");
|
|
|
|
|
if (f == NULL) {
|
|
|
|
|
perror (buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#if __APPLE_CC__
|
|
|
|
|
//### TODO Will: still working this out
|
|
|
|
|
int len = fread(buf,1,maxbufSize,f);
|
|
|
|
|
pclose(f);
|
|
|
|
|
buf[len] = 0;
|
|
|
|
|
fprintf(stderr,"< %s",buf);
|
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
|
|
|
|
for(;function != NULL && function[0] != '\0';) {
|
|
|
|
|
// get function name
|
|
|
|
|
char *ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
//printf("Looking for [%s] Found [%s]\n",function,ret);
|
|
|
|
|
if(strstr(ret,function) != NULL) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// get file and line
|
|
|
|
|
ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const size_t max_depth = 25;
|
|
|
|
|
void *stack_addrs[max_depth];
|
|
|
|
|
size_t stack_depth = backtrace(stack_addrs, max_depth);
|
|
|
|
|
char **stack_strings = backtrace_symbols(stack_addrs, stack_depth);
|
|
|
|
|
//for (size_t i = 1; i < stack_depth; i++) {
|
|
|
|
|
// errMsg += string(stack_strings[i]) + "\n";
|
|
|
|
|
//}
|
|
|
|
|
if(strlen(buf) > 0 && buf[0] != '?') {
|
|
|
|
|
//int l;
|
|
|
|
|
char *p = buf;
|
|
|
|
|
// file name is until ':'
|
|
|
|
|
while(*p != 0 && *p != ':') {
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
// after file name follows line number
|
|
|
|
|
strcpy (file , buf);
|
|
|
|
|
sscanf (p,"%10d", &line);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
strcpy (file,"unknown");
|
|
|
|
|
line = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char szBuf[8096]="";
|
|
|
|
|
string strBuf = "";
|
|
|
|
|
for(size_t i = 1; i < stack_depth; i++) {
|
|
|
|
|
void *lineAddress = stack_addrs[i]; //getStackAddress(stackIndex);
|
|
|
|
|
// get file and line
|
|
|
|
|
char *ret = fgets (buf, maxbufSize, f);
|
|
|
|
|
if(ret == NULL) {
|
|
|
|
|
pclose(f);
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t sz = 8096; // just a guess, template names will go much wider
|
|
|
|
|
char *function = static_cast<char *>(malloc(sz));
|
|
|
|
|
function[0] = '\0';
|
|
|
|
|
char *begin = 0;
|
|
|
|
|
char *end = 0;
|
|
|
|
|
if(strlen(buf) > 0 && buf[0] != '?') {
|
|
|
|
|
//int l;
|
|
|
|
|
char *p = buf;
|
|
|
|
|
|
|
|
|
|
// find the parentheses and address offset surrounding the mangled name
|
|
|
|
|
for (char *j = stack_strings[i]; *j; ++j) {
|
|
|
|
|
if (*j == '(') {
|
|
|
|
|
begin = j;
|
|
|
|
|
}
|
|
|
|
|
else if (*j == '+') {
|
|
|
|
|
end = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (begin && end) {
|
|
|
|
|
*begin++ = '\0';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
// found our mangled name, now in [begin, end)
|
|
|
|
|
// file name is until ':'
|
|
|
|
|
while(*p != 0 && *p != ':') {
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int status;
|
|
|
|
|
char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
|
|
|
|
|
if (ret) {
|
|
|
|
|
// return value may be a realloc() of the input
|
|
|
|
|
function = ret;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// demangling failed, just pretend it's a C function with no args
|
|
|
|
|
strncpy(function, begin, sz);
|
|
|
|
|
strncat(function, "()", sz);
|
|
|
|
|
function[sz-1] = '\0';
|
|
|
|
|
}
|
|
|
|
|
//fprintf(out, " %s:%s\n", stack.strings[i], function);
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
// after file name follows line number
|
|
|
|
|
strcpy (file , buf);
|
|
|
|
|
sscanf (p,"%10d", &line);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
strcpy (file,"unknown");
|
|
|
|
|
line = 0;
|
|
|
|
|
}
|
|
|
|
|
pclose(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strBuf = string(stack_strings[i]) + ":" + string(function);
|
|
|
|
|
snprintf(szBuf,8096,"address [%p]",lineAddress);
|
|
|
|
|
strBuf += szBuf;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// didn't find the mangled name, just print the whole line
|
|
|
|
|
//fprintf(out, " %s\n", stack.strings[i]);
|
|
|
|
|
strBuf = stack_strings[i];
|
|
|
|
|
snprintf(szBuf,8096,"address [%p]",lineAddress);
|
|
|
|
|
strBuf += szBuf;
|
|
|
|
|
}
|
|
|
|
|
return line;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//errMsg += string(szBuf);
|
|
|
|
|
errMsg += strBuf;
|
|
|
|
|
char file[8096]="";
|
|
|
|
|
int line = getFileAndLine(function, lineAddress, file, 8096);
|
|
|
|
|
if(line >= 0) {
|
|
|
|
|
errMsg += " line: " + intToStr(line);
|
|
|
|
|
}
|
|
|
|
|
errMsg += "\n";
|
|
|
|
|
string PlatformExceptionHandler::getStackTrace() {
|
|
|
|
|
string errMsg = "\nStack Trace:\n";
|
|
|
|
|
if(PlatformExceptionHandler::disableBacktrace == true) {
|
|
|
|
|
errMsg += "disabled...";
|
|
|
|
|
return errMsg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(function);
|
|
|
|
|
}
|
|
|
|
|
#if defined(HAS_GCC_BACKTRACE)
|
|
|
|
|
// if(disableBacktrace == false && sdl_quitCalled == false) {
|
|
|
|
|
//errMsg = "\nStack Trace:\n";
|
|
|
|
|
//errMsg += "To find line #'s use:\n";
|
|
|
|
|
//errMsg += "readelf --debug-dump=decodedline %s | egrep 0xaddress-of-stack\n";
|
|
|
|
|
|
|
|
|
|
free(stack_strings); // malloc()ed by backtrace_symbols
|
|
|
|
|
#endif
|
|
|
|
|
const size_t max_depth = 25;
|
|
|
|
|
void *stack_addrs[max_depth];
|
|
|
|
|
size_t stack_depth = backtrace(stack_addrs, max_depth);
|
|
|
|
|
char **stack_strings = backtrace_symbols(stack_addrs, stack_depth);
|
|
|
|
|
//for (size_t i = 1; i < stack_depth; i++) {
|
|
|
|
|
// errMsg += string(stack_strings[i]) + "\n";
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
return errMsg;
|
|
|
|
|
}
|
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
|
|
|
|
|
|
game_runtime_error::game_runtime_error(const string& __arg,bool noStackTrace)
|
|
|
|
|
: std::runtime_error(noStackTrace == false ? __arg + PlatformExceptionHandler::getStackTrace() : __arg), noStackTrace(noStackTrace) {
|
|
|
|
|
}
|
|
|
|
|
char szBuf[8096]="";
|
|
|
|
|
string strBuf = "";
|
|
|
|
|
for(size_t i = 1; i < stack_depth; i++) {
|
|
|
|
|
void *lineAddress = stack_addrs[i]; //getStackAddress(stackIndex);
|
|
|
|
|
|
|
|
|
|
}}//end namespace
|
|
|
|
|
size_t sz = 8096; // just a guess, template names will go much wider
|
|
|
|
|
char *function = static_cast<char *>(malloc(sz));
|
|
|
|
|
function[0] = '\0';
|
|
|
|
|
char *begin = 0;
|
|
|
|
|
char *end = 0;
|
|
|
|
|
|
|
|
|
|
// find the parentheses and address offset surrounding the mangled name
|
|
|
|
|
for (char *j = stack_strings[i]; *j; ++j) {
|
|
|
|
|
if (*j == '(') {
|
|
|
|
|
begin = j;
|
|
|
|
|
}
|
|
|
|
|
else if (*j == '+') {
|
|
|
|
|
end = j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (begin && end) {
|
|
|
|
|
*begin++ = '\0';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
// found our mangled name, now in [begin, end)
|
|
|
|
|
|
|
|
|
|
int status;
|
|
|
|
|
char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
|
|
|
|
|
if (ret) {
|
|
|
|
|
// return value may be a realloc() of the input
|
|
|
|
|
function = ret;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// demangling failed, just pretend it's a C function with no args
|
|
|
|
|
strncpy(function, begin, sz);
|
|
|
|
|
strncat(function, "()", sz);
|
|
|
|
|
function[sz-1] = '\0';
|
|
|
|
|
}
|
|
|
|
|
//fprintf(out, " %s:%s\n", stack.strings[i], function);
|
|
|
|
|
|
|
|
|
|
strBuf = string(stack_strings[i]) + ":" + string(function);
|
|
|
|
|
snprintf(szBuf,8096,"address [%p]",lineAddress);
|
|
|
|
|
strBuf += szBuf;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// didn't find the mangled name, just print the whole line
|
|
|
|
|
//fprintf(out, " %s\n", stack.strings[i]);
|
|
|
|
|
strBuf = stack_strings[i];
|
|
|
|
|
snprintf(szBuf,8096,"address [%p]",lineAddress);
|
|
|
|
|
strBuf += szBuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//errMsg += string(szBuf);
|
|
|
|
|
errMsg += strBuf;
|
|
|
|
|
char file[8096]="";
|
|
|
|
|
int line = getFileAndLine(function, lineAddress, file, 8096);
|
|
|
|
|
if(line >= 0) {
|
|
|
|
|
errMsg += " line: " + intToStr(line);
|
|
|
|
|
}
|
|
|
|
|
errMsg += "\n";
|
|
|
|
|
|
|
|
|
|
free(function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(stack_strings); // malloc()ed by backtrace_symbols
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return errMsg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
game_runtime_error::game_runtime_error(const string& __arg,bool noStackTrace)
|
|
|
|
|
: std::runtime_error(noStackTrace == false ? __arg + PlatformExceptionHandler::getStackTrace() : __arg), noStackTrace(noStackTrace) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
} //end namespace
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|