better error display - added some string functions
This commit is contained in:
parent
3d22a2aa6d
commit
4a922fa9ed
1 changed files with 71 additions and 19 deletions
88
bcheck.c
88
bcheck.c
|
|
@ -54,7 +54,7 @@ typedef struct BoundEntry {
|
||||||
/* external interface */
|
/* external interface */
|
||||||
void __bound_init(void);
|
void __bound_init(void);
|
||||||
void __bound_new_region(void *p, unsigned long size);
|
void __bound_new_region(void *p, unsigned long size);
|
||||||
void __bound_delete_region(void *p);
|
int __bound_delete_region(void *p);
|
||||||
|
|
||||||
/* currently, tcc cannot compile that because we use unsupported GNU C
|
/* currently, tcc cannot compile that because we use unsupported GNU C
|
||||||
extensions */
|
extensions */
|
||||||
|
|
@ -69,6 +69,7 @@ void *__bound_ptr_indir16(void *p, int offset) __attribute__((regparm(2)));
|
||||||
void __bound_local_new(void *p) __attribute__((regparm(1)));
|
void __bound_local_new(void *p) __attribute__((regparm(1)));
|
||||||
void __bound_local_delete(void *p) __attribute__((regparm(1)));
|
void __bound_local_delete(void *p) __attribute__((regparm(1)));
|
||||||
#endif
|
#endif
|
||||||
|
static void *get_caller_pc(int n);
|
||||||
|
|
||||||
void *__bound_malloc(size_t size, const void *caller);
|
void *__bound_malloc(size_t size, const void *caller);
|
||||||
void *__bound_memalign(size_t size, size_t align, const void *caller);
|
void *__bound_memalign(size_t size, size_t align, const void *caller);
|
||||||
|
|
@ -122,20 +123,16 @@ static BoundEntry *__bound_find_region(BoundEntry *e1, void *p)
|
||||||
return __bound_empty_t2;
|
return __bound_empty_t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bound_error(const char *fmt, ...)
|
/* print a bound error and recurse thru 'nb_callers' to get the error
|
||||||
|
position */
|
||||||
|
static void bound_error(const void *caller, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
rt_error((unsigned long)caller, "%s", fmt);
|
||||||
va_start(ap, fmt);
|
|
||||||
fprintf(stderr, "bounds check: ");
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
exit(1);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bound_alloc_error(void)
|
static void bound_alloc_error(void)
|
||||||
{
|
{
|
||||||
bound_error("not enough memory for bound checking code\n");
|
bound_error(NULL, "not enough memory for bound checking code\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* currently, tcc cannot compile that because we use GNUC extensions */
|
/* currently, tcc cannot compile that because we use GNUC extensions */
|
||||||
|
|
@ -190,6 +187,20 @@ void *__bound_ptr_indir ## dsize (void *p, int offset) \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
|
|
||||||
|
/* return the PC of the N'th caller (N=1: first caller) */
|
||||||
|
static void *get_caller_pc(int n)
|
||||||
|
{
|
||||||
|
unsigned long fp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
__asm__ __volatile__ ("movl %%ebp,%0" :"=g" (fp));
|
||||||
|
for(i=0;i<n;i++)
|
||||||
|
fp = ((unsigned long *)fp)[0];
|
||||||
|
return ((void **)fp)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the frame pointer of the caller */
|
||||||
#define GET_CALLER_FP(fp)\
|
#define GET_CALLER_FP(fp)\
|
||||||
{\
|
{\
|
||||||
unsigned long *fp1;\
|
unsigned long *fp1;\
|
||||||
|
|
@ -251,6 +262,10 @@ void *__bound_ptr_indir ## dsize (void *p, int offset) \
|
||||||
return p + offset; \
|
return p + offset; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *get_caller_pc(int n)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOUND_PTR_INDIR(1)
|
BOUND_PTR_INDIR(1)
|
||||||
|
|
@ -527,7 +542,8 @@ static inline void delete_region(BoundEntry *e,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WARNING: 'p' must be the starting point of the region. */
|
/* WARNING: 'p' must be the starting point of the region. */
|
||||||
void __bound_delete_region(void *p)
|
/* return non zero if error */
|
||||||
|
int __bound_delete_region(void *p)
|
||||||
{
|
{
|
||||||
unsigned long start, end, addr, size, empty_size;
|
unsigned long start, end, addr, size, empty_size;
|
||||||
BoundEntry *page, *e, *e2;
|
BoundEntry *page, *e, *e2;
|
||||||
|
|
@ -546,7 +562,7 @@ void __bound_delete_region(void *p)
|
||||||
e = __bound_find_region(e, p);
|
e = __bound_find_region(e, p);
|
||||||
/* test if invalid region */
|
/* test if invalid region */
|
||||||
if (e->size == EMPTY_SIZE || (unsigned long)p != e->start)
|
if (e->size == EMPTY_SIZE || (unsigned long)p != e->start)
|
||||||
bound_error("freeing invalid region");
|
return -1;
|
||||||
/* compute the size we put in invalid regions */
|
/* compute the size we put in invalid regions */
|
||||||
if (e->is_invalid)
|
if (e->is_invalid)
|
||||||
empty_size = INVALID_SIZE;
|
empty_size = INVALID_SIZE;
|
||||||
|
|
@ -599,6 +615,7 @@ void __bound_delete_region(void *p)
|
||||||
}
|
}
|
||||||
delete_region(e, p, empty_size);
|
delete_region(e, p, empty_size);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the size of the region starting at p, or EMPTY_SIZE if non
|
/* return the size of the region starting at p, or EMPTY_SIZE if non
|
||||||
|
|
@ -699,7 +716,8 @@ void __bound_free(void *ptr, const void *caller)
|
||||||
{
|
{
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return;
|
return;
|
||||||
__bound_delete_region(ptr);
|
if (__bound_delete_region(ptr) != 0)
|
||||||
|
bound_error(caller, "freeing invalid region");
|
||||||
|
|
||||||
libc_free(ptr);
|
libc_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
@ -718,7 +736,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
|
||||||
return ptr1;
|
return ptr1;
|
||||||
old_size = get_region_size(ptr);
|
old_size = get_region_size(ptr);
|
||||||
if (old_size == EMPTY_SIZE)
|
if (old_size == EMPTY_SIZE)
|
||||||
bound_error("realloc'ing invalid pointer");
|
bound_error(caller, "realloc'ing invalid pointer");
|
||||||
memcpy(ptr1, ptr, old_size);
|
memcpy(ptr1, ptr, old_size);
|
||||||
__bound_free(ptr, caller);
|
__bound_free(ptr, caller);
|
||||||
return ptr1;
|
return ptr1;
|
||||||
|
|
@ -752,7 +770,41 @@ static void bound_dump(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
/* some useful checked functions */
|
||||||
|
|
||||||
|
/* check that (p ... p + size - 1) lies inside 'p' region, if any */
|
||||||
|
static void __bound_check(const void *p, ssize_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
p = __bound_ptr_add((void *)p, size);
|
||||||
|
if (p == INVALID_POINTER)
|
||||||
|
bound_error(get_caller_pc(2), "invalid pointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__bound_memcpy(void *dst, const void *src, size_t size)
|
||||||
|
{
|
||||||
|
__bound_check(dst, size);
|
||||||
|
__bound_check(src, size);
|
||||||
|
/* check also region overlap */
|
||||||
|
if (src >= dst && src < dst + size)
|
||||||
|
bound_error(get_caller_pc(1), "memcpy: overlapping regions");
|
||||||
|
return memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__bound_memmove(void *dst, const void *src, size_t size)
|
||||||
|
{
|
||||||
|
__bound_check(dst, size);
|
||||||
|
__bound_check(src, size);
|
||||||
|
return memmove(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__bound_memset(void *dst, int c, size_t size)
|
||||||
|
{
|
||||||
|
__bound_check(dst, size);
|
||||||
|
return memset(dst, 0, size);
|
||||||
|
}
|
||||||
|
|
||||||
/* resolve check check syms */
|
/* resolve check check syms */
|
||||||
typedef struct BCSyms {
|
typedef struct BCSyms {
|
||||||
char *str;
|
char *str;
|
||||||
|
|
@ -760,13 +812,14 @@ typedef struct BCSyms {
|
||||||
} BCSyms;
|
} BCSyms;
|
||||||
|
|
||||||
static BCSyms bcheck_syms[] = {
|
static BCSyms bcheck_syms[] = {
|
||||||
|
{ "memcpy", __bound_memcpy },
|
||||||
|
{ "memmove", __bound_memmove },
|
||||||
|
{ "memset", __bound_memset },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
static void *bound_resolve_sym(const char *sym)
|
static void *bound_resolve_sym(const char *sym)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
BCSyms *p;
|
BCSyms *p;
|
||||||
p = bcheck_syms;
|
p = bcheck_syms;
|
||||||
while (p->str != NULL) {
|
while (p->str != NULL) {
|
||||||
|
|
@ -774,6 +827,5 @@ static void *bound_resolve_sym(const char *sym)
|
||||||
return p->ptr;
|
return p->ptr;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue