Browse Source

[malloc] Allow Valgrind to be used when all assertions are enabled

The free-memory-block traversal code triggers multiple warnings from
Valgrind when assertions are enabled, since the list consistency
checks performed by list_check() end up accessing areas that have been
marked as inaccessible.

Fix by ensuring that any memory areas that will be accessed by
list_check() are marked as defined when necessary.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
6f3e7e90fc
1 changed files with 67 additions and 11 deletions
  1. 67
    11
      src/core/malloc.c

+ 67
- 11
src/core/malloc.c View File

@@ -105,11 +105,36 @@ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) )));
105 105
 static inline void valgrind_make_blocks_defined ( void ) {
106 106
 	struct memory_block *block;
107 107
 
108
-	if ( RUNNING_ON_VALGRIND > 0 ) {
109
-		VALGRIND_MAKE_MEM_DEFINED ( &free_blocks,
110
-					    sizeof ( free_blocks ) );
111
-		list_for_each_entry ( block, &free_blocks, list )
112
-			VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
108
+	if ( RUNNING_ON_VALGRIND <= 0 )
109
+		return;
110
+
111
+	/* Traverse free block list, marking each block structure as
112
+	 * defined.  Some contortions are necessary to avoid errors
113
+	 * from list_check().
114
+	 */
115
+
116
+	/* Mark block list itself as defined */
117
+	VALGRIND_MAKE_MEM_DEFINED ( &free_blocks, sizeof ( free_blocks ) );
118
+
119
+	/* Mark areas accessed by list_check() as defined */
120
+	VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.prev->next,
121
+				    sizeof ( free_blocks.prev->next ) );
122
+	VALGRIND_MAKE_MEM_DEFINED ( free_blocks.next,
123
+				    sizeof ( *free_blocks.next ) );
124
+	VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->next->prev,
125
+				    sizeof ( free_blocks.next->next->prev ) );
126
+
127
+	/* Mark each block in list as defined */
128
+	list_for_each_entry ( block, &free_blocks, list ) {
129
+
130
+		/* Mark block as defined */
131
+		VALGRIND_MAKE_MEM_DEFINED ( block, sizeof ( *block ) );
132
+
133
+		/* Mark areas accessed by list_check() as defined */
134
+		VALGRIND_MAKE_MEM_DEFINED ( block->list.next,
135
+					    sizeof ( *block->list.next ) );
136
+		VALGRIND_MAKE_MEM_DEFINED ( &block->list.next->next->prev,
137
+				      sizeof ( block->list.next->next->prev ) );
113 138
 	}
114 139
 }
115 140
 
@@ -119,14 +144,45 @@ static inline void valgrind_make_blocks_defined ( void ) {
119 144
  */
120 145
 static inline void valgrind_make_blocks_noaccess ( void ) {
121 146
 	struct memory_block *block;
122
-	struct memory_block *tmp;
147
+	struct memory_block *prev = NULL;
123 148
 
124
-	if ( RUNNING_ON_VALGRIND > 0 ) {
125
-		list_for_each_entry_safe ( block, tmp, &free_blocks, list )
126
-			VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
127
-		VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks,
128
-					     sizeof ( free_blocks ) );
149
+	if ( RUNNING_ON_VALGRIND <= 0 )
150
+		return;
151
+
152
+	/* Traverse free block list, marking each block structure as
153
+	 * inaccessible.  Some contortions are necessary to avoid
154
+	 * errors from list_check().
155
+	 */
156
+
157
+	/* Mark each block in list as inaccessible */
158
+	list_for_each_entry ( block, &free_blocks, list ) {
159
+
160
+		/* Mark previous block (if any) as inaccessible. (Current
161
+		 * block will be accessed by list_check().)
162
+		 */
163
+		if ( prev )
164
+			VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
165
+		prev = block;
166
+
167
+		/* At the end of the list, list_check() will end up
168
+		 * accessing the first list item.  Temporarily mark
169
+		 * this area as defined.
170
+		 */
171
+		VALGRIND_MAKE_MEM_DEFINED ( &free_blocks.next->prev,
172
+					    sizeof ( free_blocks.next->prev ) );
129 173
 	}
174
+	/* Mark last block (if any) as inaccessible */
175
+	if ( prev )
176
+		VALGRIND_MAKE_MEM_NOACCESS ( prev, sizeof ( *prev ) );
177
+
178
+	/* Mark as inaccessible the area that was temporarily marked
179
+	 * as defined to avoid errors from list_check().
180
+	 */
181
+	VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks.next->prev,
182
+				     sizeof ( free_blocks.next->prev ) );
183
+
184
+	/* Mark block list itself as inaccessible */
185
+	VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
130 186
 }
131 187
 
132 188
 /**

Loading…
Cancel
Save