10 #include "../../stdafx.h" 11 #include "../../crashlog.h" 12 #include "../../string_func.h" 13 #include "../../gamelog.h" 14 #include "../../saveload/saveload.h" 15 #include "../../video/video_driver.hpp" 20 #include <mach-o/arch.h> 24 #include "../../safeguards.h" 29 #define IS_ALIGNED(addr) (((uintptr_t)(addr) & 0xf) == 8) 31 #define IS_ALIGNED(addr) (((uintptr_t)(addr) & 0xf) == 0) 36 #define PRINTF_PTR "0x%016lx" 38 #define PRINTF_PTR "0x%08lx" 41 #define MAX_STACK_FRAMES 64 56 int ver_maj, ver_min, ver_bug;
57 GetMacOSVersion(&ver_maj, &ver_min, &ver_bug);
59 const NXArchInfo *arch = NXGetLocalArchInfo();
61 return buffer +
seprintf(buffer, last,
64 " Release: %d.%d.%d\n" 67 ver_maj, ver_min, ver_bug,
68 arch !=
nullptr ? arch->description :
"unknown",
69 MAC_OS_X_VERSION_MIN_REQUIRED
73 char *
LogError(
char *buffer,
const char *last,
const char *
message)
const override 75 return buffer +
seprintf(buffer, last,
79 strsignal(this->signum),
81 message ==
nullptr ?
"<none>" : message
91 buffer +=
seprintf(buffer, last,
"\nStacktrace:\n");
94 #if defined(__ppc__) || defined(__ppc64__) 96 __asm__
volatile(
"mr %0, r1" :
"=r" (frame));
98 frame = (
void **)__builtin_frame_address(0);
101 for (
int i = 0; frame !=
nullptr && i < MAX_STACK_FRAMES; i++) {
103 #if defined(__ppc__) || defined(__ppc64__) 108 if (ip ==
nullptr)
break;
111 buffer +=
seprintf(buffer, last,
" [%02d]", i);
114 bool dl_valid = dladdr(ip, &dli) != 0;
116 const char *fname =
"???";
117 if (dl_valid && dli.dli_fname) {
119 const char *s = strrchr(dli.dli_fname,
'/');
123 fname = dli.dli_fname;
127 buffer +=
seprintf(buffer, last,
" %-20s " PRINTF_PTR, fname, (uintptr_t)ip);
130 if (dl_valid && dli.dli_sname !=
nullptr && dli.dli_saddr !=
nullptr) {
133 char *func_name = abi::__cxa_demangle(dli.dli_sname,
nullptr, 0, &status);
135 long int offset = (intptr_t)ip - (intptr_t)dli.dli_saddr;
136 buffer +=
seprintf(buffer, last,
" (%s + %ld)", func_name !=
nullptr ? func_name : dli.dli_sname, offset);
140 buffer +=
seprintf(buffer, last,
"\n");
143 void **next = (
void **)frame[0];
145 if (next <= frame || !IS_ALIGNED(next))
break;
149 return buffer +
seprintf(buffer, last,
"\n");
159 filename_log[0] =
'\0';
160 filename_save[0] =
'\0';
161 filename_screenshot[0] =
'\0';
170 printf(
"Crash encountered, generating crash log...\n");
172 printf(
"%s\n", buffer);
173 printf(
"Crash log generated.\n\n");
175 printf(
"Writing crash log to disk...\n");
177 filename_log[0] =
'\0';
181 printf(
"Writing crash savegame...\n");
183 filename_save[0] =
'\0';
187 printf(
"Writing crash savegame...\n");
189 filename_screenshot[0] =
'\0';
199 static const char crash_title[] =
200 "A serious fault condition occurred in the game. The game will shut down.";
204 "Please send the generated crash information and the last (auto)save to the developers. " 205 "This will greatly help debugging. The correct place to do this is https://github.com/OpenTTD/OpenTTD/issues.\n\n" 206 "Generated file(s):\n%s\n%s\n%s",
207 this->filename_log, this->filename_save, this->filename_screenshot);
229 ShowMacDialog(
"A serious fault condition occurred in the game. The game will shut down.",
230 "As you loaded an emergency savegame no crash information will be generated.\n",
236 ShowMacDialog(
"A serious fault condition occurred in the game. The game will shut down.",
237 "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.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
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.