aboutsummaryrefslogtreecommitdiff
path: root/tinycc/lib/bcheck.c
diff options
context:
space:
mode:
authorUneven Prankster <unevenprankster@protonmail.com>2023-10-15 21:28:29 -0300
committerUneven Prankster <unevenprankster@protonmail.com>2023-10-15 21:28:29 -0300
commit1c0cc775732201f4c4d3ee0d6772be786b3b4aa1 (patch)
treef5d692d046868261275c7430a624c3ea9ed75d3d /tinycc/lib/bcheck.c
parenta89f892640cf12f75c7ce18e6e88c70a8d3965ed (diff)
A lot has certainly happened!
Diffstat (limited to 'tinycc/lib/bcheck.c')
-rw-r--r--tinycc/lib/bcheck.c2270
1 files changed, 0 insertions, 2270 deletions
diff --git a/tinycc/lib/bcheck.c b/tinycc/lib/bcheck.c
deleted file mode 100644
index b8dd1c5..0000000
--- a/tinycc/lib/bcheck.c
+++ /dev/null
@@ -1,2270 +0,0 @@
-/*
- * Tiny C Memory and bounds checker
- *
- * Copyright (c) 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <setjmp.h>
-
-#if !defined(__FreeBSD__) \
- && !defined(__FreeBSD_kernel__) \
- && !defined(__DragonFly__) \
- && !defined(__OpenBSD__) \
- && !defined(__APPLE__) \
- && !defined(__NetBSD__)
-#include <malloc.h>
-#endif
-
-#if !defined(_WIN32)
-#include <unistd.h>
-#include <sys/syscall.h>
-#endif
-
-#define BOUND_DEBUG (1)
-#define BOUND_STATISTIC (1)
-
-#if BOUND_DEBUG
- #define dprintf(a...) if (print_calls) fprintf(a)
-#else
- #define dprintf(a...)
-#endif
-
-#ifdef __attribute__
- /* an __attribute__ macro is defined in the system headers */
- #undef __attribute__
-#endif
-#define FASTCALL __attribute__((regparm(3)))
-
-#ifdef _WIN32
-# define DLL_EXPORT __declspec(dllexport)
-#else
-# define DLL_EXPORT
-#endif
-
-#if defined(__FreeBSD__) \
- || defined(__FreeBSD_kernel__) \
- || defined(__DragonFly__) \
- || defined(__OpenBSD__) \
- || defined(__NetBSD__) \
- || defined(__dietlibc__)
-
-#include <sys/mman.h>
-#define INIT_SEM()
-#define EXIT_SEM()
-#define WAIT_SEM()
-#define POST_SEM()
-#define TRY_SEM()
-#define HAVE_MEMALIGN (0)
-#define MALLOC_REDIR (0)
-#define HAVE_PTHREAD_CREATE (0)
-#define HAVE_CTYPE (0)
-#define HAVE_ERRNO (0)
-#define HAVE_SIGNAL (0)
-#define HAVE_SIGACTION (0)
-#define HAVE_FORK (0)
-#define HAVE_TLS_FUNC (0)
-#define HAVE_TLS_VAR (0)
-
-#elif defined(_WIN32)
-
-#include <windows.h>
-#include <signal.h>
-static CRITICAL_SECTION bounds_sem;
-#define INIT_SEM() InitializeCriticalSection(&bounds_sem)
-#define EXIT_SEM() DeleteCriticalSection(&bounds_sem)
-#define WAIT_SEM() EnterCriticalSection(&bounds_sem)
-#define POST_SEM() LeaveCriticalSection(&bounds_sem)
-#define TRY_SEM() TryEnterCriticalSection(&bounds_sem)
-#define HAVE_MEMALIGN (0)
-#define MALLOC_REDIR (0)
-#define HAVE_PTHREAD_CREATE (0)
-#define HAVE_CTYPE (0)
-#define HAVE_ERRNO (0)
-#define HAVE_SIGNAL (1)
-#define HAVE_SIGACTION (0)
-#define HAVE_FORK (0)
-#define HAVE_TLS_FUNC (1)
-#define HAVE_TLS_VAR (0)
-
-#else
-
-#define __USE_GNU /* get RTLD_NEXT */
-#include <sys/mman.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <signal.h>
-#ifdef __APPLE__
-#include <dispatch/dispatch.h>
-static dispatch_semaphore_t bounds_sem;
-#define INIT_SEM() bounds_sem = dispatch_semaphore_create(1)
-#define EXIT_SEM() dispatch_release(*(dispatch_object_t*)&bounds_sem)
-#define WAIT_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_FOREVER)
-#define POST_SEM() if (use_sem) dispatch_semaphore_signal(bounds_sem)
-#define TRY_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_NOW)
-#elif 0
-#include <semaphore.h>
-static sem_t bounds_sem;
-#define INIT_SEM() sem_init (&bounds_sem, 0, 1)
-#define EXIT_SEM() sem_destroy (&bounds_sem)
-#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \
- && errno == EINTR)
-#define POST_SEM() if (use_sem) sem_post (&bounds_sem)
-#define TRY_SEM() if (use_sem) while (sem_trywait (&bounds_sem) < 0 \
- && errno == EINTR)
-#elif 0
-static pthread_mutex_t bounds_mtx;
-#define INIT_SEM() pthread_mutex_init (&bounds_mtx, NULL)
-#define EXIT_SEM() pthread_mutex_destroy (&bounds_mtx)
-#define WAIT_SEM() if (use_sem) pthread_mutex_lock (&bounds_mtx)
-#define POST_SEM() if (use_sem) pthread_mutex_unlock (&bounds_mtx)
-#define TRY_SEM() if (use_sem) pthread_mutex_trylock (&bounds_mtx)
-#else
-static pthread_spinlock_t bounds_spin;
-/* about 25% faster then semaphore. */
-#define INIT_SEM() pthread_spin_init (&bounds_spin, 0)
-#define EXIT_SEM() pthread_spin_destroy (&bounds_spin)
-#define WAIT_SEM() if (use_sem) pthread_spin_lock (&bounds_spin)
-#define POST_SEM() if (use_sem) pthread_spin_unlock (&bounds_spin)
-#define TRY_SEM() if (use_sem) pthread_spin_trylock (&bounds_spin)
-#endif
-#define HAVE_MEMALIGN (1)
-#define MALLOC_REDIR (1)
-#define HAVE_PTHREAD_CREATE (1)
-#define HAVE_CTYPE (1)
-#define HAVE_ERRNO (1)
-#define HAVE_SIGNAL (1)
-#define HAVE_SIGACTION (1)
-#define HAVE_FORK (1)
-#if !defined(__APPLE__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define HAVE_TLS_FUNC (0)
-#define HAVE_TLS_VAR (1)
-#else
-#define HAVE_TLS_FUNC (1)
-#define HAVE_TLS_VAR (0)
-#endif
-#if defined TCC_MUSL || defined __ANDROID__
-# undef HAVE_CTYPE
-#endif
-#endif
-
-#if MALLOC_REDIR
-static void *(*malloc_redir) (size_t);
-static void *(*calloc_redir) (size_t, size_t);
-static void (*free_redir) (void *);
-static void *(*realloc_redir) (void *, size_t);
-static unsigned int pool_index;
-static unsigned char __attribute__((aligned(16))) initial_pool[256];
-#endif
-#if HAVE_MEMALIGN
-static void *(*memalign_redir) (size_t, size_t);
-#endif
-#if HAVE_PTHREAD_CREATE
-static int (*pthread_create_redir) (pthread_t *thread,
- const pthread_attr_t *attr,
- void *(*start_routine)(void *), void *arg);
-#endif
-#if HAVE_SIGNAL
-typedef void (*bound_sig)(int);
-static bound_sig (*signal_redir) (int signum, bound_sig handler);
-#endif
-#if HAVE_SIGACTION
-static int (*sigaction_redir) (int signum, const struct sigaction *act,
- struct sigaction *oldact);
-#endif
-#if HAVE_FORK
-static int (*fork_redir) (void);
-#endif
-
-#define TCC_TYPE_NONE (0)
-#define TCC_TYPE_MALLOC (1)
-#define TCC_TYPE_CALLOC (2)
-#define TCC_TYPE_REALLOC (3)
-#define TCC_TYPE_MEMALIGN (4)
-#define TCC_TYPE_STRDUP (5)
-
-/* this pointer is generated when bound check is incorrect */
-#define INVALID_POINTER ((void *)(-2))
-
-typedef struct tree_node Tree;
-struct tree_node {
- Tree * left, * right;
- size_t start;
- size_t size;
- unsigned char type;
- unsigned char is_invalid; /* true if pointers outside region are invalid */
-};
-
-typedef struct alloca_list_struct {
- size_t fp;
- void *p;
- size_t size;
- struct alloca_list_struct *next;
-} alloca_list_type;
-
-#if defined(_WIN32)
-#define BOUND_TID_TYPE DWORD
-#define BOUND_GET_TID(id) id = GetCurrentThreadId()
-#elif defined(__OpenBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = getthrid()
-#elif defined(__FreeBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) syscall (SYS_thr_self, &id)
-#elif defined(__NetBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = syscall (SYS__lwp_self)
-#elif defined(__linux__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = syscall (SYS_gettid)
-#else
-#define BOUND_TID_TYPE int
-#define BOUND_GET_TID(id) id = 0
-#endif
-
-typedef struct jmp_list_struct {
- void *penv;
- size_t fp;
- size_t end_fp;
- BOUND_TID_TYPE tid;
- struct jmp_list_struct *next;
-} jmp_list_type;
-
-#define BOUND_STATISTIC_SPLAY (0)
-static Tree * splay (size_t addr, Tree *t);
-static Tree * splay_end (size_t addr, Tree *t);
-static Tree * splay_insert(size_t addr, size_t size, Tree * t);
-static Tree * splay_delete(size_t addr, Tree *t);
-void splay_printtree(Tree * t, int d);
-
-/* external interface */
-void __bounds_checking (int no_check);
-void __bound_checking_lock (void);
-void __bound_checking_unlock (void);
-void __bound_never_fatal (int no_check);
-DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset);
-DLL_EXPORT void FASTCALL __bound_local_new(void *p1);
-DLL_EXPORT void FASTCALL __bound_local_delete(void *p1);
-void __bound_init(size_t *, int);
-void __bound_main_arg(int argc, char **argv, char **envp);
-void __bound_exit(void);
-void __bound_exit_dll(size_t *);
-#if !defined(_WIN32)
-void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd,
- off_t offset);
-int __bound_munmap (void *start, size_t size);
-DLL_EXPORT void __bound_siglongjmp(jmp_buf env, int val);
-#endif
-DLL_EXPORT void __bound_new_region(void *p, size_t size);
-DLL_EXPORT void __bound_setjmp(jmp_buf env);
-DLL_EXPORT void __bound_longjmp(jmp_buf env, int val);
-DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size);
-DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size);
-DLL_EXPORT int __bound_strlen(const char *s);
-DLL_EXPORT char *__bound_strcpy(char *dst, const char *src);
-DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n);
-DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2);
-DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n);
-DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
-DLL_EXPORT char *__bound_strncat(char *dest, const char *src, size_t n);
-DLL_EXPORT char *__bound_strchr(const char *string, int ch);
-DLL_EXPORT char *__bound_strrchr(const char *string, int ch);
-DLL_EXPORT char *__bound_strdup(const char *s);
-
-#if defined(__arm__) && defined(__ARM_EABI__)
-DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size);
-DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size);
-#endif
-
-#if MALLOC_REDIR
-#define BOUND_MALLOC(a) malloc_redir(a)
-#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)
-#define BOUND_FREE(a) free_redir(a)
-#define BOUND_REALLOC(a,b) realloc_redir(a,b)
-#define BOUND_CALLOC(a,b) calloc_redir(a,b)
-#else
-#define BOUND_MALLOC(a) malloc(a)
-#define BOUND_MEMALIGN(a,b) memalign(a,b)
-#define BOUND_FREE(a) free(a)
-#define BOUND_REALLOC(a,b) realloc(a,b)
-#define BOUND_CALLOC(a,b) calloc(a,b)
-DLL_EXPORT void *__bound_malloc(size_t size, const void *caller);
-DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller);
-DLL_EXPORT void __bound_free(void *ptr, const void *caller);
-DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller);
-DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size);
-#endif
-
-#define FREE_REUSE_SIZE (100)
-static unsigned int free_reuse_index;
-static void *free_reuse_list[FREE_REUSE_SIZE];
-
-static Tree *tree = NULL;
-#define TREE_REUSE (1)
-#if TREE_REUSE
-static Tree *tree_free_list;
-#endif
-static alloca_list_type *alloca_list;
-static jmp_list_type *jmp_list;
-
-static unsigned char inited;
-static unsigned char print_warn_ptr_add;
-static unsigned char print_calls;
-static unsigned char print_heap;
-static unsigned char print_statistic;
-static unsigned char no_strdup;
-static unsigned char use_sem;
-static int never_fatal;
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
-static int no_checking = 0;
-static DWORD no_checking_key;
-#define NO_CHECKING_CHECK() if (!p) { \
- p = (int *) LocalAlloc(LPTR, sizeof(int)); \
- if (!p) bound_alloc_error("tls malloc"); \
- *p = 0; \
- TlsSetValue(no_checking_key, p); \
- }
-#define NO_CHECKING_GET() ({ int *p = TlsGetValue(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p; \
- })
-#define NO_CHECKING_SET(v) { int *p = TlsGetValue(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p = v; \
- }
-#else
-static int no_checking = 0;
-static pthread_key_t no_checking_key;
-#define NO_CHECKING_CHECK() if (!p) { \
- p = (int *) BOUND_MALLOC(sizeof(int)); \
- if (!p) bound_alloc_error("tls malloc"); \
- *p = 0; \
- pthread_setspecific(no_checking_key, p); \
- }
-#define NO_CHECKING_GET() ({ int *p = pthread_getspecific(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p; \
- })
-#define NO_CHECKING_SET(v) { int *p = pthread_getspecific(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p = v; \
- }
-#endif
-#elif HAVE_TLS_VAR
-static __thread int no_checking = 0;
-#define NO_CHECKING_GET() no_checking
-#define NO_CHECKING_SET(v) no_checking = v
-#else
-static int no_checking = 0;
-#define NO_CHECKING_GET() no_checking
-#define NO_CHECKING_SET(v) no_checking = v
-#endif
-static char exec[100];
-
-#if BOUND_STATISTIC
-static unsigned long long bound_ptr_add_count;
-static unsigned long long bound_ptr_indir1_count;
-static unsigned long long bound_ptr_indir2_count;
-static unsigned long long bound_ptr_indir4_count;
-static unsigned long long bound_ptr_indir8_count;
-static unsigned long long bound_ptr_indir12_count;
-static unsigned long long bound_ptr_indir16_count;
-static unsigned long long bound_local_new_count;
-static unsigned long long bound_local_delete_count;
-static unsigned long long bound_malloc_count;
-static unsigned long long bound_calloc_count;
-static unsigned long long bound_realloc_count;
-static unsigned long long bound_free_count;
-static unsigned long long bound_memalign_count;
-static unsigned long long bound_mmap_count;
-static unsigned long long bound_munmap_count;
-static unsigned long long bound_alloca_count;
-static unsigned long long bound_setjmp_count;
-static unsigned long long bound_longjmp_count;
-static unsigned long long bound_mempcy_count;
-static unsigned long long bound_memcmp_count;
-static unsigned long long bound_memmove_count;
-static unsigned long long bound_memset_count;
-static unsigned long long bound_strlen_count;
-static unsigned long long bound_strcpy_count;
-static unsigned long long bound_strncpy_count;
-static unsigned long long bound_strcmp_count;
-static unsigned long long bound_strncmp_count;
-static unsigned long long bound_strcat_count;
-static unsigned long long bound_strncat_count;
-static unsigned long long bound_strchr_count;
-static unsigned long long bound_strrchr_count;
-static unsigned long long bound_strdup_count;
-static unsigned long long bound_not_found;
-#define INCR_COUNT(x) ++x
-#else
-#define INCR_COUNT(x)
-#endif
-#if BOUND_STATISTIC_SPLAY
-static unsigned long long bound_splay;
-static unsigned long long bound_splay_end;
-static unsigned long long bound_splay_insert;
-static unsigned long long bound_splay_delete;
-#define INCR_COUNT_SPLAY(x) ++x
-#else
-#define INCR_COUNT_SPLAY(x)
-#endif
-
-int tcc_backtrace(const char *fmt, ...);
-
-/* print a bound error message */
-#define bound_warning(...) \
- do { \
- WAIT_SEM (); \
- tcc_backtrace("^bcheck.c^BCHECK: " __VA_ARGS__); \
- POST_SEM (); \
- } while (0)
-
-#define bound_error(...) \
- do { \
- bound_warning(__VA_ARGS__); \
- if (never_fatal == 0) \
- exit(255); \
- } while (0)
-
-static void bound_alloc_error(const char *s)
-{
- fprintf(stderr,"FATAL: %s\n",s);
- exit (1);
-}
-
-static void bound_not_found_warning(const char *file, const char *function,
- void *ptr)
-{
- dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr);
-}
-
-static void fetch_and_add(int* variable, int value)
-{
-#if defined __i386__ || defined __x86_64__
- __asm__ volatile("lock; addl %0, %1"
- : "+r" (value), "+m" (*variable) // input+output
- : // No input-only
- : "memory"
- );
-#elif defined __arm__
- extern void fetch_and_add_arm(int* variable, int value);
- fetch_and_add_arm(variable, value);
-#elif defined __aarch64__
- extern void fetch_and_add_arm64(int* variable, int value);
- fetch_and_add_arm64(variable, value);
-#elif defined __riscv
- extern void fetch_and_add_riscv64(int* variable, int value);
- fetch_and_add_riscv64(variable, value);
-#else
- *variable += value;
-#endif
-}
-
-/* enable/disable checking. This can be used in signal handlers. */
-void __bounds_checking (int no_check)
-{
-#if HAVE_TLS_FUNC || HAVE_TLS_VAR
- NO_CHECKING_SET(NO_CHECKING_GET() + no_check);
-#else
- fetch_and_add (&no_checking, no_check);
-#endif
-}
-
-void __bound_checking_lock(void)
-{
- WAIT_SEM ();
-}
-
-void __bound_checking_unlock(void)
-{
- POST_SEM ();
-}
-
-/* enable/disable checking. This can be used in signal handlers. */
-void __bound_never_fatal (int neverfatal)
-{
- fetch_and_add (&never_fatal, neverfatal);
-}
-
-/* return '(p + offset)' for pointer arithmetic (a pointer can reach
- the end of a region in this case */
-void * __bound_ptr_add(void *p, size_t offset)
-{
- size_t addr = (size_t)p;
-
- if (NO_CHECKING_GET())
- return p + offset;
-
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__, p, (unsigned long)offset);
-
- WAIT_SEM ();
- INCR_COUNT(bound_ptr_add_count);
- if (tree) {
- addr -= tree->start;
- if (addr >= tree->size) {
- addr = (size_t)p;
- tree = splay (addr, tree);
- addr -= tree->start;
- }
- if (addr >= tree->size) {
- addr = (size_t)p;
- tree = splay_end (addr, tree);
- addr -= tree->start;
- }
- if (addr <= tree->size) {
- if (tree->is_invalid || addr + offset > tree->size) {
- POST_SEM ();
- if (print_warn_ptr_add)
- bound_warning("%p is outside of the region", p + offset);
- if (never_fatal <= 0)
- return INVALID_POINTER; /* return an invalid pointer */
- return p + offset;
- }
- }
- else if (p) { /* Allow NULL + offset. offsetoff is using it. */
- INCR_COUNT(bound_not_found);
- POST_SEM ();
- bound_not_found_warning (__FILE__, __FUNCTION__, p);
- return p + offset;
- }
- }
- POST_SEM ();
- return p + offset;
-}
-
-/* return '(p + offset)' for pointer indirection (the resulting must
- be strictly inside the region */
-#define BOUND_PTR_INDIR(dsize) \
-void * __bound_ptr_indir ## dsize (void *p, size_t offset) \
-{ \
- size_t addr = (size_t)p; \
- \
- if (NO_CHECKING_GET()) \
- return p + offset; \
- \
- dprintf(stderr, "%s, %s(): %p 0x%lx\n", \
- __FILE__, __FUNCTION__, p, (unsigned long)offset); \
- WAIT_SEM (); \
- INCR_COUNT(bound_ptr_indir ## dsize ## _count); \
- if (tree) { \
- addr -= tree->start; \
- if (addr >= tree->size) { \
- addr = (size_t)p; \
- tree = splay (addr, tree); \
- addr -= tree->start; \
- } \
- if (addr >= tree->size) { \
- addr = (size_t)p; \
- tree = splay_end (addr, tree); \
- addr -= tree->start; \
- } \
- if (addr <= tree->size) { \
- if (tree->is_invalid || addr + offset + dsize > tree->size) { \
- POST_SEM (); \
- bound_warning("%p is outside of the region", p + offset); \
- if (never_fatal <= 0) \
- return INVALID_POINTER; /* return an invalid pointer */ \
- return p + offset; \
- } \
- } \
- else { \
- INCR_COUNT(bound_not_found); \
- POST_SEM (); \
- bound_not_found_warning (__FILE__, __FUNCTION__, p); \
- return p + offset; \
- } \
- } \
- POST_SEM (); \
- return p + offset; \
-}
-
-BOUND_PTR_INDIR(1)
-BOUND_PTR_INDIR(2)
-BOUND_PTR_INDIR(4)
-BOUND_PTR_INDIR(8)
-BOUND_PTR_INDIR(12)
-BOUND_PTR_INDIR(16)
-
-/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-/*
- * At least gcc 6.2 complains when __builtin_frame_address is used with
- * nonzero argument.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-address"
-#endif
-
-/* return the frame pointer of the caller */
-#define GET_CALLER_FP(fp)\
-{\
- fp = (size_t)__builtin_frame_address(1);\
-}
-
-/* called when entering a function to add all the local regions */
-void FASTCALL __bound_local_new(void *p1)
-{
- size_t addr, fp, *p = p1;
-
- if (NO_CHECKING_GET())
- return;
- GET_CALLER_FP(fp);
- dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
- __FILE__, __FUNCTION__, p, (void *)fp);
- WAIT_SEM ();
- while ((addr = p[0])) {
- INCR_COUNT(bound_local_new_count);
- tree = splay_insert(addr + fp, p[1], tree);
- p += 2;
- }
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = p1;
- while ((addr = p[0])) {
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) (addr + fp), (unsigned long) p[1]);
- p += 2;
- }
- }
-#endif
-}
-
-/* called when leaving a function to delete all the local regions */
-void FASTCALL __bound_local_delete(void *p1)
-{
- size_t addr, fp, *p = p1;
-
- if (NO_CHECKING_GET())
- return;
- GET_CALLER_FP(fp);
- dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
- __FILE__, __FUNCTION__, p, (void *)fp);
- WAIT_SEM ();
- while ((addr = p[0])) {
- INCR_COUNT(bound_local_delete_count);
- tree = splay_delete(addr + fp, tree);
- p += 2;
- }
- if (alloca_list) {
- alloca_list_type *last = NULL;
- alloca_list_type *cur = alloca_list;
-
- do {
- if (cur->fp == fp) {
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- tree = splay_delete ((size_t) cur->p, tree);
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, __FUNCTION__, cur->p);
- BOUND_FREE (cur);
- cur = last ? last->next : alloca_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- } while (cur);
- }
- if (jmp_list) {
- jmp_list_type *last = NULL;
- jmp_list_type *cur = jmp_list;
-
- do {
- if (cur->fp == fp) {
- if (last)
- last->next = cur->next;
- else
- jmp_list = cur->next;
- dprintf(stderr, "%s, %s(): remove setjmp %p\n",
- __FILE__, __FUNCTION__, cur->penv);
- BOUND_FREE (cur);
- cur = last ? last->next : jmp_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- } while (cur);
- }
-
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = p1;
- while ((addr = p[0])) {
- if (addr != 1) {
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) (addr + fp), (unsigned long) p[1]);
- }
- p+= 2;
- }
- }
-#endif
-}
-
-/* used by alloca */
-void __bound_new_region(void *p, size_t size)
-{
- size_t fp;
- alloca_list_type *last;
- alloca_list_type *cur;
- alloca_list_type *new;
-
- if (NO_CHECKING_GET())
- return;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, p, (unsigned long)size);
- GET_CALLER_FP (fp);
- new = BOUND_MALLOC (sizeof (alloca_list_type));
- WAIT_SEM ();
- INCR_COUNT(bound_alloca_count);
- last = NULL;
- cur = alloca_list;
- while (cur) {
-#if defined(__i386__) || (defined(__arm__) && !defined(__ARM_EABI__))
- int align = 4;
-#elif defined(__arm__)
- int align = 8;
-#else
- int align = 16;
-#endif
- void *cure = (void *)((char *)cur->p + ((cur->size + align) & -align));
- void *pe = (void *)((char *)p + ((size + align) & -align));
- if (cur->fp == fp && ((cur->p <= p && cure > p) ||
- (p <= cur->p && pe > cur->p))) {
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- tree = splay_delete((size_t)cur->p, tree);
- break;
- }
- last = cur;
- cur = cur->next;
- }
- tree = splay_insert((size_t)p, size, tree);
- if (new) {
- new->fp = fp;
- new->p = p;
- new->size = size;
- new->next = alloca_list;
- alloca_list = new;
- }
- POST_SEM ();
- if (cur) {
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, __FUNCTION__, cur->p);
- BOUND_FREE (cur);
- }
-}
-
-void __bound_setjmp(jmp_buf env)
-{
- jmp_list_type *jl;
- void *e = (void *) env;
-
- if (NO_CHECKING_GET() == 0) {
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e);
- WAIT_SEM ();
- INCR_COUNT(bound_setjmp_count);
- jl = jmp_list;
- while (jl) {
- if (jl->penv == e)
- break;
- jl = jl->next;
- }
- if (jl == NULL) {
- jl = BOUND_MALLOC (sizeof (jmp_list_type));
- if (jl) {
- jl->penv = e;
- jl->next = jmp_list;
- jmp_list = jl;
- }
- }
- if (jl) {
- size_t fp;
-
- GET_CALLER_FP (fp);
- jl->fp = fp;
- jl->end_fp = (size_t)__builtin_frame_address(0);
- BOUND_GET_TID(jl->tid);
- }
- POST_SEM ();
- }
-}
-
-static void __bound_long_jump(jmp_buf env, int val, int sig, const char *func)
-{
- jmp_list_type *jl;
- void *e;
- BOUND_TID_TYPE tid;
-
- if (NO_CHECKING_GET() == 0) {
- e = (void *)env;
- BOUND_GET_TID(tid);
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, func, e);
- WAIT_SEM();
- INCR_COUNT(bound_longjmp_count);
- jl = jmp_list;
- while (jl) {
- if (jl->penv == e && jl->tid == tid) {
- size_t start_fp = (size_t)__builtin_frame_address(0);
- size_t end_fp = jl->end_fp;
- jmp_list_type *cur = jmp_list;
- jmp_list_type *last = NULL;
-
- while (cur->penv != e || cur->tid != tid) {
- if (cur->tid == tid) {
- dprintf(stderr, "%s, %s(): remove setjmp %p\n",
- __FILE__, func, cur->penv);
- if (last)
- last->next = cur->next;
- else
- jmp_list = cur->next;
- BOUND_FREE (cur);
- cur = last ? last->next : jmp_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- }
- for (;;) {
- Tree *t = tree;
- alloca_list_type *last;
- alloca_list_type *cur;
-
- while (t && (t->start < start_fp || t->start > end_fp))
- if (t->start < start_fp)
- t = t->right;
- else
- t = t->left;
- if (t == NULL)
- break;
- last = NULL;
- cur = alloca_list;
- while (cur) {
- if ((size_t) cur->p == t->start) {
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, func, cur->p);
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- BOUND_FREE (cur);
- break;
- }
- last = cur;
- cur = cur->next;
- }
- dprintf(stderr, "%s, %s(): delete %p\n",
- __FILE__, func, (void *) t->start);
- tree = splay_delete(t->start, tree);
- }
- break;
- }
- jl = jl->next;
- }
- POST_SEM();
- }
-#if !defined(_WIN32)
- sig ? siglongjmp(env, val) :
-#endif
- longjmp (env, val);
-}
-
-void __bound_longjmp(jmp_buf env, int val)
-{
- __bound_long_jump(env,val, 0, __FUNCTION__);
-}
-
-#if !defined(_WIN32)
-void __bound_siglongjmp(jmp_buf env, int val)
-{
- __bound_long_jump(env,val, 1, __FUNCTION__);
-}
-#endif
-
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
-void __bound_init(size_t *p, int mode)
-{
- dprintf(stderr, "%s, %s(): start %s\n", __FILE__, __FUNCTION__,
- mode < 0 ? "lazy" : mode == 0 ? "normal use" : "for -run");
-
- if (inited) {
- WAIT_SEM();
- goto add_bounds;
- }
- inited = 1;
-
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
- no_checking_key = TlsAlloc();
- TlsSetValue(no_checking_key, &no_checking);
-#else
- pthread_key_create(&no_checking_key, NULL);
- pthread_setspecific(no_checking_key, &no_checking);
-#endif
-#endif
- NO_CHECKING_SET(1);
-
- print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL;
- print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL;
- print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL;
- print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;
- never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;
-
- INIT_SEM ();
-
-#if MALLOC_REDIR
- {
- void *addr = mode > 0 ? RTLD_DEFAULT : RTLD_NEXT;
-
- /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT,
- but using RTLD_NEXT with -run segfaults on MacOS in dyld as the
- generated code segment isn't registered with dyld and hence the
- caller image of dlsym isn't known to it */
- *(void **) (&malloc_redir) = dlsym (addr, "malloc");
- if (malloc_redir == NULL) {
- dprintf(stderr, "%s, %s(): use RTLD_DEFAULT\n",
- __FILE__, __FUNCTION__);
- addr = RTLD_DEFAULT;
- *(void **) (&malloc_redir) = dlsym (addr, "malloc");
- }
- *(void **) (&calloc_redir) = dlsym (addr, "calloc");
- *(void **) (&free_redir) = dlsym (addr, "free");
- *(void **) (&realloc_redir) = dlsym (addr, "realloc");
- *(void **) (&memalign_redir) = dlsym (addr, "memalign");
- dprintf(stderr, "%s, %s(): malloc_redir %p\n",
- __FILE__, __FUNCTION__, malloc_redir);
- dprintf(stderr, "%s, %s(): free_redir %p\n",
- __FILE__, __FUNCTION__, free_redir);
- dprintf(stderr, "%s, %s(): realloc_redir %p\n",
- __FILE__, __FUNCTION__, realloc_redir);
- dprintf(stderr, "%s, %s(): memalign_redir %p\n",
- __FILE__, __FUNCTION__, memalign_redir);
- if (malloc_redir == NULL || free_redir == NULL)
- bound_alloc_error ("Cannot redirect malloc/free");
-#if HAVE_PTHREAD_CREATE
- *(void **) (&pthread_create_redir) = dlsym (addr, "pthread_create");
- dprintf(stderr, "%s, %s(): pthread_create_redir %p\n",
- __FILE__, __FUNCTION__, pthread_create_redir);
- if (pthread_create_redir == NULL)
- bound_alloc_error ("Cannot redirect pthread_create");
-#endif
-#if HAVE_SIGNAL
- *(void **) (&signal_redir) = dlsym (addr, "signal");
- dprintf(stderr, "%s, %s(): signal_redir %p\n",
- __FILE__, __FUNCTION__, signal_redir);
- if (signal_redir == NULL)
- bound_alloc_error ("Cannot redirect signal");
-#endif
-#if HAVE_SIGACTION
- *(void **) (&sigaction_redir) = dlsym (addr, "sigaction");
- dprintf(stderr, "%s, %s(): sigaction_redir %p\n",
- __FILE__, __FUNCTION__, sigaction_redir);
- if (sigaction_redir == NULL)
- bound_alloc_error ("Cannot redirect sigaction");
-#endif
-#if HAVE_FORK
- *(void **) (&fork_redir) = dlsym (addr, "fork");
- dprintf(stderr, "%s, %s(): fork_redir %p\n",
- __FILE__, __FUNCTION__, fork_redir);
- if (fork_redir == NULL)
- bound_alloc_error ("Cannot redirect fork");
-#endif
- }
-#endif
-
-#ifdef __linux__
- {
- FILE *fp;
- unsigned char found;
- unsigned long start;
- unsigned long end;
- unsigned long ad =
- (unsigned long) __builtin_return_address(0);
- char line[1000];
-
- /* Display exec name. Usefull when a lot of code is compiled with tcc */
- fp = fopen ("/proc/self/comm", "r");
- if (fp) {
- memset (exec, 0, sizeof(exec));
- fread (exec, 1, sizeof(exec) - 2, fp);
- if (strchr(exec,'\n'))
- *strchr(exec,'\n') = '\0';
- strcat (exec, ":");
- fclose (fp);
- }
- /* check if dlopen is used (is threre a better way?) */
- found = 0;
- fp = fopen ("/proc/self/maps", "r");
- if (fp) {
- while (fgets (line, sizeof(line), fp)) {
- if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
- ad >= start && ad < end) {
- found = 1;
- break;
- }
- if (strstr (line,"[heap]"))
- break;
- }
- fclose (fp);
- }
- if (found == 0) {
- use_sem = 1;
- no_strdup = 1;
- }
- }
-#endif
-
- WAIT_SEM ();
-
-#if HAVE_CTYPE
-#ifdef __APPLE__
- tree = splay_insert((size_t) &_DefaultRuneLocale,
- sizeof (_DefaultRuneLocale), tree);
-#else
- /* XXX: Does not work if locale is changed */
- tree = splay_insert((size_t) __ctype_b_loc(),
- sizeof (unsigned short *), tree);
- tree = splay_insert((size_t) (*__ctype_b_loc() - 128),
- 384 * sizeof (unsigned short), tree);
- tree = splay_insert((size_t) __ctype_tolower_loc(),
- sizeof (__int32_t *), tree);
- tree = splay_insert((size_t) (*__ctype_tolower_loc() - 128),
- 384 * sizeof (__int32_t), tree);
- tree = splay_insert((size_t) __ctype_toupper_loc(),
- sizeof (__int32_t *), tree);
- tree = splay_insert((size_t) (*__ctype_toupper_loc() - 128),
- 384 * sizeof (__int32_t), tree);
-#endif
-#endif
-#if HAVE_ERRNO
- tree = splay_insert((size_t) (&errno), sizeof (int), tree);
-#endif
-
-add_bounds:
- if (!p)
- goto no_bounds;
-
- /* add all static bound check values */
- while (p[0] != 0) {
- tree = splay_insert(p[0], p[1], tree);
-#if BOUND_DEBUG
- if (print_calls) {
- dprintf(stderr, "%s, %s(): static var %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) p[0], (unsigned long) p[1]);
- }
-#endif
- p += 2;
- }
-no_bounds:
-
- POST_SEM ();
- NO_CHECKING_SET(0);
- dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__);
-}
-
-void
-#if (defined(__GLIBC__) && (__GLIBC_MINOR__ >= 4)) || defined(_WIN32)
-__attribute__((constructor))
-#endif
-__bound_main_arg(int argc, char **argv, char **envp)
-{
- __bound_init (0, -1);
- if (argc && argv) {
- int i;
-
- WAIT_SEM ();
- for (i = 0; i < argc; i++)
- tree = splay_insert((size_t) argv[i], strlen (argv[i]) + 1, tree);
- tree = splay_insert((size_t) argv, (argc + 1) * sizeof(char *), tree);
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- for (i = 0; i < argc; i++)
- dprintf(stderr, "%s, %s(): arg %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- argv[i], (unsigned long)(strlen (argv[i]) + 1));
- dprintf(stderr, "%s, %s(): argv %p %d\n",
- __FILE__, __FUNCTION__, argv,
- (int)((argc + 1) * sizeof(char *)));
- }
-#endif
- }
-
- if (envp && *envp) {
- char **p = envp;
-
- WAIT_SEM ();
- while (*p) {
- tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);
- ++p;
- }
- tree = splay_insert((size_t) envp, (++p - envp) * sizeof(char *), tree);
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = envp;
- while (*p) {
- dprintf(stderr, "%s, %s(): env %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- *p, (unsigned long)(strlen (*p) + 1));
- ++p;
- }
- dprintf(stderr, "%s, %s(): environ %p %d\n",
- __FILE__, __FUNCTION__, envp,
- (int)((++p - envp) * sizeof(char *)));
- }
-#endif
- }
-}
-
-void __attribute__((destructor)) __bound_exit(void)
-{
- int i;
- static const char * const alloc_type[] = {
- "", "malloc", "calloc", "realloc", "memalign", "strdup"
- };
-
- dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
-
- if (inited) {
-#if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \
- !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
- !defined(__ANDROID__)
- if (print_heap) {
- extern void __libc_freeres (void);
- __libc_freeres ();
- }
-#endif
-
- NO_CHECKING_SET(1);
-
- TRY_SEM ();
- while (alloca_list) {
- alloca_list_type *next = alloca_list->next;
-
- tree = splay_delete ((size_t) alloca_list->p, tree);
- BOUND_FREE (alloca_list);
- alloca_list = next;
- }
- while (jmp_list) {
- jmp_list_type *next = jmp_list->next;
-
- BOUND_FREE (jmp_list);
- jmp_list = next;
- }
- for (i = 0; i < FREE_REUSE_SIZE; i++) {
- if (free_reuse_list[i]) {
- tree = splay_delete ((size_t) free_reuse_list[i], tree);
- BOUND_FREE (free_reuse_list[i]);
- }
- }
- while (tree) {
- if (print_heap && tree->type != 0)
- fprintf (stderr, "%s, %s(): %s found size %lu\n",
- __FILE__, __FUNCTION__, alloc_type[tree->type],
- (unsigned long) tree->size);
- tree = splay_delete (tree->start, tree);
- }
-#if TREE_REUSE
- while (tree_free_list) {
- Tree *next = tree_free_list->left;
- BOUND_FREE (tree_free_list);
- tree_free_list = next;
- }
-#endif
- POST_SEM ();
- EXIT_SEM ();
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
- TlsFree(no_checking_key);
-#else
- pthread_key_delete(no_checking_key);
-#endif
-#endif
- inited = 0;
- if (print_statistic) {
-#if BOUND_STATISTIC
- fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count);
- fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count);
- fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count);
- fprintf (stderr, "bound_ptr_indir4_count %llu\n", bound_ptr_indir4_count);
- fprintf (stderr, "bound_ptr_indir8_count %llu\n", bound_ptr_indir8_count);
- fprintf (stderr, "bound_ptr_indir12_count %llu\n", bound_ptr_indir12_count);
- fprintf (stderr, "bound_ptr_indir16_count %llu\n", bound_ptr_indir16_count);
- fprintf (stderr, "bound_local_new_count %llu\n", bound_local_new_count);
- fprintf (stderr, "bound_local_delete_count %llu\n", bound_local_delete_count);
- fprintf (stderr, "bound_malloc_count %llu\n", bound_malloc_count);
- fprintf (stderr, "bound_calloc_count %llu\n", bound_calloc_count);
- fprintf (stderr, "bound_realloc_count %llu\n", bound_realloc_count);
- fprintf (stderr, "bound_free_count %llu\n", bound_free_count);
- fprintf (stderr, "bound_memalign_count %llu\n", bound_memalign_count);
- fprintf (stderr, "bound_mmap_count %llu\n", bound_mmap_count);
- fprintf (stderr, "bound_munmap_count %llu\n", bound_munmap_count);
- fprintf (stderr, "bound_alloca_count %llu\n", bound_alloca_count);
- fprintf (stderr, "bound_setjmp_count %llu\n", bound_setjmp_count);
- fprintf (stderr, "bound_longjmp_count %llu\n", bound_longjmp_count);
- fprintf (stderr, "bound_mempcy_count %llu\n", bound_mempcy_count);
- fprintf (stderr, "bound_memcmp_count %llu\n", bound_memcmp_count);
- fprintf (stderr, "bound_memmove_count %llu\n", bound_memmove_count);
- fprintf (stderr, "bound_memset_count %llu\n", bound_memset_count);
- fprintf (stderr, "bound_strlen_count %llu\n", bound_strlen_count);
- fprintf (stderr, "bound_strcpy_count %llu\n", bound_strcpy_count);
- fprintf (stderr, "bound_strncpy_count %llu\n", bound_strncpy_count);
- fprintf (stderr, "bound_strcmp_count %llu\n", bound_strcmp_count);
- fprintf (stderr, "bound_strncmp_count %llu\n", bound_strncmp_count);
- fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count);
- fprintf (stderr, "bound_strncat_count %llu\n", bound_strncat_count);
- fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count);
- fprintf (stderr, "bound_strrchr_count %llu\n", bound_strrchr_count);
- fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count);
- fprintf (stderr, "bound_not_found %llu\n", bound_not_found);
-#endif
-#if BOUND_STATISTIC_SPLAY
- fprintf (stderr, "bound_splay %llu\n", bound_splay);
- fprintf (stderr, "bound_splay_end %llu\n", bound_splay_end);
- fprintf (stderr, "bound_splay_insert %llu\n", bound_splay_insert);
- fprintf (stderr, "bound_splay_delete %llu\n", bound_splay_delete);
-#endif
- }
- }
-}
-
-void __bound_exit_dll(size_t *p)
-{
- dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
-
- if (p) {
- WAIT_SEM ();
- while (p[0] != 0) {
- tree = splay_delete(p[0], tree);
-#if BOUND_DEBUG
- if (print_calls) {
- dprintf(stderr, "%s, %s(): remove static var %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) p[0], (unsigned long) p[1]);
- }
-#endif
- p += 2;
- }
- POST_SEM ();
- }
-}
-
-#if HAVE_PTHREAD_CREATE
-typedef struct {
- void *(*start_routine) (void *);
- void *arg;
- sigset_t old_mask;
-} bound_thread_create_type;
-
-static void *bound_thread_create(void *bdata)
-{
- bound_thread_create_type *data = (bound_thread_create_type *) bdata;
- void *retval;
-#if HAVE_TLS_FUNC
- int *p = (int *) BOUND_MALLOC(sizeof(int));
-
- if (!p) bound_alloc_error("bound_thread_create malloc");
- *p = 0;
- pthread_setspecific(no_checking_key, p);
-#endif
- pthread_sigmask(SIG_SETMASK, &data->old_mask, NULL);
- retval = data->start_routine(data->arg);
-#if HAVE_TLS_FUNC
- pthread_setspecific(no_checking_key, NULL);
- BOUND_FREE (p);
-#endif
- BOUND_FREE (data);
- return retval;
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
- void *(*start_routine) (void *), void *arg)
-{
- int retval;
- bound_thread_create_type *data;
- sigset_t mask;
- sigset_t old_mask;
-
- use_sem = 1;
- dprintf (stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
- sigfillset(&mask);
- pthread_sigmask(SIG_SETMASK, &mask, &old_mask);
- data = (bound_thread_create_type *) BOUND_MALLOC(sizeof(bound_thread_create_type));
- if (!data) bound_alloc_error("bound_thread_create malloc");
- data->start_routine = start_routine;
- data->arg = arg;
- data->old_mask = old_mask;
- retval = pthread_create_redir(thread, attr, bound_thread_create, data);
- pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
- return retval;
-}
-#endif
-
-#if HAVE_SIGNAL || HAVE_SIGACTION
-typedef union {
-#if HAVE_SIGNAL
- bound_sig signal_handler;
-#endif
-#if HAVE_SIGACTION
- void (*sig_handler)(int);
- void (*sig_sigaction)(int, siginfo_t *, void *);
-#endif
-} bound_sig_type;
-
-static unsigned char bound_sig_used[NSIG];
-static bound_sig_type bound_sig_data[NSIG];
-#endif
-
-#if HAVE_SIGNAL
-static void signal_handler(int sig)
-{
- __bounds_checking(1);
- bound_sig_data[sig].signal_handler(sig);
- __bounds_checking(-1);
-}
-
-bound_sig signal(int signum, bound_sig handler)
-{
- bound_sig retval;
-
- dprintf (stderr, "%s, %s() %d %p\n", __FILE__, __FUNCTION__,
- signum, handler);
- retval = signal_redir(signum, handler ? signal_handler : handler);
- if (retval != SIG_ERR) {
- if (bound_sig_used[signum])
- retval = bound_sig_data[signum].signal_handler;
- if (handler) {
- bound_sig_used[signum] = 1;
- bound_sig_data[signum].signal_handler = handler;
- }
- }
- return retval;
-}
-#endif
-
-#if HAVE_SIGACTION
-static void sig_handler(int sig)
-{
- __bounds_checking(1);
- bound_sig_data[sig].sig_handler(sig);
- __bounds_checking(-1);
-}
-
-static void sig_sigaction(int sig, siginfo_t *info, void *ucontext)
-{
- __bounds_checking(1);
- bound_sig_data[sig].sig_sigaction(sig, info, ucontext);
- __bounds_checking(-1);
-}
-
-int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
-{
- int retval;
- struct sigaction nact, oact;
-
- dprintf (stderr, "%s, %s() %d %p %p\n", __FILE__, __FUNCTION__,
- signum, act, oldact);
-
- if (sigaction_redir == NULL)
- __bound_init(0,-1);
-
- if (act) {
- nact = *act;
- if (nact.sa_flags & SA_SIGINFO)
- nact.sa_sigaction = sig_sigaction;
- else
- nact.sa_handler = sig_handler;
- retval = sigaction_redir(signum, &nact, &oact);
- }
- else
- retval = sigaction_redir(signum, act, &oact);
- if (retval >= 0) {
- if (bound_sig_used[signum]) {
- if (oact.sa_flags & SA_SIGINFO)
- oact.sa_sigaction = bound_sig_data[signum].sig_sigaction;
- else
- oact.sa_handler = bound_sig_data[signum].sig_handler;
- }
- if (oldact) {
- *oldact = oact;
- }
- if (act) {
- bound_sig_used[signum] = 1;
- if (act->sa_flags & SA_SIGINFO)
- bound_sig_data[signum].sig_sigaction = act->sa_sigaction;
- else
- bound_sig_data[signum].sig_handler = act->sa_handler;
- }
- }
- return retval;
-}
-#endif
-
-#if HAVE_FORK
-pid_t fork(void)
-{
- pid_t retval;
-
- WAIT_SEM();
- retval = (*fork_redir)();
- if (retval == 0)
- INIT_SEM();
- else
- POST_SEM();
- return retval;
-}
-#endif
-
-#if MALLOC_REDIR
-void *malloc(size_t size)
-#else
-void *__bound_malloc(size_t size, const void *caller)
-#endif
-{
- void *ptr;
-
-#if MALLOC_REDIR
- /* This will catch the first dlsym call from __bound_init */
- if (malloc_redir == NULL) {
- __bound_init (0, -1);
- if (malloc_redir == NULL) {
- ptr = &initial_pool[pool_index];
- pool_index = (pool_index + size + 15) & ~15;
- if (pool_index >= sizeof (initial_pool))
- bound_alloc_error ("initial memory pool too small");
- dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
- return ptr;
- }
- }
-#endif
- /* we allocate one more byte to ensure the regions will be
- separated by at least one byte. With the glibc malloc, it may
- be in fact not necessary */
- ptr = BOUND_MALLOC (size + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (inited && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_malloc_count);
-
- if (ptr) {
- tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_MALLOC;
- }
- POST_SEM ();
- }
- return ptr;
-}
-
-#if MALLOC_REDIR
-void *memalign(size_t size, size_t align)
-#else
-void *__bound_memalign(size_t size, size_t align, const void *caller)
-#endif
-{
- void *ptr;
-
-#if HAVE_MEMALIGN
- /* we allocate one more byte to ensure the regions will be
- separated by at least one byte. With the glibc malloc, it may
- be in fact not necessary */
- ptr = BOUND_MEMALIGN(size + 1, align);
-#else
- if (align > 4) {
- /* XXX: handle it ? */
- ptr = NULL;
- } else {
- /* we suppose that malloc aligns to at least four bytes */
- ptr = BOUND_MALLOC(size + 1);
- }
-#endif
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_memalign_count);
-
- if (ptr) {
- tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_MEMALIGN;
- }
- POST_SEM ();
- }
- return ptr;
-}
-
-#if MALLOC_REDIR
-void free(void *ptr)
-#else
-void __bound_free(void *ptr, const void *caller)
-#endif
-{
- size_t addr = (size_t) ptr;
- void *p;
-
- if (ptr == NULL || tree == NULL
-#if MALLOC_REDIR
- || ((unsigned char *) ptr >= &initial_pool[0] &&
- (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])
-#endif
- )
- return;
-
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);
-
- if (inited && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_free_count);
- tree = splay (addr, tree);
- if (tree->start == addr) {
- if (tree->is_invalid) {
- POST_SEM ();
- bound_error("freeing invalid region");
- return;
- }
- tree->is_invalid = 1;
- memset (ptr, 0x5a, tree->size);
- p = free_reuse_list[free_reuse_index];
- free_reuse_list[free_reuse_index] = ptr;
- free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;
- if (p)
- tree = splay_delete((size_t)p, tree);
- ptr = p;
- }
- POST_SEM ();
- }
- BOUND_FREE (ptr);
-}
-
-#if MALLOC_REDIR
-void *realloc(void *ptr, size_t size)
-#else
-void *__bound_realloc(void *ptr, size_t size, const void *caller)
-#endif
-{
- void *new_ptr;
-
- if (size == 0) {
-#if MALLOC_REDIR
- free(ptr);
-#else
- __bound_free(ptr, caller);
-#endif
- return NULL;
- }
-
- new_ptr = BOUND_REALLOC (ptr, size + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
-
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_realloc_count);
-
- if (ptr)
- tree = splay_delete ((size_t) ptr, tree);
- if (new_ptr) {
- tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) new_ptr)
- tree->type = TCC_TYPE_REALLOC;
- }
- POST_SEM ();
- }
- return new_ptr;
-}
-
-#if MALLOC_REDIR
-void *calloc(size_t nmemb, size_t size)
-#else
-void *__bound_calloc(size_t nmemb, size_t size)
-#endif
-{
- void *ptr;
-
- size *= nmemb;
-#if MALLOC_REDIR
- /* This will catch the first dlsym call from __bound_init */
- if (malloc_redir == NULL) {
- __bound_init (0, -1);
- if (malloc_redir == NULL) {
- ptr = &initial_pool[pool_index];
- pool_index = (pool_index + size + 15) & ~15;
- if (pool_index >= sizeof (initial_pool))
- bound_alloc_error ("initial memory pool too small");
- dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
- memset (ptr, 0, size);
- return ptr;
- }
- }
-#endif
- ptr = BOUND_MALLOC(size + 1);
- dprintf (stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (ptr) {
- memset (ptr, 0, size);
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_calloc_count);
- tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_CALLOC;
- POST_SEM ();
- }
- }
- return ptr;
-}
-
-#if !defined(_WIN32)
-void *__bound_mmap (void *start, size_t size, int prot,
- int flags, int fd, off_t offset)
-{
- void *result;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, start, (unsigned long)size);
- result = mmap (start, size, prot, flags, fd, offset);
- if (result && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_mmap_count);
- tree = splay_insert((size_t)result, size, tree);
- POST_SEM ();
- }
- return result;
-}
-
-int __bound_munmap (void *start, size_t size)
-{
- int result;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, start, (unsigned long)size);
- if (start && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_munmap_count);
- tree = splay_delete ((size_t) start, tree);
- POST_SEM ();
- }
- result = munmap (start, size);
- return result;
-}
-#endif
-
-/* some useful checked functions */
-
-/* check that (p ... p + size - 1) lies inside 'p' region, if any */
-static void __bound_check(const void *p, size_t size, const char *function)
-{
- if (size != 0 && __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
- bound_error("invalid pointer %p, size 0x%lx in %s",
- p, (unsigned long)size, function);
- }
-}
-
-static int check_overlap (const void *p1, size_t n1,
- const void *p2, size_t n2,
- const char *function)
-{
- const void *p1e = (const void *) ((const char *) p1 + n1);
- const void *p2e = (const void *) ((const char *) p2 + n2);
-
- if (NO_CHECKING_GET() == 0 && n1 != 0 && n2 !=0 &&
- ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */
- (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */
- bound_error("overlapping regions %p(0x%lx), %p(0x%lx) in %s",
- p1, (unsigned long)n1, p2, (unsigned long)n2, function);
- return never_fatal < 0;
- }
- return 0;
-}
-
-void *__bound_memcpy(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_mempcy_count);
- __bound_check(dest, n, "memcpy dest");
- __bound_check(src, n, "memcpy src");
- if (check_overlap(dest, n, src, n, "memcpy"))
- return dest;
- return memcpy(dest, src, n);
-}
-
-int __bound_memcmp(const void *s1, const void *s2, size_t n)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
- int retval = 0;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
- INCR_COUNT(bound_memcmp_count);
- for (;;) {
- if ((ssize_t) --n == -1)
- break;
- else if (*u1 != *u2) {
- retval = *u1++ - *u2++;
- break;
- }
- ++u1;
- ++u2;
- }
- __bound_check(s1, (const void *)u1 - s1, "memcmp s1");
- __bound_check(s2, (const void *)u2 - s2, "memcmp s2");
- return retval;
-}
-
-void *__bound_memmove(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return memmove(dest, src, n);
-}
-
-void *__bound_memset(void *s, int c, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
- __FILE__, __FUNCTION__, s, c, (unsigned long)n);
- INCR_COUNT(bound_memset_count);
- __bound_check(s, n, "memset");
- return memset(s, c, n);
-}
-
-#if defined(__arm__) && defined(__ARM_EABI__)
-void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_mempcy_count);
- __bound_check(dest, n, "memcpy dest");
- __bound_check(src, n, "memcpy src");
- if (check_overlap(dest, n, src, n, "memcpy"))
- return dest;
- return __aeabi_memcpy(dest, src, n);
-}
-
-void *__bound___aeabi_memmove(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove(dest, src, n);
-}
-
-void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove4(dest, src, n);
-}
-
-void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove8(dest, src, n);
-}
-
-void *__bound___aeabi_memset(void *s, int c, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
- __FILE__, __FUNCTION__, s, c, (unsigned long)n);
- INCR_COUNT(bound_memset_count);
- __bound_check(s, n, "memset");
- return __aeabi_memset(s, c, n);
-}
-#endif
-
-int __bound_strlen(const char *s)
-{
- const char *p = s;
-
- dprintf(stderr, "%s, %s(): %p\n",
- __FILE__, __FUNCTION__, s);
- INCR_COUNT(bound_strlen_count);
- while (*p++);
- __bound_check(s, p - s, "strlen");
- return (p - s) - 1;
-}
-
-char *__bound_strcpy(char *dest, const char *src)
-{
- size_t len;
- const char *p = src;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, dest, src);
- INCR_COUNT(bound_strcpy_count);
- while (*p++);
- len = p - src;
- __bound_check(dest, len, "strcpy dest");
- __bound_check(src, len, "strcpy src");
- if (check_overlap(dest, len, src, len, "strcpy"))
- return dest;
- return strcpy (dest, src);
-}
-
-char *__bound_strncpy(char *dest, const char *src, size_t n)
-{
- size_t len = n;
- const char *p = src;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_strncpy_count);
- while (len-- && *p++);
- len = p - src;
- __bound_check(dest, len, "strncpy dest");
- __bound_check(src, len, "strncpy src");
- if (check_overlap(dest, len, src, len, "strncpy"))
- return dest;
- return strncpy(dest, src, n);
-}
-
-int __bound_strcmp(const char *s1, const char *s2)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, s1, s2);
- INCR_COUNT(bound_strcmp_count);
- while (*u1 && *u1 == *u2) {
- ++u1;
- ++u2;
- }
- __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp s1");
- __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp s2");
- return *u1 - *u2;
-}
-
-int __bound_strncmp(const char *s1, const char *s2, size_t n)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
- int retval = 0;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
- INCR_COUNT(bound_strncmp_count);
- do {
- if ((ssize_t) --n == -1)
- break;
- else if (*u1 != *u2) {
- retval = *u1++ - *u2++;
- break;
- }
- ++u2;
- } while (*u1++);
- __bound_check(s1, (const char *)u1 - s1, "strncmp s1");
- __bound_check(s2, (const char *)u2 - s2, "strncmp s2");
- return retval;
-}
-
-char *__bound_strcat(char *dest, const char *src)
-{
- char *r = dest;
- const char *s = src;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, dest, src);
- INCR_COUNT(bound_strcat_count);
- while (*dest++);
- while (*src++);
- __bound_check(r, (dest - r) + (src - s) - 1, "strcat dest");
- __bound_check(s, src - s, "strcat src");
- if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strcat"))
- return dest;
- return strcat(r, s);
-}
-
-char *__bound_strncat(char *dest, const char *src, size_t n)
-{
- char *r = dest;
- const char *s = src;
- size_t len = n;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_strncat_count);
- while (*dest++);
- while (len-- && *src++);
- __bound_check(r, (dest - r) + (src - s) - 1, "strncat dest");
- __bound_check(s, src - s, "strncat src");
- if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strncat"))
- return dest;
- return strncat(r, s, n);
-}
-
-char *__bound_strchr(const char *s, int c)
-{
- const unsigned char *str = (const unsigned char *) s;
- unsigned char ch = c;
-
- dprintf(stderr, "%s, %s(): %p, %d\n",
- __FILE__, __FUNCTION__, s, ch);
- INCR_COUNT(bound_strchr_count);
- while (*str) {
- if (*str == ch)
- break;
- ++str;
- }
- __bound_check(s, ((const char *)str - s) + 1, "strchr");
- return *str == ch ? (char *) str : NULL;
-}
-
-char *__bound_strrchr(const char *s, int c)
-{
- const unsigned char *str = (const unsigned char *) s;
- unsigned char ch = c;
-
- dprintf(stderr, "%s, %s(): %p, %d\n",
- __FILE__, __FUNCTION__, s, ch);
- INCR_COUNT(bound_strrchr_count);
- while (*str++);
- __bound_check(s, (const char *)str - s, "strrchr");
- while (str != (const unsigned char *)s) {
- if (*--str == ch)
- break;
- }
- __bound_check(s, (const char *)str - s, "strrchr");
- return *str == ch ? (char *) str : NULL;
-}
-
-char *__bound_strdup(const char *s)
-{
- const char *p = s;
- char *new;
-
- INCR_COUNT(bound_strdup_count);
- while (*p++);
- __bound_check(s, p - s, "strdup");
- new = BOUND_MALLOC ((p - s) + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, new, (unsigned long)(p -s));
- if (new) {
- if (NO_CHECKING_GET() == 0 && no_strdup == 0) {
- WAIT_SEM ();
- tree = splay_insert((size_t)new, p - s, tree);
- if (tree && tree->start == (size_t) new)
- tree->type = TCC_TYPE_STRDUP;
- POST_SEM ();
- }
- memcpy (new, s, p - s);
- }
- return new;
-}
-
-/*
- An implementation of top-down splaying with sizes
- D. Sleator <sleator@cs.cmu.edu>, January 1994.
-
- This extends top-down-splay.c to maintain a size field in each node.
- This is the number of nodes in the subtree rooted there. This makes
- it possible to efficiently compute the rank of a key. (The rank is
- the number of nodes to the left of the given key.) It it also
- possible to quickly find the node of a given rank. Both of these
- operations are illustrated in the code below. The remainder of this
- introduction is taken from top-down-splay.c.
-
- "Splay trees", or "self-adjusting search trees" are a simple and
- efficient data structure for storing an ordered set. The data
- structure consists of a binary tree, with no additional fields. It
- allows searching, insertion, deletion, deletemin, deletemax,
- splitting, joining, and many other operations, all with amortized
- logarithmic performance. Since the trees adapt to the sequence of
- requests, their performance on real access patterns is typically even
- better. Splay trees are described in a number of texts and papers
- [1,2,3,4].
-
- The code here is adapted from simple top-down splay, at the bottom of
- page 669 of [2]. It can be obtained via anonymous ftp from
- spade.pc.cs.cmu.edu in directory /usr/sleator/public.
-
- The chief modification here is that the splay operation works even if the
- item being splayed is not in the tree, and even if the tree root of the
- tree is NULL. So the line:
-
- t = splay(i, t);
-
- causes it to search for item with key i in the tree rooted at t. If it's
- there, it is splayed to the root. If it isn't there, then the node put
- at the root is the last one before NULL that would have been reached in a
- normal binary search for i. (It's a neighbor of i in the tree.) This
- allows many other operations to be easily implemented, as shown below.
-
- [1] "Data Structures and Their Algorithms", Lewis and Denenberg,
- Harper Collins, 1991, pp 243-251.
- [2] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
- JACM Volume 32, No 3, July 1985, pp 652-686.
- [3] "Data Structure and Algorithm Analysis", Mark Weiss,
- Benjamin Cummins, 1992, pp 119-130.
- [4] "Data Structures, Algorithms, and Performance", Derick Wood,
- Addison-Wesley, 1993, pp 367-375
-*/
-
-/* Code adapted for tcc */
-
-#define compare(start,tstart,tsize) (start < tstart ? -1 : \
- start >= tstart+tsize ? 1 : 0)
-
-static Tree * splay (size_t addr, Tree *t)
-/* Splay using the key start (which may or may not be in the tree.) */
-/* The starting root is t, and the tree used is defined by rat */
-{
- Tree N, *l, *r, *y;
- int comp;
-
- INCR_COUNT_SPLAY(bound_splay);
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
-
- for (;;) {
- comp = compare(addr, t->start, t->size);
- if (comp < 0) {
- y = t->left;
- if (y == NULL) break;
- if (compare(addr, y->start, y->size) < 0) {
- t->left = y->right; /* rotate right */
- y->right = t;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- } else if (comp > 0) {
- y = t->right;
- if (y == NULL) break;
- if (compare(addr, y->start, y->size) > 0) {
- t->right = y->left; /* rotate left */
- y->left = t;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- } else {
- break;
- }
- }
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
-
- return t;
-}
-
-#define compare_end(start,tend) (start < tend ? -1 : \
- start > tend ? 1 : 0)
-
-static Tree * splay_end (size_t addr, Tree *t)
-/* Splay using the key start (which may or may not be in the tree.) */
-/* The starting root is t, and the tree used is defined by rat */
-{
- Tree N, *l, *r, *y;
- int comp;
-
- INCR_COUNT_SPLAY(bound_splay_end);
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
-
- for (;;) {
- comp = compare_end(addr, t->start + t->size);
- if (comp < 0) {
- y = t->left;
- if (y == NULL) break;
- if (compare_end(addr, y->start + y->size) < 0) {
- t->left = y->right; /* rotate right */
- y->right = t;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- } else if (comp > 0) {
- y = t->right;
- if (y == NULL) break;
- if (compare_end(addr, y->start + y->size) > 0) {
- t->right = y->left; /* rotate left */
- y->left = t;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- } else {
- break;
- }
- }
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
-
- return t;
-}
-
-static Tree * splay_insert(size_t addr, size_t size, Tree * t)
-/* Insert key start into the tree t, if it is not already there. */
-/* Return a pointer to the resulting tree. */
-{
- Tree * new;
-
- INCR_COUNT_SPLAY(bound_splay_insert);
- if (t != NULL) {
- t = splay(addr,t);
- if (compare(addr, t->start, t->size)==0) {
- return t; /* it's already there */
- }
- }
-#if TREE_REUSE
- if (tree_free_list) {
- new = tree_free_list;
- tree_free_list = new->left;
- }
- else
-#endif
- {
- new = (Tree *) BOUND_MALLOC (sizeof (Tree));
- }
- if (new == NULL) {
- bound_alloc_error("not enough memory for bound checking code");
- }
- else {
- if (t == NULL) {
- new->left = new->right = NULL;
- } else if (compare(addr, t->start, t->size) < 0) {
- new->left = t->left;
- new->right = t;
- t->left = NULL;
- } else {
- new->right = t->right;
- new->left = t;
- t->right = NULL;
- }
- new->start = addr;
- new->size = size;
- new->type = TCC_TYPE_NONE;
- new->is_invalid = 0;
- }
- return new;
-}
-
-#define compare_destroy(start,tstart) (start < tstart ? -1 : \
- start > tstart ? 1 : 0)
-
-static Tree * splay_delete(size_t addr, Tree *t)
-/* Deletes addr from the tree if it's there. */
-/* Return a pointer to the resulting tree. */
-{
- Tree * x;
-
- INCR_COUNT_SPLAY(bound_splay_delete);
- if (t==NULL) return NULL;
- t = splay(addr,t);
- if (compare_destroy(addr, t->start) == 0) { /* found it */
- if (t->left == NULL) {
- x = t->right;
- } else {
- x = splay(addr, t->left);
- x->right = t->right;
- }
-#if TREE_REUSE
- t->left = tree_free_list;
- tree_free_list = t;
-#else
- BOUND_FREE(t);
-#endif
- return x;
- } else {
- return t; /* It wasn't there */
- }
-}
-
-void splay_printtree(Tree * t, int d)
-{
- int i;
- if (t == NULL) return;
- splay_printtree(t->right, d+1);
- for (i=0; i<d; i++) fprintf(stderr," ");
- fprintf(stderr,"%p(0x%lx:%u:%u)\n",
- (void *) t->start, (unsigned long) t->size,
- (unsigned)t->type, (unsigned)t->is_invalid);
- splay_printtree(t->left, d+1);
-}