| @@ -34,17 +34,20 @@ · 33 unmodified lines |
| 34 | #include <unistd.h> | 34 | #include <unistd.h> |
| 35 | #endif | 35 | #endif |
| 36 | | 36 | |
| 37 | #define BOUND_DEBUG | 37 | #define BOUND_DEBUG (1) |
| 38 | #define BOUND_STATISTIC | 38 | #define BOUND_STATISTIC (1) |
| 39 | | 39 | |
| 40 | #ifdef BOUND_DEBUG | 40 | #if BOUND_DEBUG |
| 41 | #define dprintf(a...) if (print_calls) fprintf(a) | 41 | #define dprintf(a...) if (print_calls) fprintf(a) |
| 42 | #else | 42 | #else |
| 43 | #define dprintf(a...) | 43 | #define dprintf(a...) |
| 44 | #endif | 44 | #endif |
| 45 | | 45 | |
| 46 | /* Check memalign */ | 46 | #ifdef __attribute__ |
| 47 | #define HAVE_MEMALIGN | 47 | /* an __attribute__ macro is defined in the system headers */ |
| | 48 | #undef __attribute__ |
| | 49 | #endif |
| | 50 | #define FASTCALL __attribute__((regparm(3))) |
| 48 | | 51 | |
| 49 | #if defined(__FreeBSD__) \ | 52 | #if defined(__FreeBSD__) \ |
| 50 | || defined(__FreeBSD_kernel__) \ | 53 | || defined(__FreeBSD_kernel__) \ |
| @@ -52,43 +55,76 @@ · 1 unmodified line |
| 52 | || defined(__OpenBSD__) \ | 55 | || defined(__OpenBSD__) \ |
| 53 | || defined(__NetBSD__) \ | 56 | || defined(__NetBSD__) \ |
| 54 | || defined(__dietlibc__) | 57 | || defined(__dietlibc__) |
| 55 | #undef HAVE_MEMALIGN | 58 | |
| 56 | #define INIT_SEM() | 59 | #define INIT_SEM() |
| 57 | #define EXIT_SEM() | 60 | #define EXIT_SEM() |
| 58 | #define WAIT_SEM() | 61 | #define WAIT_SEM() |
| 59 | #define POST_SEM() | 62 | #define POST_SEM() |
| 60 | #define HAS_ENVIRON 0 | 63 | #define HAVE_MEMALIGN (0) |
| 61 | #define MALLOC_REDIR (0) | 64 | #define HAS_ENVIRON (0) |
| | 65 | #define MALLOC_REDIR (0) |
| | 66 | #define HAVE_PTHREAD_CREATE (0) |
| | 67 | #define HAVE_CTYPE (0) |
| | 68 | #define HAVE_ERRNO (0) |
| | 69 | |
| 62 | #elif defined(_WIN32) | 70 | #elif defined(_WIN32) |
| | 71 | |
| 63 | #include <windows.h> | 72 | #include <windows.h> |
| 64 | #undef HAVE_MEMALIGN | | |
| 65 | static CRITICAL_SECTION bounds_sem; | 73 | static CRITICAL_SECTION bounds_sem; |
| 66 | #define INIT_SEM() InitializeCriticalSection(&bounds_sem) | 74 | #define INIT_SEM() InitializeCriticalSection(&bounds_sem) |
| 67 | #define EXIT_SEM() DeleteCriticalSection(&bounds_sem) | 75 | #define EXIT_SEM() DeleteCriticalSection(&bounds_sem) |
| 68 | #define WAIT_SEM() EnterCriticalSection(&bounds_sem) | 76 | #define WAIT_SEM() EnterCriticalSection(&bounds_sem) |
| 69 | #define POST_SEM() LeaveCriticalSection(&bounds_sem) | 77 | #define POST_SEM() LeaveCriticalSection(&bounds_sem) |
| 70 | #define HAS_ENVIRON 0 | 78 | #define HAVE_MEMALIGN (0) |
| 71 | #define MALLOC_REDIR (0) | 79 | #define HAS_ENVIRON (0) |
| | 80 | #define MALLOC_REDIR (0) |
| | 81 | #define HAVE_PTHREAD_CREATE (0) |
| | 82 | #define HAVE_CTYPE (0) |
| | 83 | #define HAVE_ERRNO (0) |
| | 84 | |
| 72 | #else | 85 | #else |
| | 86 | |
| | 87 | #define __USE_GNU /* get RTLD_NEXT */ |
| 73 | #include <sys/mman.h> | 88 | #include <sys/mman.h> |
| | 89 | #include <ctype.h> |
| | 90 | #include <pthread.h> |
| | 91 | #include <dlfcn.h> |
| 74 | #include <errno.h> | 92 | #include <errno.h> |
| | 93 | #if 0 |
| 75 | #include <semaphore.h> | 94 | #include <semaphore.h> |
| 76 | static sem_t bounds_sem; | 95 | static sem_t bounds_sem; |
| 77 | #define INIT_SEM() sem_init (&bounds_sem, 0, 1) | 96 | #define INIT_SEM() sem_init (&bounds_sem, 0, 1) |
| 78 | #define EXIT_SEM() sem_destroy (&bounds_sem) | 97 | #define EXIT_SEM() sem_destroy (&bounds_sem) |
| 79 | #define WAIT_SEM() while (sem_wait (&bounds_sem) < 0 && errno == EINTR); | 98 | #define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \ |
| 80 | #define POST_SEM() sem_post (&bounds_sem) | 99 | && errno == EINTR) |
| 81 | #define HAS_ENVIRON 0 /* Disabled for now */ | 100 | #define POST_SEM() if (use_sem) sem_post (&bounds_sem) |
| 82 | #define __USE_GNU /* get RTLD_NEXT */ | 101 | #else |
| 83 | #include <dlfcn.h> | 102 | static pthread_spinlock_t bounds_spin; |
| 84 | #define MALLOC_REDIR (1) | 103 | /* about 25% faster then semaphore. */ |
| 85 | static void *(*malloc_redir) (size_t) = NULL; | 104 | #define INIT_SEM() pthread_spin_init (&bounds_spin, 0) |
| 86 | static void *(*calloc_redir) (size_t, size_t) = NULL; | 105 | #define EXIT_SEM() pthread_spin_destroy (&bounds_spin) |
| 87 | static void (*free_redir) (void *) = NULL; | 106 | #define WAIT_SEM() if (use_sem) pthread_spin_lock (&bounds_spin) |
| 88 | static void *(*realloc_redir) (void *, size_t) = NULL; | 107 | #define POST_SEM() if (use_sem) pthread_spin_unlock (&bounds_spin) |
| 89 | static void *(*memalign_redir) (size_t, size_t) = NULL; | 108 | #endif |
| 90 | static int pool_index = 0; | 109 | #define HAVE_MEMALIGN (1) |
| 91 | static unsigned char initial_pool[256]; | 110 | #define HAS_ENVIRON (1) |
| | 111 | #define MALLOC_REDIR (1) |
| | 112 | #define HAVE_PTHREAD_CREATE (1) |
| | 113 | #define HAVE_CTYPE (1) |
| | 114 | #define HAVE_ERRNO (1) |
| | 115 | |
| | 116 | static void *(*malloc_redir) (size_t); |
| | 117 | static void *(*calloc_redir) (size_t, size_t); |
| | 118 | static void (*free_redir) (void *); |
| | 119 | static void *(*realloc_redir) (void *, size_t); |
| | 120 | static void *(*memalign_redir) (size_t, size_t); |
| | 121 | static int (*pthread_create_redir) (pthread_t *thread, |
| | 122 | const pthread_attr_t *attr, |
| | 123 | void *(*start_routine)(void *), void *arg); |
| | 124 | static unsigned int pool_index; |
| | 125 | static unsigned char __attribute__((aligned(16))) initial_pool[256]; |
| | 126 | static unsigned char use_sem; |
| | 127 | |
| 92 | #endif | 128 | #endif |
| 93 | | 129 | |
| 94 | #define TCC_TYPE_NONE (0) | 130 | #define TCC_TYPE_NONE (0) |
| @@ -106,8 +142,8 @@ struct tree_node { · 11 unmodified lines |
| 106 | Tree * left, * right; | 142 | Tree * left, * right; |
| 107 | size_t start; | 143 | size_t start; |
| 108 | size_t size; | 144 | size_t size; |
| 109 | size_t type; | 145 | unsigned char type; |
| 110 | size_t is_invalid; /* true if pointers outside region are invalid */ | 146 | unsigned char is_invalid; /* true if pointers outside region are invalid */ |
| 111 | }; | 147 | }; |
| 112 | | 148 | |
| 113 | typedef struct alloca_list_struct { | 149 | typedef struct alloca_list_struct { |
| @@ -116,6 +152,7 @@ typedef struct alloca_list_struct { · 2 unmodified lines |
| 116 | struct alloca_list_struct *next; | 152 | struct alloca_list_struct *next; |
| 117 | } alloca_list_type; | 153 | } alloca_list_type; |
| 118 | | 154 | |
| | 155 | #define BOUND_STATISTIC_SPLAY (0) |
| 119 | static Tree * splay (size_t addr, Tree *t); | 156 | static Tree * splay (size_t addr, Tree *t); |
| 120 | static Tree * splay_end (size_t addr, Tree *t); | 157 | static Tree * splay_end (size_t addr, Tree *t); |
| 121 | static Tree * splay_insert(size_t addr, size_t size, Tree * t); | 158 | static Tree * splay_insert(size_t addr, size_t size, Tree * t); |
| @@ -123,14 +160,38 @@ static Tree * splay_delete(size_t addr, Tree *t); · 1 unmodified line |
| 123 | void splay_printtree(Tree * t, int d); | 160 | void splay_printtree(Tree * t, int d); |
| 124 | | 161 | |
| 125 | /* external interface */ | 162 | /* external interface */ |
| | 163 | void __bound_checking (int no_check); |
| | 164 | void __bound_never_fatal (int no_check); |
| | 165 | void * __bound_ptr_add(void *p, size_t offset); |
| | 166 | void * __bound_ptr_indir1(void *p, size_t offset); |
| | 167 | void * __bound_ptr_indir2(void *p, size_t offset); |
| | 168 | void * __bound_ptr_indir4(void *p, size_t offset); |
| | 169 | void * __bound_ptr_indir8(void *p, size_t offset); |
| | 170 | void * __bound_ptr_indir12(void *p, size_t offset); |
| | 171 | void * __bound_ptr_indir16(void *p, size_t offset); |
| | 172 | void FASTCALL __bound_local_new(void *p1); |
| | 173 | void FASTCALL __bound_local_delete(void *p1); |
| 126 | void __bound_init(void); | 174 | void __bound_init(void); |
| | 175 | void __bound_main_arg(char **p); |
| 127 | void __bound_exit(void); | 176 | void __bound_exit(void); |
| 128 | | 177 | #if !defined(_WIN32) |
| 129 | #ifdef __attribute__ | 178 | void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd, |
| 130 | /* an __attribute__ macro is defined in the system headers */ | 179 | off_t offset); |
| 131 | #undef __attribute__ | 180 | int __bound_munmap (void *start, size_t size); |
| 132 | #endif | 181 | #endif |
| 133 | #define FASTCALL __attribute__((regparm(3))) | 182 | void __bound_new_region(void *p, size_t size); |
| | 183 | void *__bound_memcpy(void *dst, const void *src, size_t size); |
| | 184 | int __bound_memcmp(const void *s1, const void *s2, size_t size); |
| | 185 | void *__bound_memmove(void *dst, const void *src, size_t size); |
| | 186 | void *__bound_memset(void *dst, int c, size_t size); |
| | 187 | int __bound_strlen(const char *s); |
| | 188 | char *__bound_strcpy(char *dst, const char *src); |
| | 189 | char *__bound_strncpy(char *dst, const char *src, size_t n); |
| | 190 | int __bound_strcmp(const char *s1, const char *s2); |
| | 191 | int __bound_strncmp(const char *s1, const char *s2, size_t n); |
| | 192 | char *__bound_strcat(char *dest, const char *src); |
| | 193 | char *__bound_strchr(const char *string, int ch); |
| | 194 | char *__bound_strdup(const char *s); |
| 134 | | 195 | |
| 135 | #if !MALLOC_REDIR | 196 | #if !MALLOC_REDIR |
| 136 | void *__bound_malloc(size_t size, const void *caller); | 197 | void *__bound_malloc(size_t size, const void *caller); |
| @@ -141,30 +202,30 @@ void *__bound_calloc(size_t nmemb, size_t size); · 4 unmodified lines |
| 141 | #endif | 202 | #endif |
| 142 | | 203 | |
| 143 | #define FREE_REUSE_SIZE (100) | 204 | #define FREE_REUSE_SIZE (100) |
| 144 | static int free_reuse_index = 0; | 205 | static unsigned int free_reuse_index; |
| 145 | static void *free_reuse_list[FREE_REUSE_SIZE]; | 206 | static void *free_reuse_list[FREE_REUSE_SIZE]; |
| 146 | | 207 | |
| 147 | /* error message, just for TCC */ | 208 | /* error message, just for TCC */ |
| 148 | const char *__bound_error_msg; | 209 | const char *__bound_error_msg; |
| 149 | | 210 | |
| 150 | /* runtime error output */ | | |
| 151 | extern void rt_error(size_t pc, const char *fmt, ...); | | |
| 152 | | | |
| 153 | static Tree *tree = NULL; | 211 | static Tree *tree = NULL; |
| 154 | #define TREE_REUSE (1) | 212 | #define TREE_REUSE (1) |
| 155 | #if TREE_REUSE | 213 | #if TREE_REUSE |
| 156 | static Tree *tree_free_list = NULL; | 214 | static Tree *tree_free_list; |
| 157 | #endif | 215 | #endif |
| 158 | static alloca_list_type *alloca_list = NULL; | 216 | static alloca_list_type *alloca_list; |
| 159 | | 217 | |
| 160 | static int inited = 0; | 218 | static unsigned char inited; |
| 161 | static int print_calls = 0; | 219 | static unsigned char print_warn_ptr_add; |
| 162 | static int print_heap = 0; | 220 | static unsigned char print_calls; |
| 163 | static int print_statistic = 0; | 221 | static unsigned char print_heap; |
| 164 | static int never_fatal = 0; | 222 | static unsigned char print_statistic; |
| 165 | static int no_checking = 0; | 223 | static unsigned char no_strdup; |
| 166 | | 224 | static signed char never_fatal; |
| 167 | #ifdef BOUND_STATISTIC | 225 | static signed char no_checking = 1; |
| | 226 | static char exec[100]; |
| | 227 | |
| | 228 | #if BOUND_STATISTIC |
| 168 | static unsigned long long bound_ptr_add_count; | 229 | static unsigned long long bound_ptr_add_count; |
| 169 | static unsigned long long bound_ptr_indir1_count; | 230 | static unsigned long long bound_ptr_indir1_count; |
| 170 | static unsigned long long bound_ptr_indir2_count; | 231 | static unsigned long long bound_ptr_indir2_count; |
| @@ -194,46 +255,93 @@ static unsigned long long bound_strncmp_count; · 23 unmodified lines |
| 194 | static unsigned long long bound_strcat_count; | 255 | static unsigned long long bound_strcat_count; |
| 195 | static unsigned long long bound_strchr_count; | 256 | static unsigned long long bound_strchr_count; |
| 196 | static unsigned long long bound_strdup_count; | 257 | static unsigned long long bound_strdup_count; |
| 197 | #define INCR_COUNT(x) x++ | 258 | static unsigned long long bound_not_found; |
| | 259 | #define INCR_COUNT(x) ++x |
| 198 | #else | 260 | #else |
| 199 | #define INCR_COUNT(x) | 261 | #define INCR_COUNT(x) |
| 200 | #endif | 262 | #endif |
| | 263 | #if BOUND_STATISTIC_SPLAY |
| | 264 | static unsigned long long bound_splay; |
| | 265 | static unsigned long long bound_splay_end; |
| | 266 | static unsigned long long bound_splay_insert; |
| | 267 | static unsigned long long bound_splay_delete; |
| | 268 | #define INCR_COUNT_SPLAY(x) ++x |
| | 269 | #else |
| | 270 | #define INCR_COUNT_SPLAY(x) |
| | 271 | #endif |
| 201 | | 272 | |
| 202 | /* enable/disable checking. This can be used for signal handlers. */ | 273 | /* currently only i386/x86_64 supported. Change for other platforms */ |
| | 274 | static void fetch_and_add(signed char* variable, signed char value) |
| | 275 | { |
| | 276 | #if defined __i386__ || defined __x86_64__ |
| | 277 | __asm__ volatile("lock; addb %0, %1" |
| | 278 | : "+r" (value), "+m" (*variable) // input+output |
| | 279 | : // No input-only |
| | 280 | : "memory" |
| | 281 | ); |
| | 282 | #else |
| | 283 | *variable += value; |
| | 284 | #endif |
| | 285 | } |
| | 286 | |
| | 287 | /* enable/disable checking. This can be used in signal handlers. */ |
| 203 | void __bound_checking (int no_check) | 288 | void __bound_checking (int no_check) |
| 204 | { | 289 | { |
| 205 | no_checking = no_check; | 290 | fetch_and_add (&no_checking, no_check); |
| 206 | } | 291 | } |
| 207 | | 292 | |
| 208 | #define no_FASTCALL | 293 | /* enable/disable checking. This can be used in signal handlers. */ |
| 209 | //#define no_checking 1 | 294 | void __bound_never_fatal (int neverfatal) |
| | 295 | { |
| | 296 | fetch_and_add (&never_fatal, neverfatal); |
| | 297 | } |
| 210 | | 298 | |
| 211 | /* print a bound error message */ | 299 | /* print a bound error message */ |
| 212 | static void bound_error(const char *fmt, ...) | 300 | static void bound_error(const char *error) |
| 213 | { | 301 | { |
| 214 | __bound_error_msg = fmt; | 302 | __bound_error_msg = error; |
| 215 | fprintf(stderr,"%s %s: %s\n", __FILE__, __FUNCTION__, fmt); | 303 | fprintf(stderr,"%s%s %s: %s\n", exec, __FILE__, __FUNCTION__, error); |
| 216 | if (never_fatal == 0) | 304 | if (never_fatal == 0) |
| 217 | *(void **)0 = 0; /* force a runtime error */ | 305 | *(void **)0 = 0; /* force a runtime error */ |
| 218 | } | 306 | } |
| 219 | | 307 | |
| 220 | static void bound_alloc_error(void) | 308 | static void bound_alloc_error(const char *s) |
| | 309 | { |
| | 310 | fprintf(stderr,"FATAL: %s\n",s); |
| | 311 | exit (1); |
| | 312 | } |
| | 313 | |
| | 314 | static void bound_not_found_warning(const char *file, const char *function, |
| | 315 | void *ptr) |
| | 316 | { |
| | 317 | dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr); |
| | 318 | } |
| | 319 | |
| | 320 | static void bound_ptr_add_warning(const char *file, const char *function, |
| | 321 | void *ptr) |
| 221 | { | 322 | { |
| 222 | bound_error("not enough memory for bound checking code"); | 323 | fprintf(stderr,"%s%s %s(): %p is outside of the region\n", |
| | 324 | exec, file, function, ptr); |
| | 325 | } |
| | 326 | |
| | 327 | static void bound_ptr_indir_error(const char *file, const char *function, |
| | 328 | void *ptr) |
| | 329 | { |
| | 330 | fprintf(stderr,"%s%s %s(): %p is outside of the region\n", |
| | 331 | exec, file, function, ptr); |
| 223 | } | 332 | } |
| 224 | | 333 | |
| 225 | /* return '(p + offset)' for pointer arithmetic (a pointer can reach | 334 | /* return '(p + offset)' for pointer arithmetic (a pointer can reach |
| 226 | the end of a region in this case */ | 335 | the end of a region in this case */ |
| 227 | void * no_FASTCALL __bound_ptr_add(void *p, size_t offset) | 336 | void * __bound_ptr_add(void *p, size_t offset) |
| 228 | { | 337 | { |
| 229 | size_t addr = (size_t)p; | 338 | size_t addr = (size_t)p; |
| 230 | | 339 | |
| 231 | if (no_checking) { | 340 | if (no_checking) |
| 232 | return p + offset; | 341 | return p + offset; |
| 233 | } | | |
| 234 | | 342 | |
| 235 | dprintf(stderr, "%s %s : %p 0x%x\n", | 343 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", |
| 236 | __FILE__, __FUNCTION__, p, (unsigned)offset); | 344 | __FILE__, __FUNCTION__, p, (unsigned long)offset); |
| 237 | | 345 | |
| 238 | WAIT_SEM (); | 346 | WAIT_SEM (); |
| 239 | INCR_COUNT(bound_ptr_add_count); | 347 | INCR_COUNT(bound_ptr_add_count); |
| @@ -250,18 +358,21 @@ void * no_FASTCALL __bound_ptr_add(void *p, size_t offset) · 10 unmodified lines |
| 250 | addr -= tree->start; | 358 | addr -= tree->start; |
| 251 | } | 359 | } |
| 252 | if (addr <= tree->size) { | 360 | if (addr <= tree->size) { |
| 253 | addr += offset; | 361 | if (tree->is_invalid || addr + offset > tree->size) { |
| 254 | if (tree->is_invalid || addr > tree->size) { | 362 | POST_SEM (); |
| 255 | #if 0 | 363 | if (print_warn_ptr_add) |
| 256 | fprintf(stderr,"%s %s : %p is outside of the region\n", | 364 | bound_ptr_add_warning (__FILE__, __FUNCTION__, p + offset); |
| 257 | __FILE__, __FUNCTION__, p + offset); | 365 | if (never_fatal <= 0) |
| 258 | #endif | | |
| 259 | if (never_fatal == 0) { | | |
| 260 | POST_SEM (); | | |
| 261 | return INVALID_POINTER; /* return an invalid pointer */ | 366 | return INVALID_POINTER; /* return an invalid pointer */ |
| 262 | } | 367 | return p + offset; |
| 263 | } | 368 | } |
| 264 | } | 369 | } |
| | 370 | else if (p) { /* Allow NULL + offset. offsetoff is using it. */ |
| | 371 | INCR_COUNT(bound_not_found); |
| | 372 | POST_SEM (); |
| | 373 | bound_not_found_warning (__FILE__, __FUNCTION__, p); |
| | 374 | return p + offset; |
| | 375 | } |
| 265 | } | 376 | } |
| 266 | POST_SEM (); | 377 | POST_SEM (); |
| 267 | return p + offset; | 378 | return p + offset; |
| @@ -270,15 +381,15 @@ void * no_FASTCALL __bound_ptr_add(void *p, size_t offset) · 2 unmodified lines |
| 270 | /* return '(p + offset)' for pointer indirection (the resulting must | 381 | /* return '(p + offset)' for pointer indirection (the resulting must |
| 271 | be strictly inside the region */ | 382 | be strictly inside the region */ |
| 272 | #define BOUND_PTR_INDIR(dsize) \ | 383 | #define BOUND_PTR_INDIR(dsize) \ |
| 273 | void * no_FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ | 384 | void * __bound_ptr_indir ## dsize (void *p, size_t offset) \ |
| 274 | { \ | 385 | { \ |
| 275 | size_t addr = (size_t)p; \ | 386 | size_t addr = (size_t)p; \ |
| 276 | \ | 387 | \ |
| 277 | if (no_checking) { \ | 388 | if (no_checking) \ |
| 278 | return p + offset; \ | 389 | return p + offset; \ |
| 279 | } \ | 390 | \ |
| 280 | dprintf(stderr, "%s %s : %p 0x%x start\n", \ | 391 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", \ |
| 281 | __FILE__, __FUNCTION__, p, (unsigned)offset); \ | 392 | __FILE__, __FUNCTION__, p, (unsigned long)offset); \ |
| 282 | WAIT_SEM (); \ | 393 | WAIT_SEM (); \ |
| 283 | INCR_COUNT(bound_ptr_indir ## dsize ## _count); \ | 394 | INCR_COUNT(bound_ptr_indir ## dsize ## _count); \ |
| 284 | if (tree) { \ | 395 | if (tree) { \ |
| @@ -294,16 +405,21 @@ void * no_FASTCALL __bound_ptr_indir ## dsize (void *p, size_t offset) \ · 9 unmodified lines |
| 294 | addr -= tree->start; \ | 405 | addr -= tree->start; \ |
| 295 | } \ | 406 | } \ |
| 296 | if (addr <= tree->size) { \ | 407 | if (addr <= tree->size) { \ |
| 297 | addr += offset + dsize; \ | 408 | if (tree->is_invalid || addr + offset + dsize > tree->size) { \ |
| 298 | if (tree->is_invalid || addr > tree->size) { \ | 409 | POST_SEM (); \ |
| 299 | fprintf(stderr,"%s %s : %p is outside of the region\n", \ | 410 | bound_ptr_indir_error (__FILE__, __FUNCTION__, \ |
| 300 | __FILE__, __FUNCTION__, p + offset); \ | 411 | p + offset); \ |
| 301 | if (never_fatal == 0) { \ | 412 | if (never_fatal <= 0) \ |
| 302 | POST_SEM (); \ | | |
| 303 | return INVALID_POINTER; /* return an invalid pointer */ \ | 413 | return INVALID_POINTER; /* return an invalid pointer */ \ |
| 304 | } \ | 414 | return p + offset; \ |
| 305 | } \ | 415 | } \ |
| 306 | } \ | 416 | } \ |
| | 417 | else { \ |
| | 418 | INCR_COUNT(bound_not_found); \ |
| | 419 | POST_SEM (); \ |
| | 420 | bound_not_found_warning (__FILE__, __FUNCTION__, p); \ |
| | 421 | return p + offset; \ |
| | 422 | } \ |
| 307 | } \ | 423 | } \ |
| 308 | POST_SEM (); \ | 424 | POST_SEM (); \ |
| 309 | return p + offset; \ | 425 | return p + offset; \ |
| @@ -334,90 +450,180 @@ BOUND_PTR_INDIR(16) · 24 unmodified lines |
| 334 | /* called when entering a function to add all the local regions */ | 450 | /* called when entering a function to add all the local regions */ |
| 335 | void FASTCALL __bound_local_new(void *p1) | 451 | void FASTCALL __bound_local_new(void *p1) |
| 336 | { | 452 | { |
| 337 | size_t addr, size, fp, *p = p1; | 453 | size_t addr, fp, *p = p1; |
| 338 | | 454 | |
| 339 | if (no_checking) | 455 | if (no_checking) |
| 340 | return; | 456 | return; |
| 341 | GET_CALLER_FP(fp); | 457 | GET_CALLER_FP(fp); |
| 342 | dprintf(stderr, "%s, %s local new p1=%p fp=%p\n", | 458 | dprintf(stderr, "%s, %s(): p1=%p fp=%p\n", |
| 343 | __FILE__, __FUNCTION__, p, (void *)fp); | 459 | __FILE__, __FUNCTION__, p, (void *)fp); |
| 344 | WAIT_SEM (); | 460 | WAIT_SEM (); |
| 345 | for(;;) { | 461 | while ((addr = p[0])) { |
| 346 | addr = p[0]; | | |
| 347 | if (addr == 0) | | |
| 348 | break; | | |
| 349 | INCR_COUNT(bound_local_new_count); | 462 | INCR_COUNT(bound_local_new_count); |
| 350 | if (addr == 1) { | 463 | if (addr != 1) |
| 351 | dprintf(stderr, "%s, %s() alloca/vla used\n", | 464 | tree = splay_insert(addr + fp, p[1], tree); |
| 352 | __FILE__, __FUNCTION__); | | |
| 353 | } | | |
| 354 | else { | | |
| 355 | addr += fp; | | |
| 356 | size = p[1]; | | |
| 357 | dprintf(stderr, "%s, %s() (%p 0x%lx)\n", | | |
| 358 | __FILE__, __FUNCTION__, (void *) addr, (unsigned long) size); | | |
| 359 | tree = splay_insert(addr, size, tree); | | |
| 360 | } | | |
| 361 | p += 2; | 465 | p += 2; |
| 362 | } | 466 | } |
| 363 | POST_SEM (); | 467 | POST_SEM (); |
| | 468 | #if BOUND_DEBUG |
| | 469 | if (print_calls) { |
| | 470 | p = p1; |
| | 471 | while ((addr = p[0])) { |
| | 472 | if (addr == 1) { |
| | 473 | dprintf(stderr, "%s, %s(): alloca/vla used\n", |
| | 474 | __FILE__, __FUNCTION__); |
| | 475 | } |
| | 476 | else { |
| | 477 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", |
| | 478 | __FILE__, __FUNCTION__, |
| | 479 | (void *) (addr + fp), (unsigned long) p[1]); |
| | 480 | } |
| | 481 | p += 2; |
| | 482 | } |
| | 483 | } |
| | 484 | #endif |
| 364 | } | 485 | } |
| 365 | | 486 | |
| 366 | /* called when leaving a function to delete all the local regions */ | 487 | /* called when leaving a function to delete all the local regions */ |
| 367 | void FASTCALL __bound_local_delete(void *p1) | 488 | void FASTCALL __bound_local_delete(void *p1) |
| 368 | { | 489 | { |
| 369 | size_t addr, fp, *p = p1; | 490 | size_t addr, fp, *p = p1; |
| | 491 | alloca_list_type *free_list = NULL; |
| 370 | | 492 | |
| 371 | if (no_checking) | 493 | if (no_checking) |
| 372 | return; | 494 | return; |
| 373 | GET_CALLER_FP(fp); | 495 | GET_CALLER_FP(fp); |
| 374 | dprintf(stderr, "%s, %s local delete p1=%p fp=%p\n", | 496 | dprintf(stderr, "%s, %s(): p1=%p fp=%p\n", |
| 375 | __FILE__, __FUNCTION__, p, (void *)fp); | 497 | __FILE__, __FUNCTION__, p, (void *)fp); |
| 376 | WAIT_SEM (); | 498 | WAIT_SEM (); |
| 377 | for(;;) { | 499 | while ((addr = p[0])) { |
| 378 | addr = p[0]; | | |
| 379 | if (addr == 0) | | |
| 380 | break; | | |
| 381 | INCR_COUNT(bound_local_delete_count); | 500 | INCR_COUNT(bound_local_delete_count); |
| 382 | if (addr == 1) { | 501 | if (addr == 1) { |
| 383 | while (alloca_list && alloca_list->fp == fp) { | 502 | alloca_list_type *last = NULL; |
| 384 | alloca_list_type *next = alloca_list->next; | 503 | alloca_list_type *cur = alloca_list; |
| | 504 | |
| | 505 | while (cur) { |
| | 506 | if (cur->fp == fp) { |
| | 507 | if (last) |
| | 508 | last->next = cur->next; |
| | 509 | else |
| | 510 | alloca_list = cur->next; |
| | 511 | tree = splay_delete ((size_t) cur->p, tree); |
| | 512 | cur->next = free_list; |
| | 513 | free_list = cur; |
| | 514 | cur = last ? last->next : alloca_list; |
| | 515 | } |
| | 516 | else { |
| | 517 | last = cur; |
| | 518 | cur = cur->next; |
| | 519 | } |
| | 520 | } |
| | 521 | } |
| | 522 | else |
| | 523 | tree = splay_delete(addr + fp, tree); |
| | 524 | p += 2; |
| | 525 | } |
| | 526 | POST_SEM (); |
| | 527 | while (free_list) { |
| | 528 | alloca_list_type *next = free_list->next; |
| 385 | | 529 | |
| 386 | dprintf(stderr, "%s, %s() remove alloca/vla %p\n", | 530 | dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", |
| 387 | __FILE__, __FUNCTION__, alloca_list->p); | 531 | __FILE__, __FUNCTION__, free_list->p); |
| 388 | tree = splay_delete ((size_t) alloca_list->p, tree); | | |
| 389 | #if MALLOC_REDIR | 532 | #if MALLOC_REDIR |
| 390 | free_redir (alloca_list); | 533 | free_redir (free_list); |
| 391 | #else | 534 | #else |
| 392 | free (alloca_list); | 535 | free (free_list); |
| 393 | #endif | 536 | #endif |
| 394 | alloca_list = next; | 537 | free_list = next; |
| | 538 | } |
| | 539 | #if BOUND_DEBUG |
| | 540 | if (print_calls) { |
| | 541 | p = p1; |
| | 542 | while ((addr = p[0])) { |
| | 543 | if (addr != 1) { |
| | 544 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", |
| | 545 | __FILE__, __FUNCTION__, |
| | 546 | (void *) (addr + fp), (unsigned long) p[1]); |
| 395 | } | 547 | } |
| | 548 | p+= 2; |
| 396 | } | 549 | } |
| 397 | else { | 550 | } |
| 398 | addr += fp; | 551 | #endif |
| 399 | dprintf(stderr, "%s, %s() (%p 0x%lx)\n", | 552 | } |
| 400 | __FILE__, __FUNCTION__, (void *) addr, (unsigned long) p[1]); | 553 | |
| 401 | tree = splay_delete(addr, tree); | 554 | /* used by alloca */ |
| | 555 | void __bound_new_region(void *p, size_t size) |
| | 556 | { |
| | 557 | size_t fp; |
| | 558 | alloca_list_type *last; |
| | 559 | alloca_list_type *cur; |
| | 560 | alloca_list_type *new; |
| | 561 | |
| | 562 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| | 563 | __FILE__, __FUNCTION__, p, (unsigned long)size); |
| | 564 | GET_CALLER_FP (fp); |
| | 565 | #if MALLOC_REDIR |
| | 566 | new = malloc_redir (sizeof (alloca_list_type)); |
| | 567 | #else |
| | 568 | new = malloc (sizeof (alloca_list_type)); |
| | 569 | #endif |
| | 570 | WAIT_SEM (); |
| | 571 | INCR_COUNT(bound_alloca_count); |
| | 572 | last = NULL; |
| | 573 | cur = alloca_list; |
| | 574 | while (cur) { |
| | 575 | if (cur->fp == fp && cur->p == p) { |
| | 576 | if (last) |
| | 577 | last->next = cur->next; |
| | 578 | else |
| | 579 | alloca_list = cur->next; |
| | 580 | tree = splay_delete((size_t)p, tree); |
| | 581 | break; |
| 402 | } | 582 | } |
| 403 | p += 2; | 583 | last = cur; |
| | 584 | cur = cur->next; |
| | 585 | } |
| | 586 | if (no_checking == 0) |
| | 587 | tree = splay_insert((size_t)p, size, tree); |
| | 588 | if (new) { |
| | 589 | new->fp = fp; |
| | 590 | new->p = p; |
| | 591 | new->next = alloca_list; |
| | 592 | alloca_list = new; |
| 404 | } | 593 | } |
| 405 | POST_SEM (); | 594 | POST_SEM (); |
| | 595 | if (cur) { |
| | 596 | dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", |
| | 597 | __FILE__, __FUNCTION__, cur->p); |
| | 598 | #if MALLOC_REDIR |
| | 599 | free_redir (cur); |
| | 600 | #else |
| | 601 | free (cur); |
| | 602 | #endif |
| | 603 | } |
| 406 | } | 604 | } |
| 407 | | 605 | |
| 408 | void __bound_init(void) | 606 | #if defined(__GNUC__) && (__GNUC__ >= 6) |
| | 607 | #pragma GCC diagnostic pop |
| | 608 | #endif |
| | 609 | |
| | 610 | void __attribute__((constructor)) __bound_init(void) |
| 409 | { | 611 | { |
| | 612 | extern size_t __bounds_start[]; |
| | 613 | size_t *p; |
| | 614 | |
| 410 | if (inited) | 615 | if (inited) |
| 411 | return; | 616 | return; |
| 412 | | 617 | |
| 413 | inited = 1; | 618 | inited = 1; |
| 414 | | 619 | |
| | 620 | print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL; |
| 415 | print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL; | 621 | print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL; |
| 416 | print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL; | 622 | print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL; |
| 417 | print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL; | 623 | print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL; |
| 418 | never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL; | 624 | never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL; |
| 419 | | 625 | |
| 420 | dprintf(stderr, "%s, %s() start\n", __FILE__, __FUNCTION__); | 626 | dprintf(stderr, "%s, %s(): start\n", __FILE__, __FUNCTION__); |
| 421 | | 627 | |
| 422 | INIT_SEM (); | 628 | INIT_SEM (); |
| 423 | | 629 | |
| @@ -428,7 +634,7 @@ void __bound_init(void) · 4 unmodified lines |
| 428 | /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT */ | 634 | /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT */ |
| 429 | *(void **) (&malloc_redir) = dlsym (addr, "malloc"); | 635 | *(void **) (&malloc_redir) = dlsym (addr, "malloc"); |
| 430 | if (malloc_redir == NULL) { | 636 | if (malloc_redir == NULL) { |
| 431 | dprintf(stderr, "%s, %s() use RTLD_DEFAULT\n", | 637 | dprintf(stderr, "%s, %s(): use RTLD_DEFAULT\n", |
| 432 | __FILE__, __FUNCTION__); | 638 | __FILE__, __FUNCTION__); |
| 433 | addr = RTLD_DEFAULT; | 639 | addr = RTLD_DEFAULT; |
| 434 | *(void **) (&malloc_redir) = dlsym (addr, "malloc"); | 640 | *(void **) (&malloc_redir) = dlsym (addr, "malloc"); |
| @@ -437,37 +643,109 @@ void __bound_init(void) · 2 unmodified lines |
| 437 | *(void **) (&free_redir) = dlsym (addr, "free"); | 643 | *(void **) (&free_redir) = dlsym (addr, "free"); |
| 438 | *(void **) (&realloc_redir) = dlsym (addr, "realloc"); | 644 | *(void **) (&realloc_redir) = dlsym (addr, "realloc"); |
| 439 | *(void **) (&memalign_redir) = dlsym (addr, "memalign"); | 645 | *(void **) (&memalign_redir) = dlsym (addr, "memalign"); |
| 440 | dprintf(stderr, "%s, %s() malloc_redir %p\n", | 646 | dprintf(stderr, "%s, %s(): malloc_redir %p\n", |
| 441 | __FILE__, __FUNCTION__, malloc_redir); | 647 | __FILE__, __FUNCTION__, malloc_redir); |
| 442 | dprintf(stderr, "%s, %s() free_redir %p\n", | 648 | dprintf(stderr, "%s, %s(): free_redir %p\n", |
| 443 | __FILE__, __FUNCTION__, free_redir); | 649 | __FILE__, __FUNCTION__, free_redir); |
| 444 | dprintf(stderr, "%s, %s() realloc_redir %p\n", | 650 | dprintf(stderr, "%s, %s(): realloc_redir %p\n", |
| 445 | __FILE__, __FUNCTION__, realloc_redir); | 651 | __FILE__, __FUNCTION__, realloc_redir); |
| 446 | dprintf(stderr, "%s, %s() memalign_redir %p\n", | 652 | dprintf(stderr, "%s, %s(): memalign_redir %p\n", |
| 447 | __FILE__, __FUNCTION__, memalign_redir); | 653 | __FILE__, __FUNCTION__, memalign_redir); |
| | 654 | if (malloc_redir == NULL || free_redir == NULL) |
| | 655 | bound_alloc_error ("Cannot redirect malloc/free"); |
| | 656 | #if HAVE_PTHREAD_CREATE |
| | 657 | *(void **) (&pthread_create_redir) = dlsym (addr, "pthread_create"); |
| | 658 | dprintf(stderr, "%s, %s(): pthread_create_redir %p\n", |
| | 659 | __FILE__, __FUNCTION__, pthread_create_redir); |
| | 660 | #endif |
| 448 | } | 661 | } |
| 449 | #endif | 662 | #endif |
| 450 | | 663 | |
| 451 | tree = NULL; | 664 | #ifdef __linux__ |
| | 665 | { |
| | 666 | FILE *fp; |
| | 667 | unsigned char found; |
| | 668 | unsigned long long start; |
| | 669 | unsigned long long end; |
| | 670 | unsigned long long ad = |
| | 671 | (unsigned long long) __builtin_return_address(0); |
| | 672 | char line[1000]; |
| | 673 | |
| | 674 | /* Display exec name. Usefull when a lot of code is compiled with tcc */ |
| | 675 | fp = fopen ("/proc/self/comm", "r"); |
| | 676 | if (fp) { |
| | 677 | memset (exec, 0, sizeof(exec)); |
| | 678 | fread (exec, 1, sizeof(exec) - 2, fp); |
| | 679 | if (strchr(exec,'\n')) |
| | 680 | *strchr(exec,'\n') = '\0'; |
| | 681 | strcat (exec, ":"); |
| | 682 | fclose (fp); |
| | 683 | } |
| | 684 | /* check if dlopen is used (is threre a better way?) */ |
| | 685 | found = 0; |
| | 686 | fp = fopen ("/proc/self/maps", "r"); |
| | 687 | if (fp) { |
| | 688 | while (fgets (line, sizeof(line), fp)) { |
| | 689 | if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 && |
| | 690 | ad >= start && ad < end) { |
| | 691 | found = 1; |
| | 692 | break; |
| | 693 | } |
| | 694 | if (strstr (line,"[heap]")) |
| | 695 | break; |
| | 696 | } |
| | 697 | fclose (fp); |
| | 698 | } |
| | 699 | if (found == 0) { |
| | 700 | use_sem = 1; |
| | 701 | no_strdup = 1; |
| | 702 | } |
| | 703 | } |
| | 704 | #endif |
| 452 | | 705 | |
| 453 | /* save malloc hooks and install bound check hooks */ | 706 | WAIT_SEM (); |
| 454 | memset (free_reuse_list, 0, sizeof (free_reuse_list)); | | |
| 455 | | 707 | |
| 456 | dprintf(stderr, "%s, %s() end\n\n", __FILE__, __FUNCTION__); | 708 | #if HAVE_CTYPE |
| 457 | } | 709 | /* XXX: Does not work if locale is changed */ |
| | 710 | tree = splay_insert((size_t) __ctype_b_loc(), |
| | 711 | sizeof (unsigned short *), tree); |
| | 712 | tree = splay_insert((size_t) (*__ctype_b_loc() - 128), |
| | 713 | 384 * sizeof (unsigned short), tree); |
| | 714 | tree = splay_insert((size_t) __ctype_tolower_loc(), |
| | 715 | sizeof (__int32_t *), tree); |
| | 716 | tree = splay_insert((size_t) (*__ctype_tolower_loc() - 128), |
| | 717 | 384 * sizeof (__int32_t), tree); |
| | 718 | tree = splay_insert((size_t) __ctype_toupper_loc(), |
| | 719 | sizeof (__int32_t *), tree); |
| | 720 | tree = splay_insert((size_t) (*__ctype_toupper_loc() - 128), |
| | 721 | 384 * sizeof (__int32_t), tree); |
| | 722 | #endif |
| | 723 | #if HAVE_ERRNO |
| | 724 | tree = splay_insert((size_t) (&errno), sizeof (int), tree); |
| | 725 | #endif |
| 458 | | 726 | |
| 459 | void __bounds_add_static_var (size_t *p) | | |
| 460 | { | | |
| 461 | dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__); | | |
| 462 | /* add all static bound check values */ | 727 | /* add all static bound check values */ |
| 463 | WAIT_SEM (); | 728 | p = __bounds_start; |
| 464 | while (p[0] != 0) { | 729 | while (p[0] != 0) { |
| 465 | dprintf(stderr, "%s, %s() (%p 0x%lx)\n", | | |
| 466 | __FILE__, __FUNCTION__, (void *) p[0], (unsigned long) p[1]); | | |
| 467 | tree = splay_insert(p[0], p[1], tree); | 730 | tree = splay_insert(p[0], p[1], tree); |
| 468 | p += 2; | 731 | p += 2; |
| 469 | } | 732 | } |
| 470 | POST_SEM (); | 733 | POST_SEM (); |
| | 734 | #if BOUND_DEBUG |
| | 735 | if (print_calls) { |
| | 736 | p = __bounds_start; |
| | 737 | while (p[0] != 0) { |
| | 738 | dprintf(stderr, "%s, %s(): static var %p 0x%lx\n", |
| | 739 | __FILE__, __FUNCTION__, |
| | 740 | (void *) p[0], (unsigned long) p[1]); |
| | 741 | p += 2; |
| | 742 | } |
| | 743 | } |
| | 744 | #endif |
| | 745 | |
| | 746 | no_checking = 0; |
| | 747 | |
| | 748 | dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__); |
| 471 | } | 749 | } |
| 472 | | 750 | |
| 473 | void __bound_main_arg(char **p) | 751 | void __bound_main_arg(char **p) |
| @@ -476,33 +754,55 @@ void __bound_main_arg(char **p) · 2 unmodified lines |
| 476 | | 754 | |
| 477 | WAIT_SEM (); | 755 | WAIT_SEM (); |
| 478 | while (*p) { | 756 | while (*p) { |
| 479 | dprintf(stderr, "%s, %s() (%p 0x%lx)\n", | | |
| 480 | __FILE__, __FUNCTION__, *p, (unsigned long)(strlen (*p) + 1)); | | |
| 481 | tree = splay_insert((size_t) *p, strlen (*p) + 1, tree); | 757 | tree = splay_insert((size_t) *p, strlen (*p) + 1, tree); |
| 482 | p++; | 758 | ++p; |
| 483 | } | 759 | } |
| 484 | dprintf(stderr, "%s, %s() argv (%p 0x%lx)\n", | | |
| 485 | __FILE__, __FUNCTION__, start, (unsigned long)((char *) p - start)); | | |
| 486 | tree = splay_insert((size_t) start, (char *) p - start, tree); | 760 | tree = splay_insert((size_t) start, (char *) p - start, tree); |
| | 761 | POST_SEM (); |
| | 762 | #if BOUND_DEBUG |
| | 763 | if (print_calls) { |
| | 764 | p = (char **) start; |
| | 765 | while (*p) { |
| | 766 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", |
| | 767 | __FILE__, __FUNCTION__, |
| | 768 | *p, (unsigned long)(strlen (*p) + 1)); |
| | 769 | ++p; |
| | 770 | } |
| | 771 | dprintf(stderr, "%s, %s(): argv %p 0x%lx\n", |
| | 772 | __FILE__, __FUNCTION__, |
| | 773 | start, (unsigned long)((char *) p - start)); |
| | 774 | } |
| | 775 | #endif |
| 487 | | 776 | |
| 488 | #if HAS_ENVIRON | 777 | #if HAS_ENVIRON |
| 489 | { | 778 | { |
| 490 | extern char **environ; | 779 | extern char **environ; |
| 491 | | 780 | |
| | 781 | WAIT_SEM (); |
| 492 | p = environ; | 782 | p = environ; |
| 493 | start = (char *) p; | 783 | start = (char *) p; |
| 494 | while (*p) { | 784 | while (*p) { |
| 495 | dprintf(stderr, "%s, %s() (%p 0x%lx)\n", | | |
| 496 | __FILE__, __FUNCTION__, *p, (unsigned long)(strlen (*p) + 1)); | | |
| 497 | tree = splay_insert((size_t) *p, strlen (*p) + 1, tree); | 785 | tree = splay_insert((size_t) *p, strlen (*p) + 1, tree); |
| 498 | p++; | 786 | ++p; |
| 499 | } | 787 | } |
| 500 | dprintf(stderr, "%s, %s() environ(%p 0x%lx)\n", | | |
| 501 | __FILE__, __FUNCTION__, start, (unsigned long)((char *) p - start)); | | |
| 502 | tree = splay_insert((size_t) start, (char *) p - start, tree); | 788 | tree = splay_insert((size_t) start, (char *) p - start, tree); |
| | 789 | POST_SEM (); |
| | 790 | #if BOUND_DEBUG |
| | 791 | if (print_calls) { |
| | 792 | p = environ; |
| | 793 | while (*p) { |
| | 794 | dprintf(stderr, "%s, %s(): %p 0x%lx\n", |
| | 795 | __FILE__, __FUNCTION__, |
| | 796 | *p, (unsigned long)(strlen (*p) + 1)); |
| | 797 | ++p; |
| | 798 | } |
| | 799 | dprintf(stderr, "%s, %s(): environ %p 0x%lx\n", |
| | 800 | __FILE__, __FUNCTION__, |
| | 801 | start, (unsigned long)((char *) p - start)); |
| | 802 | } |
| | 803 | #endif |
| 503 | } | 804 | } |
| 504 | #endif | 805 | #endif |
| 505 | POST_SEM (); | | |
| 506 | } | 806 | } |
| 507 | | 807 | |
| 508 | void __attribute__((destructor)) __bound_exit(void) | 808 | void __attribute__((destructor)) __bound_exit(void) |
| @@ -512,16 +812,30 @@ void __attribute__((destructor)) __bound_exit(void) · 3 unmodified lines |
| 512 | "", "malloc", "calloc", "realloc", "memalign", "strdup" | 812 | "", "malloc", "calloc", "realloc", "memalign", "strdup" |
| 513 | }; | 813 | }; |
| 514 | | 814 | |
| 515 | dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__); | 815 | dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__); |
| 516 | | 816 | |
| 517 | if (inited) { | 817 | if (inited) { |
| 518 | #if !defined(_WIN32) | 818 | #if !defined(_WIN32) |
| 519 | if (print_heap) { | 819 | if (print_heap) { |
| 520 | extern void __libc_freeres (); | 820 | extern void __libc_freeres (void); |
| 521 | __libc_freeres (); | 821 | __libc_freeres (); |
| 522 | } | 822 | } |
| 523 | #endif | 823 | #endif |
| 524 | | 824 | |
| | 825 | no_checking = 1; |
| | 826 | |
| | 827 | WAIT_SEM (); |
| | 828 | while (alloca_list) { |
| | 829 | alloca_list_type *next = alloca_list->next; |
| | 830 | |
| | 831 | tree = splay_delete ((size_t) alloca_list->p, tree); |
| | 832 | #if MALLOC_REDIR |
| | 833 | free_redir (alloca_list); |
| | 834 | #else |
| | 835 | free (alloca_list); |
| | 836 | #endif |
| | 837 | alloca_list = next; |
| | 838 | } |
| 525 | for (i = 0; i < FREE_REUSE_SIZE; i++) { | 839 | for (i = 0; i < FREE_REUSE_SIZE; i++) { |
| 526 | if (free_reuse_list[i]) { | 840 | if (free_reuse_list[i]) { |
| 527 | tree = splay_delete ((size_t) free_reuse_list[i], tree); | 841 | tree = splay_delete ((size_t) free_reuse_list[i], tree); |
| @@ -533,11 +847,10 @@ void __attribute__((destructor)) __bound_exit(void) · 5 unmodified lines |
| 533 | } | 847 | } |
| 534 | } | 848 | } |
| 535 | while (tree) { | 849 | while (tree) { |
| 536 | if (print_heap && tree->type != 0) { | 850 | if (print_heap && tree->type != 0) |
| 537 | fprintf (stderr, "%s, %s() %s found size %lu\n", | 851 | fprintf (stderr, "%s, %s(): %s found size %lu\n", |
| 538 | __FILE__, __FUNCTION__, alloc_type[tree->type], | 852 | __FILE__, __FUNCTION__, alloc_type[tree->type], |
| 539 | (unsigned long) tree->size); | 853 | (unsigned long) tree->size); |
| 540 | } | | |
| 541 | tree = splay_delete (tree->start, tree); | 854 | tree = splay_delete (tree->start, tree); |
| 542 | } | 855 | } |
| 543 | #if TREE_REUSE | 856 | #if TREE_REUSE |
| @@ -551,10 +864,11 @@ void __attribute__((destructor)) __bound_exit(void) · 7 unmodified lines |
| 551 | tree_free_list = next; | 864 | tree_free_list = next; |
| 552 | } | 865 | } |
| 553 | #endif | 866 | #endif |
| | 867 | POST_SEM (); |
| 554 | EXIT_SEM (); | 868 | EXIT_SEM (); |
| 555 | inited = 0; | 869 | inited = 0; |
| 556 | #ifdef BOUND_STATISTIC | | |
| 557 | if (print_statistic) { | 870 | if (print_statistic) { |
| | 871 | #if BOUND_STATISTIC |
| 558 | fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count); | 872 | fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count); |
| 559 | fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count); | 873 | fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count); |
| 560 | fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count); | 874 | fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count); |
| @@ -584,14 +898,28 @@ void __attribute__((destructor)) __bound_exit(void) · 23 unmodified lines |
| 584 | fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); | 898 | fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); |
| 585 | fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); | 899 | fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); |
| 586 | fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); | 900 | fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); |
| 587 | } | 901 | fprintf (stderr, "bound_not_found %llu\n", bound_not_found); |
| | 902 | #endif |
| | 903 | #if BOUND_STATISTIC_SPLAY |
| | 904 | fprintf (stderr, "bound_splay %llu\n", bound_splay); |
| | 905 | fprintf (stderr, "bound_splay_end %llu\n", bound_splay_end); |
| | 906 | fprintf (stderr, "bound_splay_insert %llu\n", bound_splay_insert); |
| | 907 | fprintf (stderr, "bound_splay_delete %llu\n", bound_splay_delete); |
| 588 | #endif | 908 | #endif |
| | 909 | } |
| 589 | } | 910 | } |
| 590 | } | 911 | } |
| 591 | | 912 | |
| 592 | /* XXX: we should use a malloc which ensure that it is unlikely that | 913 | #if HAVE_PTHREAD_CREATE |
| 593 | two malloc'ed data have the same address if 'free' are made in | 914 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, |
| 594 | between. */ | 915 | void *(*start_routine) (void *), void *arg) |
| | 916 | { |
| | 917 | use_sem = 1; |
| | 918 | dprintf (stderr, "%s, %s()n", __FILE__, __FUNCTION__); |
| | 919 | return pthread_create_redir(thread, attr, start_routine, arg); |
| | 920 | } |
| | 921 | #endif |
| | 922 | |
| 595 | #if MALLOC_REDIR | 923 | #if MALLOC_REDIR |
| 596 | void *malloc(size_t size) | 924 | void *malloc(size_t size) |
| 597 | #else | 925 | #else |
| @@ -603,34 +931,40 @@ void *__bound_malloc(size_t size, const void *caller) · 5 unmodified lines |
| 603 | #if MALLOC_REDIR | 931 | #if MALLOC_REDIR |
| 604 | /* This will catch the first dlsym call from __bound_init */ | 932 | /* This will catch the first dlsym call from __bound_init */ |
| 605 | if (malloc_redir == NULL) { | 933 | if (malloc_redir == NULL) { |
| 606 | ptr = &initial_pool[pool_index]; | 934 | __bound_init (); |
| 607 | pool_index = (pool_index + size + 7) & ~8; | 935 | if (malloc_redir == NULL) { |
| 608 | dprintf (stderr, "%s, %s initial (%p, 0x%x)\n", | 936 | ptr = &initial_pool[pool_index]; |
| 609 | __FILE__, __FUNCTION__, ptr, (unsigned)size); | 937 | pool_index = (pool_index + size + 15) & ~15; |
| 610 | return ptr; | 938 | if (pool_index >= sizeof (initial_pool)) |
| | 939 | bound_alloc_error ("initial memory pool too small"); |
| | 940 | dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n", |
| | 941 | __FILE__, __FUNCTION__, ptr, (unsigned long)size); |
| | 942 | return ptr; |
| | 943 | } |
| 611 | } | 944 | } |
| 612 | #endif | 945 | #endif |
| 613 | /* we allocate one more byte to ensure the regions will be | 946 | /* we allocate one more byte to ensure the regions will be |
| 614 | separated by at least one byte. With the glibc malloc, it may | 947 | separated by at least one byte. With the glibc malloc, it may |
| 615 | be in fact not necessary */ | 948 | be in fact not necessary */ |
| 616 | WAIT_SEM (); | | |
| 617 | INCR_COUNT(bound_malloc_count); | | |
| 618 | #if MALLOC_REDIR | 949 | #if MALLOC_REDIR |
| 619 | ptr = malloc_redir (size); | 950 | ptr = malloc_redir (size + 1); |
| 620 | #else | 951 | #else |
| 621 | ptr = malloc(size + 1); | 952 | ptr = malloc(size + 1); |
| 622 | #endif | 953 | #endif |
| | 954 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| | 955 | __FILE__, __FUNCTION__, ptr, (unsigned long)size); |
| 623 | | 956 | |
| 624 | dprintf(stderr, "%s, %s (%p, 0x%x)\n", | 957 | if (no_checking == 0) { |
| 625 | __FILE__, __FUNCTION__, ptr, (unsigned)size); | 958 | WAIT_SEM (); |
| | 959 | INCR_COUNT(bound_malloc_count); |
| 626 | | 960 | |
| 627 | if (ptr) { | 961 | if (ptr) { |
| 628 | tree = splay_insert ((size_t) ptr, size, tree); | 962 | tree = splay_insert ((size_t) ptr, size, tree); |
| 629 | if (tree && tree->start == (size_t) ptr) { | 963 | if (tree && tree->start == (size_t) ptr) |
| 630 | tree->type = TCC_TYPE_MALLOC; | 964 | tree->type = TCC_TYPE_MALLOC; |
| 631 | } | 965 | } |
| | 966 | POST_SEM (); |
| 632 | } | 967 | } |
| 633 | POST_SEM (); | | |
| 634 | return ptr; | 968 | return ptr; |
| 635 | } | 969 | } |
| 636 | | 970 | |
| @@ -642,10 +976,16 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 5 unmodified lines |
| 642 | { | 976 | { |
| 643 | void *ptr; | 977 | void *ptr; |
| 644 | | 978 | |
| 645 | WAIT_SEM (); | 979 | #if HAVE_MEMALIGN |
| 646 | INCR_COUNT(bound_memalign_count); | 980 | /* we allocate one more byte to ensure the regions will be |
| 647 | | 981 | separated by at least one byte. With the glibc malloc, it may |
| 648 | #ifndef HAVE_MEMALIGN | 982 | be in fact not necessary */ |
| | 983 | #if MALLOC_REDIR |
| | 984 | ptr = memalign_redir(size + 1, align); |
| | 985 | #else |
| | 986 | ptr = memalign(size + 1, align); |
| | 987 | #endif |
| | 988 | #else |
| 649 | if (align > 4) { | 989 | if (align > 4) { |
| 650 | /* XXX: handle it ? */ | 990 | /* XXX: handle it ? */ |
| 651 | ptr = NULL; | 991 | ptr = NULL; |
| @@ -657,25 +997,21 @@ void *__bound_memalign(size_t size, size_t align, const void *caller) · 5 unmodified lines |
| 657 | ptr = malloc(size + 1); | 997 | ptr = malloc(size + 1); |
| 658 | #endif | 998 | #endif |
| 659 | } | 999 | } |
| 660 | #else | | |
| 661 | /* we allocate one more byte to ensure the regions will be | | |
| 662 | separated by at least one byte. With the glibc malloc, it may | | |
| 663 | be in fact not necessary */ | | |
| 664 | #if MALLOC_REDIR | | |
| 665 | ptr = memalign_redir(size + 1, align); | | |
| 666 | #else | | |
| 667 | ptr = memalign(size + 1, align); | | |
| 668 | #endif | | |
| 669 | #endif | 1000 | #endif |
| 670 | if (ptr) { | 1001 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| 671 | dprintf(stderr, "%s, %s (%p, 0x%x)\n", | 1002 | __FILE__, __FUNCTION__, ptr, (unsigned long)size); |
| 672 | __FILE__, __FUNCTION__, ptr, (unsigned)size); | 1003 | |
| 673 | tree = splay_insert((size_t) ptr, size, tree); | 1004 | if (no_checking == 0) { |
| 674 | if (tree && tree->start == (size_t) ptr) { | 1005 | WAIT_SEM (); |
| 675 | tree->type = TCC_TYPE_MEMALIGN; | 1006 | INCR_COUNT(bound_memalign_count); |
| | 1007 | |
| | 1008 | if (ptr) { |
| | 1009 | tree = splay_insert((size_t) ptr, size, tree); |
| | 1010 | if (tree && tree->start == (size_t) ptr) |
| | 1011 | tree->type = TCC_TYPE_MEMALIGN; |
| 676 | } | 1012 | } |
| | 1013 | POST_SEM (); |
| 677 | } | 1014 | } |
| 678 | POST_SEM (); | | |
| 679 | return ptr; | 1015 | return ptr; |
| 680 | } | 1016 | } |
| 681 | | 1017 | |
| @@ -688,7 +1024,7 @@ void __bound_free(void *ptr, const void *caller) · 6 unmodified lines |
| 688 | size_t addr = (size_t) ptr; | 1024 | size_t addr = (size_t) ptr; |
| 689 | void *p; | 1025 | void *p; |
| 690 | | 1026 | |
| 691 | if (ptr == NULL || tree == NULL | 1027 | if (ptr == NULL || tree == NULL || no_checking |
| 692 | #if MALLOC_REDIR | 1028 | #if MALLOC_REDIR |
| 693 | || ((unsigned char *) ptr >= &initial_pool[0] && | 1029 | || ((unsigned char *) ptr >= &initial_pool[0] && |
| 694 | (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)]) | 1030 | (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)]) |
| @@ -696,15 +1032,15 @@ void __bound_free(void *ptr, const void *caller) · 1 unmodified line |
| 696 | ) | 1032 | ) |
| 697 | return; | 1033 | return; |
| 698 | | 1034 | |
| 699 | dprintf(stderr, "%s, %s (%p)\n", __FILE__, __FUNCTION__, ptr); | 1035 | dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr); |
| 700 | | 1036 | |
| 701 | WAIT_SEM (); | 1037 | WAIT_SEM (); |
| 702 | INCR_COUNT(bound_free_count); | 1038 | INCR_COUNT(bound_free_count); |
| 703 | tree = splay (addr, tree); | 1039 | tree = splay (addr, tree); |
| 704 | if (tree->start == addr) { | 1040 | if (tree->start == addr) { |
| 705 | if (tree->is_invalid) { | 1041 | if (tree->is_invalid) { |
| 706 | bound_error("freeing invalid region"); | | |
| 707 | POST_SEM (); | 1042 | POST_SEM (); |
| | 1043 | bound_error("freeing invalid region"); |
| 708 | return; | 1044 | return; |
| 709 | } | 1045 | } |
| 710 | tree->is_invalid = 1; | 1046 | tree->is_invalid = 1; |
| @@ -712,17 +1048,16 @@ void __bound_free(void *ptr, const void *caller) · 1 unmodified line |
| 712 | p = free_reuse_list[free_reuse_index]; | 1048 | p = free_reuse_list[free_reuse_index]; |
| 713 | free_reuse_list[free_reuse_index] = ptr; | 1049 | free_reuse_list[free_reuse_index] = ptr; |
| 714 | free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE; | 1050 | free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE; |
| 715 | if (p) { | 1051 | if (p) |
| 716 | tree = splay_delete((size_t)p, tree); | 1052 | tree = splay_delete((size_t)p, tree); |
| 717 | } | | |
| 718 | ptr = p; | 1053 | ptr = p; |
| 719 | } | 1054 | } |
| | 1055 | POST_SEM (); |
| 720 | #if MALLOC_REDIR | 1056 | #if MALLOC_REDIR |
| 721 | free_redir (ptr); | 1057 | free_redir (ptr); |
| 722 | #else | 1058 | #else |
| 723 | free(ptr); | 1059 | free(ptr); |
| 724 | #endif | 1060 | #endif |
| 725 | POST_SEM (); | | |
| 726 | } | 1061 | } |
| 727 | | 1062 | |
| 728 | #if MALLOC_REDIR | 1063 | #if MALLOC_REDIR |
| @@ -731,6 +1066,8 @@ void *realloc(void *ptr, size_t size) · 2 unmodified lines |
| 731 | void *__bound_realloc(void *ptr, size_t size, const void *caller) | 1066 | void *__bound_realloc(void *ptr, size_t size, const void *caller) |
| 732 | #endif | 1067 | #endif |
| 733 | { | 1068 | { |
| | 1069 | void *new_ptr; |
| | 1070 | |
| 734 | if (size == 0) { | 1071 | if (size == 0) { |
| 735 | #if MALLOC_REDIR | 1072 | #if MALLOC_REDIR |
| 736 | free(ptr); | 1073 | free(ptr); |
| @@ -739,40 +1076,29 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller) · 2 unmodified lines |
| 739 | #endif | 1076 | #endif |
| 740 | return NULL; | 1077 | return NULL; |
| 741 | } | 1078 | } |
| 742 | else if (ptr == NULL) { | 1079 | |
| 743 | #if MALLOC_REDIR | 1080 | #if MALLOC_REDIR |
| 744 | ptr = realloc_redir (ptr, size); | 1081 | new_ptr = realloc_redir (ptr, size); |
| 745 | #else | 1082 | #else |
| 746 | ptr = realloc (ptr, size); | 1083 | new_ptr = realloc (ptr, size); |
| 747 | #endif | 1084 | #endif |
| | 1085 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| | 1086 | __FILE__, __FUNCTION__, new_ptr, (unsigned long)size); |
| | 1087 | |
| | 1088 | if (no_checking == 0) { |
| 748 | WAIT_SEM (); | 1089 | WAIT_SEM (); |
| 749 | INCR_COUNT(bound_realloc_count); | 1090 | INCR_COUNT(bound_realloc_count); |
| 750 | if (ptr) { | 1091 | |
| 751 | tree = splay_insert ((size_t) ptr, size, tree); | 1092 | if (ptr) |
| 752 | if (tree && tree->start == (size_t) ptr) { | 1093 | tree = splay_delete ((size_t) ptr, tree); |
| 753 | tree->type = TCC_TYPE_REALLOC; | 1094 | if (new_ptr) { |
| 754 | } | 1095 | tree = splay_insert ((size_t) new_ptr, size, tree); |
| 755 | } | 1096 | if (tree && tree->start == (size_t) new_ptr) |
| 756 | POST_SEM (); | | |
| 757 | return ptr; | | |
| 758 | } | | |
| 759 | else { | | |
| 760 | WAIT_SEM (); | | |
| 761 | tree = splay_delete ((size_t) ptr, tree); | | |
| 762 | #if MALLOC_REDIR | | |
| 763 | ptr = realloc_redir (ptr, size); | | |
| 764 | #else | | |
| 765 | ptr = realloc (ptr, size); | | |
| 766 | #endif | | |
| 767 | if (ptr) { | | |
| 768 | tree = splay_insert ((size_t) ptr, size, tree); | | |
| 769 | if (tree && tree->start == (size_t) ptr) { | | |
| 770 | tree->type = TCC_TYPE_REALLOC; | 1097 | tree->type = TCC_TYPE_REALLOC; |
| 771 | } | | |
| 772 | } | 1098 | } |
| 773 | POST_SEM (); | 1099 | POST_SEM (); |
| 774 | return ptr; | | |
| 775 | } | 1100 | } |
| | 1101 | return new_ptr; |
| 776 | } | 1102 | } |
| 777 | | 1103 | |
| 778 | #if MALLOC_REDIR | 1104 | #if MALLOC_REDIR |
| @@ -787,12 +1113,17 @@ void *__bound_calloc(size_t nmemb, size_t size) · 8 unmodified lines |
| 787 | #if MALLOC_REDIR | 1113 | #if MALLOC_REDIR |
| 788 | /* This will catch the first dlsym call from __bound_init */ | 1114 | /* This will catch the first dlsym call from __bound_init */ |
| 789 | if (malloc_redir == NULL) { | 1115 | if (malloc_redir == NULL) { |
| 790 | ptr = &initial_pool[pool_index]; | 1116 | __bound_init (); |
| 791 | pool_index = (pool_index + size + 7) & ~8; | 1117 | if (malloc_redir == NULL) { |
| 792 | dprintf (stderr, "%s, %s initial (%p, 0x%x)\n", | 1118 | ptr = &initial_pool[pool_index]; |
| 793 | __FILE__, __FUNCTION__, ptr, (unsigned)size); | 1119 | pool_index = (pool_index + size + 15) & ~15; |
| 794 | memset (ptr, 0, size); | 1120 | if (pool_index >= sizeof (initial_pool)) |
| 795 | return ptr; | 1121 | bound_alloc_error ("initial memory pool too small"); |
| | 1122 | dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n", |
| | 1123 | __FILE__, __FUNCTION__, ptr, (unsigned long)size); |
| | 1124 | memset (ptr, 0, size); |
| | 1125 | return ptr; |
| | 1126 | } |
| 796 | } | 1127 | } |
| 797 | #endif | 1128 | #endif |
| 798 | #if MALLOC_REDIR | 1129 | #if MALLOC_REDIR |
| @@ -800,15 +1131,19 @@ void *__bound_calloc(size_t nmemb, size_t size) · 1 unmodified line |
| 800 | #else | 1131 | #else |
| 801 | ptr = malloc(size + 1); | 1132 | ptr = malloc(size + 1); |
| 802 | #endif | 1133 | #endif |
| | 1134 | dprintf (stderr, "%s, %s(): %p, 0x%lx\n", |
| | 1135 | __FILE__, __FUNCTION__, ptr, (unsigned long)size); |
| | 1136 | |
| 803 | if (ptr) { | 1137 | if (ptr) { |
| 804 | memset (ptr, 0, size); | 1138 | memset (ptr, 0, size); |
| 805 | WAIT_SEM (); | 1139 | if (no_checking == 0) { |
| 806 | INCR_COUNT(bound_calloc_count); | 1140 | WAIT_SEM (); |
| 807 | tree = splay_insert ((size_t) ptr, size, tree); | 1141 | INCR_COUNT(bound_calloc_count); |
| 808 | if (tree && tree->start == (size_t) ptr) { | 1142 | tree = splay_insert ((size_t) ptr, size, tree); |
| 809 | tree->type = TCC_TYPE_CALLOC; | 1143 | if (tree && tree->start == (size_t) ptr) |
| | 1144 | tree->type = TCC_TYPE_CALLOC; |
| | 1145 | POST_SEM (); |
| 810 | } | 1146 | } |
| 811 | POST_SEM (); | | |
| 812 | } | 1147 | } |
| 813 | return ptr; | 1148 | return ptr; |
| 814 | } | 1149 | } |
| @@ -819,10 +1154,10 @@ void *__bound_mmap (void *start, size_t size, int prot, · 4 unmodified lines |
| 819 | { | 1154 | { |
| 820 | void *result; | 1155 | void *result; |
| 821 | | 1156 | |
| 822 | dprintf(stderr, "%s, %s (%p, 0x%x)\n", | 1157 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| 823 | __FILE__, __FUNCTION__, start, (unsigned)size); | 1158 | __FILE__, __FUNCTION__, start, (unsigned long)size); |
| 824 | result = mmap (start, size, prot, flags, fd, offset); | 1159 | result = mmap (start, size, prot, flags, fd, offset); |
| 825 | if (result) { | 1160 | if (result && no_checking == 0) { |
| 826 | WAIT_SEM (); | 1161 | WAIT_SEM (); |
| 827 | INCR_COUNT(bound_mmap_count); | 1162 | INCR_COUNT(bound_mmap_count); |
| 828 | tree = splay_insert((size_t)result, size, tree); | 1163 | tree = splay_insert((size_t)result, size, tree); |
| @@ -835,161 +1170,151 @@ int __bound_munmap (void *start, size_t size) · 6 unmodified lines |
| 835 | { | 1170 | { |
| 836 | int result; | 1171 | int result; |
| 837 | | 1172 | |
| 838 | dprintf(stderr, "%s, %s (%p, 0x%x)\n", | 1173 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| 839 | __FILE__, __FUNCTION__, start, (unsigned)size); | 1174 | __FILE__, __FUNCTION__, start, (unsigned long)size); |
| 840 | WAIT_SEM (); | 1175 | if (start && no_checking == 0) { |
| 841 | INCR_COUNT(bound_munmap_count); | 1176 | WAIT_SEM (); |
| 842 | tree = splay_delete ((size_t) start, tree); | 1177 | INCR_COUNT(bound_munmap_count); |
| 843 | POST_SEM (); | 1178 | tree = splay_delete ((size_t) start, tree); |
| | 1179 | POST_SEM (); |
| | 1180 | } |
| 844 | result = munmap (start, size); | 1181 | result = munmap (start, size); |
| 845 | return result; | 1182 | return result; |
| 846 | } | 1183 | } |
| 847 | #endif | 1184 | #endif |
| 848 | | 1185 | |
| 849 | /* used by alloca */ | | |
| 850 | void __bound_new_region(void *p, size_t size) | | |
| 851 | { | | |
| 852 | size_t fp; | | |
| 853 | alloca_list_type *last; | | |
| 854 | alloca_list_type *cur; | | |
| 855 | | | |
| 856 | dprintf(stderr, "%s, %s (%p, 0x%x)\n", | | |
| 857 | __FILE__, __FUNCTION__, p, (unsigned)size); | | |
| 858 | WAIT_SEM (); | | |
| 859 | INCR_COUNT(bound_alloca_count); | | |
| 860 | GET_CALLER_FP (fp); | | |
| 861 | last = NULL; | | |
| 862 | cur = alloca_list; | | |
| 863 | while (cur && cur->fp == fp) { | | |
| 864 | if (cur->p == p) { | | |
| 865 | dprintf(stderr, "%s, %s() remove alloca/vla %p\n", | | |
| 866 | __FILE__, __FUNCTION__, alloca_list->p); | | |
| 867 | if (last) { | | |
| 868 | last->next = cur->next; | | |
| 869 | } | | |
| 870 | else { | | |
| 871 | alloca_list = cur->next; | | |
| 872 | } | | |
| 873 | tree = splay_delete((size_t)p, tree); | | |
| 874 | #if MALLOC_REDIR | | |
| 875 | free_redir (cur); | | |
| 876 | #else | | |
| 877 | free (cur); | | |
| 878 | #endif | | |
| 879 | break; | | |
| 880 | } | | |
| 881 | last = cur; | | |
| 882 | cur = cur->next; | | |
| 883 | } | | |
| 884 | tree = splay_insert((size_t)p, size, tree); | | |
| 885 | #if MALLOC_REDIR | | |
| 886 | cur = malloc_redir (sizeof (alloca_list_type)); | | |
| 887 | #else | | |
| 888 | cur = malloc (sizeof (alloca_list_type)); | | |
| 889 | #endif | | |
| 890 | if (cur) { | | |
| 891 | cur->fp = fp; | | |
| 892 | cur->p = p; | | |
| 893 | cur->next = alloca_list; | | |
| 894 | alloca_list = cur; | | |
| 895 | } | | |
| 896 | POST_SEM (); | | |
| 897 | } | | |
| 898 | | | |
| 899 | #if defined(__GNUC__) && (__GNUC__ >= 6) | | |
| 900 | #pragma GCC diagnostic pop | | |
| 901 | #endif | | |
| 902 | | | |
| 903 | | | |
| 904 | /* some useful checked functions */ | 1186 | /* some useful checked functions */ |
| 905 | | 1187 | |
| 906 | /* check that (p ... p + size - 1) lies inside 'p' region, if any */ | 1188 | /* check that (p ... p + size - 1) lies inside 'p' region, if any */ |
| 907 | static void __bound_check(const void *p, size_t size, const char *function) | 1189 | static void __bound_check(const void *p, size_t size, const char *function) |
| 908 | { | 1190 | { |
| 909 | if (no_checking) | 1191 | if (no_checking == 0 && size != 0 && |
| 910 | return; | 1192 | __bound_ptr_add((void *)p, size) == INVALID_POINTER) { |
| 911 | if (size == 0) | 1193 | static char line[100]; |
| 912 | return; | 1194 | sprintf(line, "invalid pointer %p, size 0x%lx in %s", |
| 913 | p = __bound_ptr_add((void *)p, size); | 1195 | p, (unsigned long)size, function); |
| 914 | if (p == INVALID_POINTER) | 1196 | bound_error(line); |
| 915 | bound_error("invalid pointer"); | 1197 | } |
| 916 | } | 1198 | } |
| 917 | | 1199 | |
| 918 | void *__bound_memcpy(void *dst, const void *src, size_t size) | 1200 | static int check_overlap (const void *p1, size_t n1, |
| | 1201 | const void *p2, size_t n2, |
| | 1202 | const char *function) |
| 919 | { | 1203 | { |
| 920 | void* p; | 1204 | const void *p1e = (const void *) ((const char *) p1 + n1); |
| | 1205 | const void *p2e = (const void *) ((const char *) p2 + n2); |
| | 1206 | |
| | 1207 | if (no_checking == 0 && n1 != 0 && n2 !=0 && |
| | 1208 | ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */ |
| | 1209 | (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */ |
| | 1210 | static char line[100]; |
| | 1211 | sprintf(line, "overlapping regions %p(0x%lx), %p(0x%lx) in %s", |
| | 1212 | p1, (unsigned long)n1, p2, (unsigned long)n2, function); |
| | 1213 | bound_error(line); |
| | 1214 | return never_fatal < 0; |
| | 1215 | } |
| | 1216 | return 0; |
| | 1217 | } |
| 921 | | 1218 | |
| | 1219 | void *__bound_memcpy(void *dest, const void *src, size_t n) |
| | 1220 | { |
| | 1221 | dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", |
| | 1222 | __FILE__, __FUNCTION__, dest, src, (unsigned long)n); |
| 922 | INCR_COUNT(bound_mempcy_count); | 1223 | INCR_COUNT(bound_mempcy_count); |
| 923 | __bound_check(dst, size, "memcpy"); | 1224 | __bound_check(dest, n, "memcpy dest"); |
| 924 | __bound_check(src, size, "memcpy"); | 1225 | __bound_check(src, n, "memcpy src"); |
| 925 | /* check also region overlap */ | 1226 | if (check_overlap(dest, n, src, n, "memcpy")) |
| 926 | if (no_checking == 0 && src >= dst && src < dst + size) | 1227 | return dest; |
| 927 | bound_error("overlapping regions in memcpy()"); | 1228 | return memcpy(dest, src, n); |
| 928 | | | |
| 929 | p = memcpy(dst, src, size); | | |
| 930 | | | |
| 931 | return p; | | |
| 932 | } | 1229 | } |
| 933 | | 1230 | |
| 934 | int __bound_memcmp(const void *s1, const void *s2, size_t size) | 1231 | int __bound_memcmp(const void *s1, const void *s2, size_t n) |
| 935 | { | 1232 | { |
| | 1233 | const unsigned char *u1 = (const unsigned char *) s1; |
| | 1234 | const unsigned char *u2 = (const unsigned char *) s2; |
| | 1235 | int retval = 0; |
| | 1236 | |
| | 1237 | dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", |
| | 1238 | __FILE__, __FUNCTION__, s1, s2, (unsigned long)n); |
| 936 | INCR_COUNT(bound_memcmp_count); | 1239 | INCR_COUNT(bound_memcmp_count); |
| 937 | __bound_check(s1, size, "memcmp"); | 1240 | for (;;) { |
| 938 | __bound_check(s2, size, "memcmp"); | 1241 | if ((ssize_t) --n == -1) |
| 939 | return memcmp(s1, s2, size); | 1242 | break; |
| | 1243 | else if (*u1 != *u2) { |
| | 1244 | retval = *u1++ - *u2++; |
| | 1245 | break; |
| | 1246 | } |
| | 1247 | ++u1; |
| | 1248 | ++u2; |
| | 1249 | } |
| | 1250 | __bound_check(s1, (const void *)u1 - s1, "memcmp s1"); |
| | 1251 | __bound_check(s2, (const void *)u2 - s2, "memcmp s2"); |
| | 1252 | return retval; |
| 940 | } | 1253 | } |
| 941 | | 1254 | |
| 942 | void *__bound_memmove(void *dst, const void *src, size_t size) | 1255 | void *__bound_memmove(void *dest, const void *src, size_t n) |
| 943 | { | 1256 | { |
| | 1257 | dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", |
| | 1258 | __FILE__, __FUNCTION__, dest, src, (unsigned long)n); |
| 944 | INCR_COUNT(bound_memmove_count); | 1259 | INCR_COUNT(bound_memmove_count); |
| 945 | __bound_check(dst, size, "memmove"); | 1260 | __bound_check(dest, n, "memmove dest"); |
| 946 | __bound_check(src, size, "memmove"); | 1261 | __bound_check(src, n, "memmove src"); |
| 947 | return memmove(dst, src, size); | 1262 | return memmove(dest, src, n); |
| 948 | } | 1263 | } |
| 949 | | 1264 | |
| 950 | void *__bound_memset(void *dst, int c, size_t size) | 1265 | void *__bound_memset(void *s, int c, size_t n) |
| 951 | { | 1266 | { |
| | 1267 | dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n", |
| | 1268 | __FILE__, __FUNCTION__, s, c, (unsigned long)n); |
| 952 | INCR_COUNT(bound_memset_count); | 1269 | INCR_COUNT(bound_memset_count); |
| 953 | __bound_check(dst, size, "memset"); | 1270 | __bound_check(s, n, "memset"); |
| 954 | return memset(dst, c, size); | 1271 | return memset(s, c, n); |
| 955 | } | 1272 | } |
| 956 | | 1273 | |
| 957 | int __bound_strlen(const char *s) | 1274 | int __bound_strlen(const char *s) |
| 958 | { | 1275 | { |
| 959 | const char *p = s; | 1276 | const char *p = s; |
| 960 | size_t len; | | |
| 961 | | 1277 | |
| | 1278 | dprintf(stderr, "%s, %s(): %p\n", |
| | 1279 | __FILE__, __FUNCTION__, s); |
| 962 | INCR_COUNT(bound_strlen_count); | 1280 | INCR_COUNT(bound_strlen_count); |
| 963 | while (*p++); | 1281 | while (*p++); |
| 964 | len = (p - s) - 1; | 1282 | __bound_check(s, p - s, "strlen"); |
| 965 | p = __bound_ptr_indir1((char *)s, len); | 1283 | return (p - s) - 1; |
| 966 | if (p == INVALID_POINTER) | | |
| 967 | bound_error("bad pointer in strlen()"); | | |
| 968 | return len; | | |
| 969 | } | 1284 | } |
| 970 | | 1285 | |
| 971 | char *__bound_strcpy(char *dst, const char *src) | 1286 | char *__bound_strcpy(char *dest, const char *src) |
| 972 | { | 1287 | { |
| 973 | size_t len; | 1288 | size_t len; |
| 974 | void *p; | 1289 | const char *p = src; |
| 975 | | 1290 | |
| | 1291 | dprintf(stderr, "%s, %s(): %p, %p\n", |
| | 1292 | __FILE__, __FUNCTION__, dest, src); |
| 976 | INCR_COUNT(bound_strcpy_count); | 1293 | INCR_COUNT(bound_strcpy_count); |
| 977 | len = __bound_strlen(src); | 1294 | while (*p++); |
| 978 | p = __bound_memcpy(dst, src, len + 1); | 1295 | len = p - src; |
| 979 | return p; | 1296 | __bound_check(dest, len, "strcpy dest"); |
| | 1297 | __bound_check(src, len, "strcpy src"); |
| | 1298 | if (check_overlap(dest, len, src, len, "strcpy")) |
| | 1299 | return dest; |
| | 1300 | return strcpy (dest, src); |
| 980 | } | 1301 | } |
| 981 | | 1302 | |
| 982 | char *__bound_strncpy(char *dst, const char *src, size_t n) | 1303 | char *__bound_strncpy(char *dest, const char *src, size_t n) |
| 983 | { | 1304 | { |
| 984 | size_t len = n; | 1305 | size_t len = n; |
| 985 | const char *p = src; | 1306 | const char *p = src; |
| 986 | | 1307 | |
| | 1308 | dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", |
| | 1309 | __FILE__, __FUNCTION__, dest, src, (unsigned long)n); |
| | 1310 | INCR_COUNT(bound_strncpy_count); |
| 987 | while (len-- && *p++); | 1311 | while (len-- && *p++); |
| 988 | len = p - src; | 1312 | len = p - src; |
| 989 | INCR_COUNT(bound_strncpy_count); | 1313 | __bound_check(dest, len, "strncpy dest"); |
| 990 | __bound_check(dst, len, "strncpy"); | 1314 | __bound_check(src, len, "strncpy src"); |
| 991 | __bound_check(src, len, "strncpy"); | 1315 | if (check_overlap(dest, len, src, len, "strncpy")) |
| 992 | return strncpy (dst, src, n); | 1316 | return dest; |
| | 1317 | return strncpy(dest, src, n); |
| 993 | } | 1318 | } |
| 994 | | 1319 | |
| 995 | int __bound_strcmp(const char *s1, const char *s2) | 1320 | int __bound_strcmp(const char *s1, const char *s2) |
| @@ -997,14 +1322,16 @@ int __bound_strcmp(const char *s1, const char *s2) · 1 unmodified line |
| 997 | const unsigned char *u1 = (const unsigned char *) s1; | 1322 | const unsigned char *u1 = (const unsigned char *) s1; |
| 998 | const unsigned char *u2 = (const unsigned char *) s2; | 1323 | const unsigned char *u2 = (const unsigned char *) s2; |
| 999 | | 1324 | |
| | 1325 | dprintf(stderr, "%s, %s(): %p, %p\n", |
| | 1326 | __FILE__, __FUNCTION__, s1, s2); |
| 1000 | INCR_COUNT(bound_strcmp_count); | 1327 | INCR_COUNT(bound_strcmp_count); |
| 1001 | while (*u1 && *u1 == *u2) { | 1328 | while (*u1 && *u1 == *u2) { |
| 1002 | u1++; | 1329 | ++u1; |
| 1003 | u2++; | 1330 | ++u2; |
| 1004 | } | 1331 | } |
| 1005 | __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp"); | 1332 | __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp s1"); |
| 1006 | __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp"); | 1333 | __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp s2"); |
| 1007 | return (*u1 - *u2); | 1334 | return *u1 - *u2; |
| 1008 | } | 1335 | } |
| 1009 | | 1336 | |
| 1010 | int __bound_strncmp(const char *s1, const char *s2, size_t n) | 1337 | int __bound_strncmp(const char *s1, const char *s2, size_t n) |
| @@ -1013,18 +1340,20 @@ int __bound_strncmp(const char *s1, const char *s2, size_t n) · 2 unmodified lines |
| 1013 | const unsigned char *u2 = (const unsigned char *) s2; | 1340 | const unsigned char *u2 = (const unsigned char *) s2; |
| 1014 | int retval = 0; | 1341 | int retval = 0; |
| 1015 | | 1342 | |
| | 1343 | dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", |
| | 1344 | __FILE__, __FUNCTION__, s1, s2, (unsigned long)n); |
| 1016 | INCR_COUNT(bound_strncmp_count); | 1345 | INCR_COUNT(bound_strncmp_count); |
| 1017 | do { | 1346 | do { |
| 1018 | if ((ssize_t) --n == -1) | 1347 | if ((ssize_t) --n == -1) |
| 1019 | break; | 1348 | break; |
| 1020 | else if (*u1 != *u2) { | 1349 | else if (*u1 != *u2) { |
| 1021 | retval = *u1 - *u2; | 1350 | retval = *u1++ - *u2++; |
| 1022 | break; | 1351 | break; |
| 1023 | } | 1352 | } |
| 1024 | u2++; | 1353 | ++u2; |
| 1025 | } while (*u1++); | 1354 | } while (*u1++); |
| 1026 | __bound_check(s1, ((const char *)u1 - s1) + 1, "strncmp"); | 1355 | __bound_check(s1, (const char *)u1 - s1, "strncmp s1"); |
| 1027 | __bound_check(s2, ((const char *)u1 - s1) + 1, "strncmp"); | 1356 | __bound_check(s2, (const char *)u2 - s2, "strncmp s2"); |
| 1028 | return retval; | 1357 | return retval; |
| 1029 | } | 1358 | } |
| 1030 | | 1359 | |
| @@ -1033,29 +1362,33 @@ char *__bound_strcat(char *dest, const char *src) · 2 unmodified lines |
| 1033 | char *r = dest; | 1362 | char *r = dest; |
| 1034 | const char *s = src; | 1363 | const char *s = src; |
| 1035 | | 1364 | |
| | 1365 | dprintf(stderr, "%s, %s(): %p, %p\n", |
| | 1366 | __FILE__, __FUNCTION__, dest, src); |
| 1036 | INCR_COUNT(bound_strcat_count); | 1367 | INCR_COUNT(bound_strcat_count); |
| 1037 | while (*dest++); | 1368 | while (*dest++); |
| 1038 | dest--; | 1369 | while (*src++); |
| 1039 | while ((*dest++ = *src++) != 0); | 1370 | __bound_check(r, (dest - r) + (src - s) - 1, "strcat dest"); |
| 1040 | __bound_check(r, dest - r, "strcat"); | 1371 | __bound_check(s, src - s, "strcat src"); |
| 1041 | __bound_check(s, src - s, "strcat"); | 1372 | if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strcat")) |
| 1042 | return r; | 1373 | return dest; |
| | 1374 | return strcat(r, s); |
| 1043 | } | 1375 | } |
| 1044 | | 1376 | |
| 1045 | char *__bound_strchr(const char *string, int ch) | 1377 | char *__bound_strchr(const char *s, int c) |
| 1046 | { | 1378 | { |
| 1047 | const unsigned char *s = (const unsigned char *) string; | 1379 | const unsigned char *str = (const unsigned char *) s; |
| 1048 | unsigned char c = ch; | 1380 | unsigned char ch = c; |
| 1049 | | 1381 | |
| | 1382 | dprintf(stderr, "%s, %s(): %p, %d\n", |
| | 1383 | __FILE__, __FUNCTION__, s, ch); |
| 1050 | INCR_COUNT(bound_strchr_count); | 1384 | INCR_COUNT(bound_strchr_count); |
| 1051 | while (*s) { | 1385 | while (*str) { |
| 1052 | if (*s == c) { | 1386 | if (*str == ch) |
| 1053 | break; | 1387 | break; |
| 1054 | } | 1388 | ++str; |
| 1055 | s++; | | |
| 1056 | } | 1389 | } |
| 1057 | __bound_check(string, ((const char *)s - string) + 1, "strchr"); | 1390 | __bound_check(s, ((const char *)str - s) + 1, "strchr"); |
| 1058 | return *s == c ? (char *) s : NULL; | 1391 | return *str == ch ? (char *) str : NULL; |
| 1059 | } | 1392 | } |
| 1060 | | 1393 | |
| 1061 | char *__bound_strdup(const char *s) | 1394 | char *__bound_strdup(const char *s) |
| @@ -1067,18 +1400,21 @@ char *__bound_strdup(const char *s) · 5 unmodified lines |
| 1067 | while (*p++); | 1400 | while (*p++); |
| 1068 | __bound_check(s, p - s, "strdup"); | 1401 | __bound_check(s, p - s, "strdup"); |
| 1069 | #if MALLOC_REDIR | 1402 | #if MALLOC_REDIR |
| 1070 | new = malloc_redir (p - s); | 1403 | new = malloc_redir ((p - s) + 1); |
| 1071 | #else | 1404 | #else |
| 1072 | new = malloc (p - s); | 1405 | new = malloc ((p - s) + 1); |
| 1073 | #endif | 1406 | #endif |
| | 1407 | dprintf(stderr, "%s, %s(): %p, 0x%lx\n", |
| | 1408 | __FILE__, __FUNCTION__, new, (unsigned long)(p -s)); |
| 1074 | if (new) { | 1409 | if (new) { |
| 1075 | WAIT_SEM (); | 1410 | if (no_checking == 0 && no_strdup == 0) { |
| 1076 | tree = splay_insert((size_t)new, p - s, tree); | 1411 | WAIT_SEM (); |
| 1077 | if (tree && tree->start == (size_t) new) { | 1412 | tree = splay_insert((size_t)new, p - s, tree); |
| 1078 | tree->type = TCC_TYPE_STRDUP; | 1413 | if (tree && tree->start == (size_t) new) |
| | 1414 | tree->type = TCC_TYPE_STRDUP; |
| | 1415 | POST_SEM (); |
| 1079 | } | 1416 | } |
| 1080 | memcpy (new, s, p - s); | 1417 | memcpy (new, s, p - s); |
| 1081 | POST_SEM (); | | |
| 1082 | } | 1418 | } |
| 1083 | return new; | 1419 | return new; |
| 1084 | } | 1420 | } |
| @@ -1136,16 +1472,14 @@ char *__bound_strdup(const char *s) · 51 unmodified lines |
| 1136 | #define compare(start,tstart,tsize) (start < tstart ? -1 : \ | 1472 | #define compare(start,tstart,tsize) (start < tstart ? -1 : \ |
| 1137 | start >= tstart+tsize ? 1 : 0) | 1473 | start >= tstart+tsize ? 1 : 0) |
| 1138 | | 1474 | |
| 1139 | /* This is the comparison. */ | | |
| 1140 | /* Returns <0 if i<j, =0 if i=j, and >0 if i>j */ | | |
| 1141 | | | |
| 1142 | static Tree * splay (size_t addr, Tree *t) | 1475 | static Tree * splay (size_t addr, Tree *t) |
| 1143 | /* Splay using the key start (which may or may not be in the tree.) */ | 1476 | /* Splay using the key start (which may or may not be in the tree.) */ |
| 1144 | /* The starting root is t, and the tree used is defined by rat */ | 1477 | /* The starting root is t, and the tree used is defined by rat */ |
| 1145 | { | 1478 | { |
| 1146 | Tree N, *l, *r, *y; | 1479 | Tree N, *l, *r, *y; |
| 1147 | int comp; | 1480 | int comp; |
| 1148 | | 1481 | |
| | 1482 | INCR_COUNT_SPLAY(bound_splay); |
| 1149 | if (t == NULL) return t; | 1483 | if (t == NULL) return t; |
| 1150 | N.left = N.right = NULL; | 1484 | N.left = N.right = NULL; |
| 1151 | l = r = &N; | 1485 | l = r = &N; |
| @@ -1198,6 +1532,7 @@ static Tree * splay_end (size_t addr, Tree *t) · 46 unmodified lines |
| 1198 | Tree N, *l, *r, *y; | 1532 | Tree N, *l, *r, *y; |
| 1199 | int comp; | 1533 | int comp; |
| 1200 | | 1534 | |
| | 1535 | INCR_COUNT_SPLAY(bound_splay_end); |
| 1201 | if (t == NULL) return t; | 1536 | if (t == NULL) return t; |
| 1202 | N.left = N.right = NULL; | 1537 | N.left = N.right = NULL; |
| 1203 | l = r = &N; | 1538 | l = r = &N; |
| @@ -1242,10 +1577,11 @@ static Tree * splay_end (size_t addr, Tree *t) · 38 unmodified lines |
| 1242 | | 1577 | |
| 1243 | static Tree * splay_insert(size_t addr, size_t size, Tree * t) | 1578 | static Tree * splay_insert(size_t addr, size_t size, Tree * t) |
| 1244 | /* Insert key start into the tree t, if it is not already there. */ | 1579 | /* Insert key start into the tree t, if it is not already there. */ |
| 1245 | /* Return a pointer to the resulting tree. */ | 1580 | /* Return a pointer to the resulting tree. */ |
| 1246 | { | 1581 | { |
| 1247 | Tree * new; | 1582 | Tree * new; |
| 1248 | | 1583 | |
| | 1584 | INCR_COUNT_SPLAY(bound_splay_insert); |
| 1249 | if (t != NULL) { | 1585 | if (t != NULL) { |
| 1250 | t = splay(addr,t); | 1586 | t = splay(addr,t); |
| 1251 | if (compare(addr, t->start, t->size)==0) { | 1587 | if (compare(addr, t->start, t->size)==0) { |
| @@ -1267,7 +1603,7 @@ static Tree * splay_insert(size_t addr, size_t size, Tree * t) · 15 unmodified lines |
| 1267 | #endif | 1603 | #endif |
| 1268 | } | 1604 | } |
| 1269 | if (new == NULL) { | 1605 | if (new == NULL) { |
| 1270 | bound_alloc_error(); | 1606 | bound_alloc_error("not enough memory for bound checking code"); |
| 1271 | } | 1607 | } |
| 1272 | else { | 1608 | else { |
| 1273 | if (t == NULL) { | 1609 | if (t == NULL) { |
| @@ -1294,13 +1630,14 @@ static Tree * splay_insert(size_t addr, size_t size, Tree * t) · 20 unmodified lines |
| 1294 | | 1630 | |
| 1295 | static Tree * splay_delete(size_t addr, Tree *t) | 1631 | static Tree * splay_delete(size_t addr, Tree *t) |
| 1296 | /* Deletes addr from the tree if it's there. */ | 1632 | /* Deletes addr from the tree if it's there. */ |
| 1297 | /* Return a pointer to the resulting tree. */ | 1633 | /* Return a pointer to the resulting tree. */ |
| 1298 | { | 1634 | { |
| 1299 | Tree * x; | 1635 | Tree * x; |
| 1300 | | 1636 | |
| | 1637 | INCR_COUNT_SPLAY(bound_splay_delete); |
| 1301 | if (t==NULL) return NULL; | 1638 | if (t==NULL) return NULL; |
| 1302 | t = splay(addr,t); | 1639 | t = splay(addr,t); |
| 1303 | if (compare_destroy(addr, t->start) == 0) { /* found it */ | 1640 | if (compare_destroy(addr, t->start) == 0) { /* found it */ |
| 1304 | if (t->left == NULL) { | 1641 | if (t->left == NULL) { |
| 1305 | x = t->right; | 1642 | x = t->right; |
| 1306 | } else { | 1643 | } else { |
| @@ -1319,7 +1656,7 @@ static Tree * splay_delete(size_t addr, Tree *t) · 12 unmodified lines |
| 1319 | #endif | 1656 | #endif |
| 1320 | return x; | 1657 | return x; |
| 1321 | } else { | 1658 | } else { |
| 1322 | return t; /* It wasn't there */ | 1659 | return t; /* It wasn't there */ |
| 1323 | } | 1660 | } |
| 1324 | } | 1661 | } |
| 1325 | | 1662 | |
| @@ -1329,7 +1666,8 @@ void splay_printtree(Tree * t, int d) · 3 unmodified lines |
| 1329 | if (t == NULL) return; | 1666 | if (t == NULL) return; |
| 1330 | splay_printtree(t->right, d+1); | 1667 | splay_printtree(t->right, d+1); |
| 1331 | for (i=0; i<d; i++) fprintf(stderr," "); | 1668 | for (i=0; i<d; i++) fprintf(stderr," "); |
| 1332 | fprintf(stderr,"%p(0x%lx:%u)\n", | 1669 | fprintf(stderr,"%p(0x%lx:%u:%u)\n", |
| 1333 | (void *) t->start, (unsigned long) t->size, (unsigned)t->is_invalid); | 1670 | (void *) t->start, (unsigned long) t->size, |
| | 1671 | (unsigned)t->type, (unsigned)t->is_invalid); |
| 1334 | splay_printtree(t->left, d+1); | 1672 | splay_printtree(t->left, d+1); |
| 1335 | } | 1673 | } |