From 8ff4f1aec9f19613e4f67d2e22ae96bec7657292 Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Sun, 26 Sep 2010 12:05:42 +0000 Subject: 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 --- firmware/buffer.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-- firmware/export/buffer.h | 4 +++ firmware/thread.c | 11 +++++++ 3 files changed, 94 insertions(+), 3 deletions(-) (limited to 'firmware') 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 #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 #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); -- cgit v1.2.3