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) | |
download | rockbox-8ff4f1aec9f19613e4f67d2e22ae96bec7657292.tar.gz rockbox-8ff4f1aec9f19613e4f67d2e22ae96bec7657292.zip |
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 @@ | |||
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdio.h> | 21 | #include <stdio.h> |
22 | #include "buffer.h" | 22 | #include "buffer.h" |
23 | #include "panic.h" | ||
24 | #include "logf.h" | ||
23 | 25 | ||
24 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 26 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) |
25 | unsigned char audiobuffer[(MEM*1024-256)*1024]; | 27 | unsigned char audiobuffer[(MEM*1024-256)*1024]; |
@@ -31,20 +33,94 @@ extern unsigned char audiobuffer[]; | |||
31 | 33 | ||
32 | unsigned char *audiobuf; | 34 | unsigned char *audiobuf; |
33 | 35 | ||
36 | #ifdef BUFFER_ALLOC_DEBUG | ||
37 | static unsigned char *audiobuf_orig_start; | ||
38 | |||
39 | struct buffer_start_marker | ||
40 | { | ||
41 | unsigned int magic; | ||
42 | size_t buffer_size; | ||
43 | }; | ||
44 | #define BUF_MAGIC 0xDEADD0D0 | ||
45 | |||
46 | struct buffer_end_marker | ||
47 | { | ||
48 | unsigned int magic; | ||
49 | int last; | ||
50 | }; | ||
51 | #endif /* BUFFER_ALLOC_DEBUG */ | ||
52 | |||
34 | void buffer_init(void) | 53 | void buffer_init(void) |
35 | { | 54 | { |
36 | /* 32-bit aligned */ | 55 | /* 32-bit aligned */ |
37 | audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); | 56 | audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); |
57 | #ifdef BUFFER_ALLOC_DEBUG | ||
58 | audiobuf_orig_start = audiobuf; | ||
59 | #endif /* BUFFER_ALLOC_DEBUG */ | ||
38 | } | 60 | } |
39 | 61 | ||
40 | void *buffer_alloc(size_t size) | 62 | void *buffer_alloc(size_t size) |
41 | { | 63 | { |
42 | void *retval = audiobuf; | 64 | void *retval = audiobuf; |
43 | 65 | #ifdef BUFFER_ALLOC_DEBUG | |
44 | audiobuf += size; | 66 | struct buffer_start_marker *start; |
67 | struct buffer_end_marker *end; | ||
68 | #endif /* BUFFER_ALLOC_DEBUG */ | ||
69 | |||
45 | /* 32-bit aligned */ | 70 | /* 32-bit aligned */ |
46 | audiobuf = (void *)(((unsigned long)audiobuf + 3) & ~3); | 71 | size = (size + 3) & ~3; |
72 | |||
73 | #ifdef BUFFER_ALLOC_DEBUG | ||
74 | retval +=sizeof(struct buffer_start_marker); | ||
75 | end=(struct buffer_end_marker*)(audiobuf - sizeof(struct buffer_end_marker)); | ||
76 | if(end->magic == BUF_MAGIC) | ||
77 | { | ||
78 | end->last=0; | ||
79 | } | ||
80 | start=(struct buffer_start_marker*)audiobuf; | ||
81 | start->magic = BUF_MAGIC; | ||
82 | start->buffer_size = size; | ||
83 | end=(struct buffer_end_marker*)(audiobuf+sizeof(struct buffer_start_marker)+size); | ||
84 | end->magic = BUF_MAGIC; | ||
85 | end->last = 1; | ||
86 | |||
87 | audiobuf = ((unsigned char *)end) + sizeof(struct buffer_end_marker); | ||
88 | |||
89 | logf("Alloc %x %d",(unsigned int)retval,size); | ||
90 | #else /* !BUFFER_ALLOC_DEBUG */ | ||
91 | audiobuf += size; | ||
92 | #endif /* BUFFER_ALLOC_DEBUG */ | ||
93 | |||
94 | if (audiobuf > audiobufend) { | ||
95 | panicf("OOM: %d bytes", (int) size); | ||
96 | } | ||
47 | 97 | ||
48 | return retval; | 98 | return retval; |
49 | } | 99 | } |
50 | 100 | ||
101 | #ifdef BUFFER_ALLOC_DEBUG | ||
102 | void buffer_alloc_check(char *name) | ||
103 | { | ||
104 | unsigned char *buf_ptr = audiobuf_orig_start; | ||
105 | struct buffer_start_marker *start; | ||
106 | struct buffer_end_marker *end; | ||
107 | |||
108 | |||
109 | while(buf_ptr < audiobuf) | ||
110 | { | ||
111 | start=(struct buffer_start_marker*)buf_ptr; | ||
112 | if(start->magic != BUF_MAGIC) | ||
113 | { | ||
114 | panicf("%s corrupted buffer %x start", name,(unsigned int)buf_ptr+sizeof(struct buffer_start_marker)); | ||
115 | } | ||
116 | end=(struct buffer_end_marker*)(buf_ptr+sizeof(struct buffer_start_marker)+start->buffer_size); | ||
117 | if(end->magic != BUF_MAGIC) | ||
118 | { | ||
119 | panicf("%s corrupted %x end", name,(unsigned int)buf_ptr+sizeof(struct buffer_start_marker)); | ||
120 | } | ||
121 | if(end->last) | ||
122 | break; | ||
123 | buf_ptr=((unsigned char *)end)+sizeof(struct buffer_end_marker); | ||
124 | } | ||
125 | } | ||
126 | #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; | |||
39 | void buffer_init(void) INIT_ATTR; | 39 | void buffer_init(void) INIT_ATTR; |
40 | void *buffer_alloc(size_t size); | 40 | void *buffer_alloc(size_t size); |
41 | 41 | ||
42 | #ifdef BUFFER_ALLOC_DEBUG | ||
43 | void buffer_alloc_check(char *name); | ||
44 | #endif | ||
45 | |||
42 | #endif | 46 | #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 @@ | |||
27 | #include "kernel.h" | 27 | #include "kernel.h" |
28 | #include "cpu.h" | 28 | #include "cpu.h" |
29 | #include "string.h" | 29 | #include "string.h" |
30 | #include "buffer.h" | ||
30 | #ifdef RB_PROFILE | 31 | #ifdef RB_PROFILE |
31 | #include <profile.h> | 32 | #include <profile.h> |
32 | #endif | 33 | #endif |
@@ -1160,6 +1161,16 @@ void switch_thread(void) | |||
1160 | if (UNLIKELY(thread->stack[0] != DEADBEEF) && thread->stack_size > 0) | 1161 | if (UNLIKELY(thread->stack[0] != DEADBEEF) && thread->stack_size > 0) |
1161 | thread_stkov(thread); | 1162 | thread_stkov(thread); |
1162 | 1163 | ||
1164 | #ifdef BUFFER_ALLOC_DEBUG | ||
1165 | /* Check if the current thread just did bad things with buffer_alloc()ed | ||
1166 | * memory */ | ||
1167 | { | ||
1168 | static char name[32]; | ||
1169 | thread_get_name(name, 32, thread); | ||
1170 | buffer_alloc_check(name); | ||
1171 | } | ||
1172 | #endif | ||
1173 | |||
1163 | #if NUM_CORES > 1 | 1174 | #if NUM_CORES > 1 |
1164 | /* Run any blocking operations requested before switching/sleeping */ | 1175 | /* Run any blocking operations requested before switching/sleeping */ |
1165 | run_blocking_ops(core, thread); | 1176 | run_blocking_ops(core, thread); |