10 #include "../../stdafx.h" 11 #include "../../crashlog.h" 12 #include "../../string_func.h" 13 #include "../../gamelog.h" 14 #include "../../saveload/saveload.h" 19 #include <mach-o/arch.h> 23 #include "../../safeguards.h" 28 #define IS_ALIGNED(addr) (((uintptr_t)(addr) & 0xf) == 8) 30 #define IS_ALIGNED(addr) (((uintptr_t)(addr) & 0xf) == 0) 35 #define PRINTF_PTR "0x%016lx" 37 #define PRINTF_PTR "0x%08lx" 40 #define MAX_STACK_FRAMES 64 55 int ver_maj, ver_min, ver_bug;
56 GetMacOSVersion(&ver_maj, &ver_min, &ver_bug);
58 const NXArchInfo *arch = NXGetLocalArchInfo();
60 return buffer +
seprintf(buffer, last,
63 " Release: %d.%d.%d\n" 66 ver_maj, ver_min, ver_bug,
67 arch !=
nullptr ? arch->description :
"unknown",
68 MAC_OS_X_VERSION_MIN_REQUIRED
72 char *
LogError(
char *buffer,
const char *last,
const char *
message)
const override 74 return buffer +
seprintf(buffer, last,
78 strsignal(this->signum),
80 message ==
nullptr ?
"<none>" : message
90 buffer +=
seprintf(buffer, last,
"\nStacktrace:\n");
93 #if defined(__ppc__) || defined(__ppc64__) 95 __asm__
volatile(
"mr %0, r1" :
"=r" (frame));
97 frame = (
void **)__builtin_frame_address(0);
100 for (
int i = 0; frame !=
nullptr && i < MAX_STACK_FRAMES; i++) {
102 #if defined(__ppc__) || defined(__ppc64__) 107 if (ip ==
nullptr)
break;
110 buffer +=
seprintf(buffer, last,
" [%02d]", i);
113 bool dl_valid = dladdr(ip, &dli) != 0;
115 const char *fname =
"???";
116 if (dl_valid && dli.dli_fname) {
118 const char *s = strrchr(dli.dli_fname,
'/');
122 fname = dli.dli_fname;
126 buffer +=
seprintf(buffer, last,
" %-20s " PRINTF_PTR, fname, (uintptr_t)ip);
129 if (dl_valid && dli.dli_sname !=
nullptr && dli.dli_saddr !=
nullptr) {
132 char *func_name = abi::__cxa_demangle(dli.dli_sname,
nullptr, 0, &status);
134 long int offset = (intptr_t)ip - (intptr_t)dli.dli_saddr;
135 buffer +=
seprintf(buffer, last,
" (%s + %ld)", func_name !=
nullptr ? func_name : dli.dli_sname, offset);
139 buffer +=
seprintf(buffer, last,
"\n");
142 void **next = (
void **)frame[0];
144 if (next <= frame || !IS_ALIGNED(next))
break;
148 return buffer +
seprintf(buffer, last,
"\n");
158 filename_log[0] =
'\0';
159 filename_save[0] =
'\0';
160 filename_screenshot[0] =
'\0';
169 printf(
"Crash encountered, generating crash log...\n");
171 printf(
"%s\n", buffer);
172 printf(
"Crash log generated.\n\n");
174 printf(
"Writing crash log to disk...\n");
176 filename_log[0] =
'\0';
180 printf(
"Writing crash savegame...\n");
182 filename_save[0] =
'\0';
186 printf(
"Writing crash savegame...\n");
188 filename_screenshot[0] =
'\0';
198 static const char crash_title[] =
199 "A serious fault condition occurred in the game. The game will shut down.";
203 "Please send the generated crash information and the last (auto)save to the developers. " 204 "This will greatly help debugging. The correct place to do this is https://github.com/OpenTTD/OpenTTD/issues.\n\n" 205 "Generated file(s):\n%s\n%s\n%s",
206 this->filename_log, this->filename_save, this->filename_screenshot);
228 ShowMacDialog(
"A serious fault condition occurred in the game. The game will shut down.",
229 "As you loaded an emergency savegame no crash information will be generated.\n",
235 ShowMacDialog(
"A serious fault condition occurred in the game. The game will shut down.",
236 "As you loaded an savegame for which you do not have the required NewGRFs no crash information will be generated.\n",
bool GamelogTestEmergency()
Finds out if current game is a loaded emergency savegame.
Helper class for creating crash logs.
char filename_save[MAX_PATH]
Path of crash.sav.
char * LogStacktrace(char *buffer, const char *last) const override
Writes the stack trace to the buffer, if there is information about it available. ...
bool WriteCrashLog(const char *buffer, char *filename, const char *filename_last) const
Write the crash log to a file.
bool MakeCrashLog()
Generate the crash log.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
void CDECL HandleCrash(int signum)
Entry point for the crash handler.
#define lastof(x)
Get the last element of an fixed size array.
static void InitialiseCrashLog()
Initialiser for crash logs; do the appropriate things so crashes are handled by our crash handler ins...
char filename_screenshot[MAX_PATH]
Path of crash.(png|bmp|pcx)
int signum
Signal that has been thrown.
static const char * message
Pointer to the error message.
char * LogOSVersion(char *buffer, const char *last) const override
Writes OS' version to the buffer.
static void AfterCrashLogCleanup()
Try to close the sound/video stuff so it doesn't keep lingering around incorrect video states or so...
bool WriteScreenshot(char *filename, const char *filename_last) const
Write the (crash) screenshot to a file.
char * LogError(char *buffer, const char *last, const char *message) const override
Writes actually encountered error to the buffer.
static const int _signals_to_handle[]
The signals we want our crash handler to handle.
bool WriteSavegame(char *filename, const char *filename_last) const
Write the (crash) savegame to a file.
OSX implementation for the crash logger.
void DisplayCrashDialog() const
Show a dialog with the crash information.
CrashLogOSX(int signum)
A crash log is always generated by signal.
#define endof(x)
Get the end element of an fixed size array.
void ShowMacDialog(const char *title, const char *message, const char *button_label)
Helper function displaying a message the best possible way.
Functions related to MacOS support.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
bool SaveloadCrashWithMissingNewGRFs()
Did loading the savegame cause a crash? If so, were NewGRFs missing?
char * FillCrashLog(char *buffer, const char *last) const
Fill the crash log buffer with all data of a crash log.
char filename_log[MAX_PATH]
Path of crash.log.