UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
unix_main.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 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 
59 const 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 
78 void Sys_Error (const char* error, ...)
79 {
80  va_list argptr;
81  char string[1024];
82 
83  Sys_Backtrace();
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
93  Mem_Shutdown();
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 
109 void 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
124 static 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 
145 struct file_match {
146  const char* file;
147  void* address;
148  void* base;
149  void* hdr;
150 };
151 
152 #define BUFFER_MAX (16*1024)
153 static char g_output[BUFFER_MAX];
154 
155 static 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 
179 static 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 
230 void 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 
271 #ifdef COMPILE_UFO
272  Com_UploadCrashDump(dumpFile);
273 #endif
274 }
void Com_BreakIntoDebugger(void)
Definition: common.cpp:470
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
Definition: shared.cpp:535
void Sys_Quit(void)
Definition: unix_main.cpp:109
const char * Sys_GetCurrentUser(void)
Definition: unix_main.cpp:59
void Mem_Shutdown(void)
Definition: mem.cpp:603
#define CPUSTRING
Definition: common.h:109
#define FILE
Definition: test_webapi.cpp:30
void Sys_Error(const char *error,...)
Errors out of the game.
Definition: unix_main.cpp:78
#define UFO_VERSION
Definition: common.h:36
GLsizei size
Definition: r_gl.h:152
#define MAX_VAR
Definition: shared.h:36
#define BUILDSTRING
Definition: common.h:121
void Sys_Backtrace(void)
On platforms supporting it, print a backtrace.
Definition: unix_main.cpp:230
void Com_UploadCrashDump(const char *crashDumpFile)
Definition: common.cpp:683
QGL_EXTERN GLint i
Definition: r_gl.h:113
void CL_Shutdown(void)
Saves configuration file and shuts the client systems down.
Definition: cl_main.cpp:1220
void Qcommon_Shutdown(void)
Definition: common.cpp:1537
#define UFO_SIZE_T
Definition: ufotypes.h:89
void Sys_ConsoleShutdown(void)
FILE * Sys_Fopen(const char *filename, const char *mode)
Definition: unix_files.cpp:240
GLsizei const GLvoid * data
Definition: r_gl.h:152