/Plugins/APP_Links2/links-2.1pre23/error.c
C | 403 lines | 361 code | 35 blank | 7 comment | 36 complexity | dd6d9d338c12e7e43815045d563266c2 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
- /* error.c
- * (c) 2002 Mikulas Patocka
- * This file is a part of the Links program, released under GPL.
- */
- #include "links.h"
- #if DEBUGLEVEL >= 2
- #define RED_ZONE 'R'
- #define FREE_FILL 0xfe
- #define REALLOC_FILL 0xfd
- #define ALLOC_FILL 0xfc
- #endif
- #if DEBUGLEVEL < 0
- #define FREE_FILL 0xfe
- #endif
- #if DEBUGLEVEL < 0
- #define NO_IE
- #endif
- #ifdef RED_ZONE
- #define RED_ZONE_INC 1
- #else
- #define RED_ZONE_INC 0
- #endif
- void er(int, unsigned char *, va_list); /* prototype */
- void do_not_optimize_here(void *p)
- {
- /* stop GCC optimization - avoid bugs in it */
- }
- #ifdef LEAK_DEBUG
- long mem_amount = 0;
- long last_mem_amount = -1;
- #ifdef LEAK_DEBUG_LIST
- struct list_head memory_list = { &memory_list, &memory_list };
- #endif
- #endif
- static inline void force_dump(void)
- {
- fprintf(stderr, "\n\033[1m%s\033[0m\n", "Forcing core dump");
- fflush(stdout);
- fflush(stderr);
- fatal_tty_exit();
- raise(SIGSEGV);
- }
- void check_memory_leaks(void)
- {
- #if defined(NO_IE)
- return;
- #else
- #ifdef LEAK_DEBUG
- if (mem_amount) {
- fprintf(stderr, "\n\033[1mMemory leak by %ld bytes\033[0m\n", mem_amount);
- #ifdef LEAK_DEBUG_LIST
- fprintf(stderr, "\nList of blocks: ");
- {
- int r = 0;
- struct alloc_header *ah;
- foreach (ah, memory_list) {
- fprintf(stderr, "%s%p:%d @ %s:%d", r ? ", ": "", (char *)ah + L_D_S, ah->size, ah->file, ah->line), r = 1;
- if (ah->comment) fprintf(stderr, ":\"%s\"", ah->comment);
- }
- fprintf(stderr, "\n");
- }
- #endif
- force_dump();
- }
- #endif
- #endif
- }
- void er(int b, unsigned char *m, va_list l)
- {
- if (b) fprintf(stderr, "%c", (char)7);
- #ifdef HAVE_VPRINTF
- vfprintf(stderr, m, l);
- #else
- fprintf(stderr, "%s", m);
- #endif
- fprintf(stderr, "\n");
- sleep(1);
- }
- void error(unsigned char *m, ...)
- {
- va_list l;
- va_start(l, m);
- er(1, m, l);
- va_end(l);
- }
- int errline;
- unsigned char *errfile;
- unsigned char errbuf[4096];
- void int_error(unsigned char *m, ...)
- {
- #ifdef NO_IE
- return;
- #else
- va_list l;
- va_start(l, m);
- sprintf(errbuf, "\033[1mINTERNAL ERROR\033[0m at %s:%d: ", errfile, errline);
- strcat(errbuf, m);
- er(1, errbuf, l);
- force_dump();
- va_end(l);
- #endif
- }
- void debug_msg(unsigned char *m, ...)
- {
- va_list l;
- va_start(l, m);
- sprintf(errbuf, "DEBUG MESSAGE at %s:%d: ", errfile, errline);
- strcat(errbuf, m);
- er(0, errbuf, l);
- va_end(l);
- }
- #ifdef LEAK_DEBUG
- void *debug_mem_alloc(unsigned char *file, int line, size_t size)
- {
- void *p;
- #ifdef LEAK_DEBUG
- struct alloc_header *ah;
- #endif
- if (!size) return DUMMY;
- if (size > MAXINT) overalloc();
- #ifdef LEAK_DEBUG
- mem_amount += size;
- size += L_D_S;
- #endif
- if (!(p = malloc(size + RED_ZONE_INC))) {
- error("ERROR: out of memory (malloc returned NULL)");
- #ifdef PSP
- pspDebugScreenPrintf("Out of Memory when: Allocating %ld bytes (called from '%s' line %d)\n", size+RED_ZONE_INC, file, line);
- pspDebugScreenPrintf("Memory allocated = %ld bytes | JS Mem Allocated = %ld bytes\n", mem_amount, js_zaflaknuto_pameti);
- wait_for_triangle("debug_mem_alloc() out of memory!");
- terminate_loop = 1;
- return NULL;
- #endif
- fatal_tty_exit();
- exit(RET_FATAL);
- return NULL;
- }
- #ifdef RED_ZONE
- *((char *)p + size + RED_ZONE_INC - 1) = RED_ZONE;
- #endif
- #ifdef LEAK_DEBUG
- ah = p;
- p = (char *)p + L_D_S;
- ah->size = size - L_D_S;
- ah->magic = ALLOC_MAGIC;
- #ifdef LEAK_DEBUG_LIST
- ah->file = file;
- ah->line = line;
- ah->comment = NULL;
- add_to_list(memory_list, ah);
- #endif
- #endif
- #ifdef ALLOC_FILL
- memset(p, ALLOC_FILL, size - L_D_S);
- #endif
- return p;
- }
- void *debug_mem_calloc(unsigned char *file, int line, size_t size)
- {
- void *p;
- #ifdef LEAK_DEBUG
- struct alloc_header *ah;
- #endif
- if (!size) return DUMMY;
- if (size > MAXINT) overalloc();
- #ifdef LEAK_DEBUG
- mem_amount += size;
- size += L_D_S;
- #endif
- if (!(p = x_calloc(size + RED_ZONE_INC))) {
- error("ERROR: out of memory (calloc returned NULL)");
- #ifdef PSP
- wait_for_triangle("debug_mem_calloc() out of memory!");
- #endif
- fatal_tty_exit();
- exit(RET_FATAL);
- return NULL;
- }
- #ifdef RED_ZONE
- *((char *)p + size + RED_ZONE_INC - 1) = RED_ZONE;
- #endif
- #ifdef LEAK_DEBUG
- ah = p;
- p = (char *)p + L_D_S;
- ah->size = size - L_D_S;
- ah->magic = ALLOC_MAGIC;
- #ifdef LEAK_DEBUG_LIST
- ah->file = file;
- ah->line = line;
- ah->comment = NULL;
- add_to_list(memory_list, ah);
- #endif
- #endif
- return p;
- }
- void debug_mem_free(unsigned char *file, int line, void *p)
- {
- #ifdef LEAK_DEBUG
- struct alloc_header *ah;
- #endif
- if (p == DUMMY) return;
- if (!p) {
- errfile = file, errline = line, int_error("mem_free(NULL)");
- return;
- }
- #ifdef LEAK_DEBUG
- p = (char *)p - L_D_S;
- ah = p;
- if (ah->magic != ALLOC_MAGIC) {
- errfile = file, errline = line, int_error("mem_free: magic doesn't match: %08x", ah->magic);
- return;
- }
- #ifdef FREE_FILL
- memset((char *)p + L_D_S, FREE_FILL, ah->size);
- #endif
- ah->magic = ALLOC_FREE_MAGIC;
- #ifdef LEAK_DEBUG_LIST
- del_from_list(ah);
- if (ah->comment) free(ah->comment);
- #endif
- mem_amount -= ah->size;
- #endif
- #ifdef RED_ZONE
- if (*((char *)p + L_D_S + ah->size + RED_ZONE_INC - 1) != RED_ZONE) {
- errfile = file, errline = line, int_error("mem_free: red zone damaged: %02x (block allocated at %s:%d:%s)", *((unsigned char *)p + L_D_S + ah->size + RED_ZONE_INC - 1),
- #ifdef LEAK_DEBUG_LIST
- ah->file, ah->line, ah->comment);
- #else
- "-", 0, "-");
- #endif
- return;
- }
- #endif
- free(p);
- }
- void *debug_mem_realloc(unsigned char *file, int line, void *p, size_t size)
- {
- #ifdef LEAK_DEBUG
- struct alloc_header *ah;
- #endif
- if (p == DUMMY) return debug_mem_alloc(file, line, size);
- if (!p) {
- errfile = file, errline = line, int_error("mem_realloc(NULL, %d)", size);
- return NULL;
- }
- if (!size) {
- debug_mem_free(file, line, p);
- return DUMMY;
- }
- if (size > MAXINT) overalloc();
- #ifdef LEAK_DEBUG
- p = (char *)p - L_D_S;
- ah = p;
- if (ah->magic != ALLOC_MAGIC) {
- errfile = file, errline = line, int_error("mem_realloc: magic doesn't match: %08x", ah->magic);
- return NULL;
- }
- ah->magic = ALLOC_REALLOC_MAGIC;
- #ifdef REALLOC_FILL
- if (size < (size_t)ah->size) memset((char *)p + L_D_S + size, REALLOC_FILL, ah->size - size);
- #endif
- #endif
- #ifdef RED_ZONE
- if (*((char *)p + L_D_S + ah->size + RED_ZONE_INC - 1) != RED_ZONE) {
- errfile = file, errline = line, int_error("mem_realloc: red zone damaged: %02x (block allocated at %s:%d:%s)", *((unsigned char *)p + L_D_S + ah->size + RED_ZONE_INC - 1),
- #ifdef LEAK_DEBUG_LIST
- ah->file, ah->line, ah->comment);
- #else
- "-", 0, "-");
- #endif
- return (char *)p + L_D_S;
- }
- #endif
- if (!(p = realloc(p, size + L_D_S + RED_ZONE_INC))) {
- error("ERROR: out of memory (realloc returned NULL)");
- #ifdef PSP
- wait_for_triangle("debug_mem_realloc() out of memory!");
- #endif
- fatal_tty_exit();
- exit(RET_FATAL);
- return NULL;
- }
- #ifdef RED_ZONE
- *((char *)p + size + L_D_S + RED_ZONE_INC - 1) = RED_ZONE;
- #endif
- #ifdef LEAK_DEBUG
- ah = p;
- mem_amount += size - ah->size;
- ah->size = size;
- ah->magic = ALLOC_MAGIC;
- #ifdef LEAK_DEBUG_LIST
- ah->prev->next = ah;
- ah->next->prev = ah;
- #endif
- #endif
- return (char *)p + L_D_S;
- }
- void set_mem_comment(void *p, unsigned char *c, int l)
- {
- #ifdef LEAK_DEBUG_LIST
- struct alloc_header *ah = (struct alloc_header *)((char *)p - L_D_S);
- if (ah->comment) free(ah->comment);
- if ((ah->comment = malloc(l + 1))) memcpy(ah->comment, c, l), ah->comment[l] = 0;
- #endif
- }
- unsigned char *get_mem_comment(void *p)
- {
- #ifdef LEAK_DEBUG_LIST
- /* perm je prase: return ((struct alloc_header*)((char*)((void*)((char*)p-sizeof(int))) - L_D_S))->comment;*/
- struct alloc_header *ah = (struct alloc_header *)((char *)p - L_D_S);
- if (!ah->comment) return "";
- else return ah->comment;
- #else
- return "";
- #endif
- }
- #endif
- #ifdef OOPS
- struct prot {
- struct prot *next;
- struct prot *prev;
- sigjmp_buf buf;
- };
- struct list_head prot = {&prot, &prot };
- int handled = 0;
- void fault(void *dummy)
- {
- struct prot *p;
- /*fprintf(stderr, "FAULT: %d !\n", (int)(unsigned long)dummy);*/
- if (list_empty(prot)) {
- #ifdef PSP
- wait_for_triangle("fault!");
- #endif
- fatal_tty_exit();
- exit(0);
- }
- p = prot.next;
- del_from_list(p);
- longjmp(p->buf, 1);
- }
- sigjmp_buf *new_stack_frame(void)
- {
- struct prot *new;
- if (!handled) {
- install_signal_handler(SIGSEGV, fault, (void *)SIGSEGV, 1);
- install_signal_handler(SIGBUS, fault, (void *)SIGBUS, 1);
- install_signal_handler(SIGFPE, fault, (void *)SIGFPE, 1);
- install_signal_handler(SIGILL, fault, (void *)SIGILL, 1);
- install_signal_handler(SIGABRT, fault, (void *)SIGABRT, 1);
- handled = 1;
- }
- if (!(new = mem_alloc(sizeof(struct prot)))) return NULL;
- add_to_list(prot, new);
- return &new->buf;
- }
- void xpr()
- {
- if (!list_empty(prot)) {
- struct prot *next = prot.next;
- del_from_list(next);
- mem_free(next);
- }
- }
- void nopr()
- {
- free_list(prot);
- }
- #endif