30 #include <sys/types.h>
38 #include "../../common/common.h"
39 #include "../system.h"
41 #ifdef HAVE_EXECINFO_H
43 #define MAX_BACKTRACE_SYMBOLS 50
46 #ifdef HAVE_SYS_UTSNAME_H
47 #include <sys/utsname.h>
57 #include "../../shared/bfd.h"
61 static char s_userName[
MAX_VAR];
62 const struct passwd* p;
64 if ((p = getpwuid(getuid())) ==
nullptr)
67 strncpy(s_userName, p->pw_name,
sizeof(s_userName));
68 s_userName[
sizeof(s_userName) - 1] =
'\0';
90 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
96 va_start(argptr,error);
100 fprintf(stderr,
"Error: %s\n",
string);
119 fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~FNDELAY);
124 static int Sys_BacktraceLibsCallback (
struct dl_phdr_info* info,
size_t size,
void*
data)
130 if (!info->dlpi_name || !info->dlpi_name[0])
133 for (
int j = 0; j < info->dlpi_phnum; j++) {
134 end += info->dlpi_phdr[j].p_memsz;
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);
152 #define BUFFER_MAX (16*1024)
153 static char g_output[BUFFER_MAX];
155 static int find_matching_file (
struct dl_phdr_info* info,
size_t size,
void* data)
158 typedef ElfW(Phdr) Elf_Phdr;
159 typedef ElfW(Addr) Elf_Addr;
162 struct file_match* match = (file_match*)data;
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)) {
171 match->file = info->dlpi_name;
172 match->base = (
void*)info->dlpi_addr;
179 static void _backtrace (
FILE* crash,
void*
const* buffer,
int size)
181 struct bfd_set* set = (bfd_set*)calloc(1,
sizeof(*set));
182 struct output_buffer ob;
184 output_init(&ob, g_output,
sizeof(g_output));
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;
193 const char* procname;
195 dl_iterate_phdr(find_matching_file, &match);
196 const unsigned long addr = (
char*)buffer[x] - (
char*)match.base;
198 if (match.file && strlen(match.file))
199 procname = match.file;
201 procname =
"/proc/self/exe";
203 struct bfd_ctx* bc = get_bc(&ob, set, procname);
205 find(bc, addr, &file, &func, &line);
206 procname = bc->handle->filename;
209 if (func ==
nullptr) {
210 output_print(&ob,
"0x%x : %s : %s \n",
211 addr, procname ==
nullptr ?
"unknown" : procname, file ==
nullptr ?
"unknown" : file);
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);
218 fprintf(crash,
"%s", g_output);
236 const char* dumpFile =
"crashdump.txt";
238 FILE* crash = file !=
nullptr ? file : stderr;
240 fprintf(crash,
"======start======\n");
242 #ifdef HAVE_SYS_UTSNAME_H
245 fprintf(crash,
"OS Info: %s %s %s %s %s\n", info.sysname, info.nodename, info.release, info.version, info.machine);
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);
257 backtrace_symbols_fd(symbols, i, fileno(crash));
262 fprintf(crash,
"Loaded libraries:\n");
263 dl_iterate_phdr(Sys_BacktraceLibsCallback, crash);
266 fprintf(crash,
"======end========\n");
void Com_BreakIntoDebugger(void)
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
const char * Sys_GetCurrentUser(void)
void Sys_Error(const char *error,...)
Errors out of the game.
void Sys_Backtrace(void)
On platforms supporting it, print a backtrace.
void Com_UploadCrashDump(const char *crashDumpFile)
void CL_Shutdown(void)
Saves configuration file and shuts the client systems down.
void Qcommon_Shutdown(void)
void Sys_ConsoleShutdown(void)
FILE * Sys_Fopen(const char *filename, const char *mode)
GLsizei const GLvoid * data