diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2010-09-26 12:05:42 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2010-09-26 12:05:42 +0000 |
commit | 8ff4f1aec9f19613e4f67d2e22ae96bec7657292 (patch) | |
tree | c9e2b19b56375fac35d996fb85d5e3a5802dfc45 | |
parent | 927a7bdb4b91d3a63f014824711f796e5eb4c5ba (diff) |
Add optional (define BUFFER_ALLOC_DEBUG to enable it) code to check for code overflowing buffer_alloc()-allocated buffers.
Also add a panicf() if buffer_alloc() doesn't have enough space left to allocate a requested buffer
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28173 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/buffer.c | 82 | ||||
-rw-r--r-- | firmware/export/buffer.h | 4 | ||||
-rw-r--r-- | firmware/thread.c | 11 |
3 files changed, 94 insertions, 3 deletions
diff --git a/firmware/buffer.c b/firmware/buffer.c index 015fc04b86..a21a882ff2 100644 --- a/firmware/buffer.c +++ b/firmware/buffer.c @@ -20,6 +20,8 @@ ****************************************************************************/ #include <stdio.h> #include "buffer.h" +#include "panic.h" +#include "logf.h" #if (CONFIG_PLATFORM & PLATFORM_HOSTED) unsigned char audiobuffer[(MEM*1024-256)*1024]; @@ -31,20 +33,94 @@ extern unsigned char audiobuffer[]; unsigned char *audiobuf; +#ifdef BUFFER_ALLOC_DEBUG +static unsigned char *audiobuf_orig_start; + +struct buffer_start_marker +{ + unsigned int magic; + size_t buffer_size; +}; +#define BUF_MAGIC 0xDEADD0D0 + +struct buffer_end_marker +{ + unsigned int magic; + int last; +}; +#endif /* BUFFER_ALLOC_DEBUG */ + void buffer_init(void) { /* 32-bit aligned */ audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); +#ifdef BUFFER_ALLOC_DEBUG + audiobuf_orig_start = audiobuf; +#endif /* BUFFER_ALLOC_DEBUG */ } void *buffer_alloc(size_t size) { void *retval = audiobuf; - - audiobuf += size; +#ifdef BUFFER_ALLOC_DEBUG + struct buffer_start_marker *start; + struct buffer_end_marker *end; +#endif /* BUFFER_ALLOC_DEBUG */ + /* 32-bit aligned */ - audiobuf = (void *)(((unsigned long)audiobuf + 3) & ~3); + size = (size + 3) & ~3; + +#ifdef BUFFER_ALLOC_DEBUG + retval +=sizeof(struct buffer_start_marker); + end=(struct buffer_end_marker*)(audiobuf - sizeof(struct buffer_end_marker)); + if(end->magic == BUF_MAGIC) + { + end->last=0; + } + start=(struct buffer_start_marker*)audiobuf; + start->magic = BUF_MAGIC; + start->buffer_size = size; + end=(struct buffer_end_marker*)(audiobuf+sizeof(struct buffer_start_marker)+size); + end->magic = BUF_MAGIC; + end->last = 1; + + audiobuf = ((unsigned char *)end) + sizeof(struct buffer_end_marker); + + logf("Alloc %x %d",(unsigned int)retval,size); +#else /* !BUFFER_ALLOC_DEBUG */ + audiobuf += size; +#endif /* BUFFER_ALLOC_DEBUG */ + + if (audiobuf > audiobufend) { + panicf("OOM: %d bytes", (int) size); + } return retval; } +#ifdef BUFFER_ALLOC_DEBUG +void buffer_alloc_check(char *name) +{ + unsigned char *buf_ptr = audiobuf_orig_start; + struct buffer_start_marker *start; + struct buffer_end_marker *end; + + + while(buf_ptr < audiobuf) + { + start=(struct buffer_start_marker*)buf_ptr; + if(start->magic != BUF_MAGIC) + { + panicf("%s corrupted buffer %x start", name,(unsigned int)buf_ptr+sizeof(struct buffer_start_marker)); + } + end=(struct buffer_end_marker*)(buf_ptr+sizeof(struct buffer_start_marker)+start->buffer_size); + if(end->magic != BUF_MAGIC) + { + panicf("%s corrupted %x end", name,(unsigned int)buf_ptr+sizeof(struct buffer_start_marker)); + } + if(end->last) + break; + buf_ptr=((unsigned char *)end)+sizeof(struct buffer_end_marker); + } +} +#endif /* BUFFER_ALLOC_DEBUG */ diff --git a/firmware/export/buffer.h b/firmware/export/buffer.h index f0525edd68..18f53f0000 100644 --- a/firmware/export/buffer.h +++ b/firmware/export/buffer.h @@ -39,4 +39,8 @@ extern unsigned char *audiobuf; void buffer_init(void) INIT_ATTR; void *buffer_alloc(size_t size); +#ifdef BUFFER_ALLOC_DEBUG +void buffer_alloc_check(char *name); +#endif + #endif diff --git a/firmware/thread.c b/firmware/thread.c index b3d8ec3970..655af1a940 100644 --- a/firmware/thread.c +++ b/firmware/thread.c @@ -27,6 +27,7 @@ #include "kernel.h" #include "cpu.h" #include "string.h" +#include "buffer.h" #ifdef RB_PROFILE #include <profile.h> #endif @@ -1160,6 +1161,16 @@ void switch_thread(void) if (UNLIKELY(thread->stack[0] != DEADBEEF) && thread->stack_size > 0) thread_stkov(thread); +#ifdef BUFFER_ALLOC_DEBUG + /* Check if the current thread just did bad things with buffer_alloc()ed + * memory */ + { + static char name[32]; + thread_get_name(name, 32, thread); + buffer_alloc_check(name); + } +#endif + #if NUM_CORES > 1 /* Run any blocking operations requested before switching/sleeping */ run_blocking_ops(core, thread); |