UFO: Alien Invasion
Loading...
Searching...
No Matches
unix_main.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include <unistd.h>
27#include <sys/time.h>
28#include <stdlib.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <pwd.h>
32#include <dlfcn.h>
33#include <fcntl.h>
34#include <locale.h>
35#include <signal.h>
36#include <dirent.h>
37
38#include "../../common/common.h"
39#include "../system.h"
40
41#ifdef HAVE_EXECINFO_H
42#include <execinfo.h>
43#define MAX_BACKTRACE_SYMBOLS 50
44#endif
45
46#ifdef HAVE_SYS_UTSNAME_H
47#include <sys/utsname.h>
48#endif
49
50#ifdef HAVE_LINK_H
51#include <link.h>
52#endif
53
54#ifndef COMPILE_UFO
55#undef HAVE_BFD_H
56#endif
57#include "../../shared/bfd.h"
58
59const char* Sys_GetCurrentUser (void)
60{
61 static char s_userName[MAX_VAR];
62 const struct passwd* p;
63
64 if ((p = getpwuid(getuid())) == nullptr)
65 s_userName[0] = '\0';
66 else {
67 strncpy(s_userName, p->pw_name, sizeof(s_userName));
68 s_userName[sizeof(s_userName) - 1] = '\0';
69 }
70 return s_userName;
71}
72
78void Sys_Error (const char* error, ...)
79{
80 va_list argptr;
81 char string[1024];
82
84
85#ifdef COMPILE_UFO
87#endif
88
89 /* change stdin to non blocking */
90 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
91
92#ifdef COMPILE_MAP
94#endif
95
96 va_start(argptr,error);
97 Q_vsnprintf(string, sizeof(string), error, argptr);
98 va_end(argptr);
99
100 fprintf(stderr, "Error: %s\n", string);
101
102 exit(1);
103}
104
109void Sys_Quit (void)
110{
111#ifdef COMPILE_UFO
112 CL_Shutdown();
115#elif COMPILE_MAP
116 Mem_Shutdown();
117#endif
118
119 fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~FNDELAY);
120 exit(0);
121}
122
123#ifdef HAVE_LINK_H
124static int Sys_BacktraceLibsCallback (struct dl_phdr_info* info, size_t size, void* data)
125{
126 FILE* crash = (FILE*)data;
127
128 int end = 0;
129
130 if (!info->dlpi_name || !info->dlpi_name[0])
131 return 0;
132
133 for (int j = 0; j < info->dlpi_phnum; j++) {
134 end += info->dlpi_phdr[j].p_memsz;
135 }
136
137 fprintf(crash, "[0x" UFO_SIZE_T "x-0x" UFO_SIZE_T "x] %s\n", info->dlpi_addr, info->dlpi_addr + end, info->dlpi_name);
138 return 0;
139}
140
141#ifdef HAVE_BFD_H
142
143/* following code parts are taken from libcairo */
144
145struct file_match {
146 const char* file;
147 void* address;
148 void* base;
149 void* hdr;
150};
151
152#define BUFFER_MAX (16*1024)
153static char g_output[BUFFER_MAX];
154
155static int find_matching_file (struct dl_phdr_info* info, size_t size, void* data)
156{
157#ifdef ElfW
158 typedef ElfW(Phdr) Elf_Phdr;
159 typedef ElfW(Addr) Elf_Addr;
160#endif
161
162 struct file_match* match = (file_match*)data;
163 /* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
164 Elf_Addr const load_base = info->dlpi_addr;
165 Elf_Phdr const* phdr = info->dlpi_phdr;
166 for (long n = info->dlpi_phnum; --n >= 0; phdr++) {
167 if (phdr->p_type == PT_LOAD) {
168 Elf_Addr vaddr = phdr->p_vaddr + load_base;
169 if (match->address >= (void*)vaddr && match->address < (void*)(vaddr + phdr->p_memsz)) {
170 /* we found a match */
171 match->file = info->dlpi_name;
172 match->base = (void*)info->dlpi_addr;
173 }
174 }
175 }
176 return 0;
177}
178
179static void _backtrace (FILE* crash, void* const* buffer, int size)
180{
181 struct bfd_set* set = (bfd_set*)calloc(1, sizeof(*set));
182 struct output_buffer ob;
183
184 output_init(&ob, g_output, sizeof(g_output));
185
186 bfd_init();
187
188 for (int x = 0; x < size; x++) {
189 struct file_match match = {(const char*)buffer[x], nullptr, nullptr, nullptr};
190 const char* file = nullptr;
191 const char* func = nullptr;
192 unsigned line = 0;
193 const char* procname;
194
195 dl_iterate_phdr(find_matching_file, &match);
196 const unsigned long addr = (char*)buffer[x] - (char*)match.base;
197
198 if (match.file && strlen(match.file))
199 procname = match.file;
200 else
201 procname = "/proc/self/exe";
202
203 struct bfd_ctx* bc = get_bc(&ob, set, procname);
204 if (bc) {
205 find(bc, addr, &file, &func, &line);
206 procname = bc->handle->filename;
207 }
208
209 if (func == nullptr) {
210 output_print(&ob, "0x%x : %s : %s \n",
211 addr, procname == nullptr ? "unknown" : procname, file == nullptr ? "unknown" : file);
212 } else {
213 output_print(&ob, "0x%x : %s : %s (%d) : in function (%s) \n",
214 addr, procname == nullptr ? "unknown" : procname, file == nullptr ? "unknown" : file, line, func);
215 }
216 }
217
218 fprintf(crash, "%s", g_output);
219
220 release_set(set);
221}
222
223#endif
224
225#endif
226
230void Sys_Backtrace (void)
231{
232#ifdef COMPILE_UFO
234#endif
235
236 const char* dumpFile = "crashdump.txt";
237 FILE* file = Sys_Fopen(dumpFile, "w");
238 FILE* crash = file != nullptr ? file : stderr;
239
240 fprintf(crash, "======start======\n");
241
242#ifdef HAVE_SYS_UTSNAME_H
243 struct utsname info;
244 uname(&info);
245 fprintf(crash, "OS Info: %s %s %s %s %s\n", info.sysname, info.nodename, info.release, info.version, info.machine);
246#endif
247
248 fprintf(crash, BUILDSTRING ", cpu: " CPUSTRING ", version: " UFO_VERSION "\n\n");
249 fflush(crash);
250
251#ifdef HAVE_EXECINFO_H
252 void* symbols[MAX_BACKTRACE_SYMBOLS];
253 const int i = backtrace(symbols, MAX_BACKTRACE_SYMBOLS);
254#if defined HAVE_LINK_H && defined HAVE_BFD_H
255 _backtrace(crash, symbols, i);
256#else
257 backtrace_symbols_fd(symbols, i, fileno(crash));
258#endif
259#endif
260
261#ifdef HAVE_LINK_H
262 fprintf(crash, "Loaded libraries:\n");
263 dl_iterate_phdr(Sys_BacktraceLibsCallback, crash);
264#endif
265
266 fprintf(crash, "======end========\n");
267
268 if (file != nullptr)
269 fclose(file);
270}
void Sys_ConsoleShutdown(void)
void CL_Shutdown(void)
Saves configuration file and shuts the client systems down.
Definition cl_main.cpp:1219
void Com_BreakIntoDebugger(void)
Definition common.cpp:512
void Qcommon_Shutdown(void)
Definition common.cpp:1555
definitions common between client and server, but not game lib
#define CPUSTRING
Definition common.h:109
#define UFO_VERSION
Definition common.h:36
#define BUILDSTRING
Definition common.h:121
voidpf void uLong size
Definition ioapi.h:42
void Mem_Shutdown(void)
Definition mem.cpp:518
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
QGL_EXTERN GLint i
Definition r_gl.h:113
#define MAX_VAR
Definition shared.h:36
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
Definition shared.cpp:535
System specific stuff.
FILE * Sys_Fopen(const char *filename, const char *mode)
#define FILE
#define UFO_SIZE_T
Definition ufotypes.h:89
void Sys_Backtrace(void)
On platforms supporting it, print a backtrace.
void Sys_Error(const char *error,...)
Errors out of the game.
Definition unix_main.cpp:78
void Sys_Quit(void)
const char * Sys_GetCurrentUser(void)
Definition unix_main.cpp:59