|  | @@ -15,9 +15,13 @@
 | 
		
	
		
			
			| 15 | 15 |   * along with this program; if not, write to the Free Software
 | 
		
	
		
			
			| 16 | 16 |   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
		
	
		
			
			| 17 | 17 |   * 02110-1301, USA.
 | 
		
	
		
			
			|  | 18 | + *
 | 
		
	
		
			
			|  | 19 | + * You can also choose to distribute this program under the terms of
 | 
		
	
		
			
			|  | 20 | + * the Unmodified Binary Distribution Licence (as given in the file
 | 
		
	
		
			
			|  | 21 | + * COPYING.UBDL), provided that you have satisfied its requirements.
 | 
		
	
		
			
			| 18 | 22 |   */
 | 
		
	
		
			
			| 19 | 23 |  
 | 
		
	
		
			
			| 20 |  | -FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			|  | 24 | +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 21 | 25 |  
 | 
		
	
		
			
			| 22 | 26 |  #include <stddef.h>
 | 
		
	
		
			
			| 23 | 27 |  #include <stdint.h>
 | 
		
	
	
		
			
			|  | @@ -106,6 +110,7 @@ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) )));
 | 
		
	
		
			
			| 106 | 110 |  static inline void valgrind_make_blocks_defined ( void ) {
 | 
		
	
		
			
			| 107 | 111 |  	struct memory_block *block;
 | 
		
	
		
			
			| 108 | 112 |  
 | 
		
	
		
			
			|  | 113 | +	/* Do nothing unless running under Valgrind */
 | 
		
	
		
			
			| 109 | 114 |  	if ( RUNNING_ON_VALGRIND <= 0 )
 | 
		
	
		
			
			| 110 | 115 |  		return;
 | 
		
	
		
			
			| 111 | 116 |  
 | 
		
	
	
		
			
			|  | @@ -147,6 +152,7 @@ static inline void valgrind_make_blocks_noaccess ( void ) {
 | 
		
	
		
			
			| 147 | 152 |  	struct memory_block *block;
 | 
		
	
		
			
			| 148 | 153 |  	struct memory_block *prev = NULL;
 | 
		
	
		
			
			| 149 | 154 |  
 | 
		
	
		
			
			|  | 155 | +	/* Do nothing unless running under Valgrind */
 | 
		
	
		
			
			| 150 | 156 |  	if ( RUNNING_ON_VALGRIND <= 0 )
 | 
		
	
		
			
			| 151 | 157 |  		return;
 | 
		
	
		
			
			| 152 | 158 |  
 | 
		
	
	
		
			
			|  | @@ -267,24 +273,25 @@ static void discard_all_cache ( void ) {
 | 
		
	
		
			
			| 267 | 273 |  void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 268 | 274 |  	struct memory_block *block;
 | 
		
	
		
			
			| 269 | 275 |  	size_t align_mask;
 | 
		
	
		
			
			|  | 276 | +	size_t actual_size;
 | 
		
	
		
			
			| 270 | 277 |  	size_t pre_size;
 | 
		
	
		
			
			| 271 | 278 |  	ssize_t post_size;
 | 
		
	
		
			
			| 272 | 279 |  	struct memory_block *pre;
 | 
		
	
		
			
			| 273 | 280 |  	struct memory_block *post;
 | 
		
	
		
			
			| 274 |  | -	struct memory_block *ptr;
 | 
		
	
		
			
			|  | 281 | +	void *ptr;
 | 
		
	
		
			
			| 275 | 282 |  
 | 
		
	
		
			
			| 276 | 283 |  	/* Sanity checks */
 | 
		
	
		
			
			| 277 | 284 |  	assert ( size != 0 );
 | 
		
	
		
			
			| 278 | 285 |  	assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
 | 
		
	
		
			
			| 279 |  | -
 | 
		
	
		
			
			| 280 | 286 |  	valgrind_make_blocks_defined();
 | 
		
	
		
			
			| 281 | 287 |  	check_blocks();
 | 
		
	
		
			
			| 282 | 288 |  
 | 
		
	
		
			
			| 283 | 289 |  	/* Round up size to multiple of MIN_MEMBLOCK_SIZE and
 | 
		
	
		
			
			| 284 | 290 |  	 * calculate alignment mask.
 | 
		
	
		
			
			| 285 | 291 |  	 */
 | 
		
	
		
			
			| 286 |  | -	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
 | 
		
	
		
			
			| 287 |  | -	align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
 | 
		
	
		
			
			|  | 292 | +	actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
 | 
		
	
		
			
			|  | 293 | +			~( MIN_MEMBLOCK_SIZE - 1 ) );
 | 
		
	
		
			
			|  | 294 | +	align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) );
 | 
		
	
		
			
			| 288 | 295 |  
 | 
		
	
		
			
			| 289 | 296 |  	DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n",
 | 
		
	
		
			
			| 290 | 297 |  		size, align, offset );
 | 
		
	
	
		
			
			|  | @@ -293,7 +300,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 293 | 300 |  		list_for_each_entry ( block, &free_blocks, list ) {
 | 
		
	
		
			
			| 294 | 301 |  			pre_size = ( ( offset - virt_to_phys ( block ) )
 | 
		
	
		
			
			| 295 | 302 |  				     & align_mask );
 | 
		
	
		
			
			| 296 |  | -			post_size = ( block->size - pre_size - size );
 | 
		
	
		
			
			|  | 303 | +			post_size = ( block->size - pre_size - actual_size );
 | 
		
	
		
			
			| 297 | 304 |  			if ( post_size >= 0 ) {
 | 
		
	
		
			
			| 298 | 305 |  				/* Split block into pre-block, block, and
 | 
		
	
		
			
			| 299 | 306 |  				 * post-block.  After this split, the "pre"
 | 
		
	
	
		
			
			|  | @@ -302,7 +309,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 302 | 309 |  				 */
 | 
		
	
		
			
			| 303 | 310 |  				pre   = block;
 | 
		
	
		
			
			| 304 | 311 |  				block = ( ( ( void * ) pre   ) + pre_size );
 | 
		
	
		
			
			| 305 |  | -				post  = ( ( ( void * ) block ) + size     );
 | 
		
	
		
			
			|  | 312 | +				post  = ( ( ( void * ) block ) + actual_size );
 | 
		
	
		
			
			| 306 | 313 |  				DBGC2 ( &heap, "[%p,%p) -> [%p,%p) + [%p,%p)\n",
 | 
		
	
		
			
			| 307 | 314 |  					pre, ( ( ( void * ) pre ) + pre->size ),
 | 
		
	
		
			
			| 308 | 315 |  					pre, block, post,
 | 
		
	
	
		
			
			|  | @@ -313,8 +320,8 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 313 | 320 |  				 * the heap).
 | 
		
	
		
			
			| 314 | 321 |  				 */
 | 
		
	
		
			
			| 315 | 322 |  				if ( (size_t) post_size >= MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			| 316 |  | -					VALGRIND_MAKE_MEM_DEFINED ( post,
 | 
		
	
		
			
			| 317 |  | -							     sizeof ( *post ) );
 | 
		
	
		
			
			|  | 323 | +					VALGRIND_MAKE_MEM_UNDEFINED
 | 
		
	
		
			
			|  | 324 | +						( post, sizeof ( *post ) );
 | 
		
	
		
			
			| 318 | 325 |  					post->size = post_size;
 | 
		
	
		
			
			| 319 | 326 |  					list_add ( &post->list, &pre->list );
 | 
		
	
		
			
			| 320 | 327 |  				}
 | 
		
	
	
		
			
			|  | @@ -328,14 +335,18 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 328 | 335 |  				 * it is too small, which can happen only at
 | 
		
	
		
			
			| 329 | 336 |  				 * the very start of the heap.
 | 
		
	
		
			
			| 330 | 337 |  				 */
 | 
		
	
		
			
			| 331 |  | -				if ( pre_size < MIN_MEMBLOCK_SIZE )
 | 
		
	
		
			
			|  | 338 | +				if ( pre_size < MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			| 332 | 339 |  					list_del ( &pre->list );
 | 
		
	
		
			
			|  | 340 | +					VALGRIND_MAKE_MEM_NOACCESS
 | 
		
	
		
			
			|  | 341 | +						( pre, sizeof ( *pre ) );
 | 
		
	
		
			
			|  | 342 | +				}
 | 
		
	
		
			
			| 333 | 343 |  				/* Update total free memory */
 | 
		
	
		
			
			| 334 |  | -				freemem -= size;
 | 
		
	
		
			
			|  | 344 | +				freemem -= actual_size;
 | 
		
	
		
			
			| 335 | 345 |  				/* Return allocated block */
 | 
		
	
		
			
			| 336 | 346 |  				DBGC2 ( &heap, "Allocated [%p,%p)\n", block,
 | 
		
	
		
			
			| 337 | 347 |  					( ( ( void * ) block ) + size ) );
 | 
		
	
		
			
			| 338 | 348 |  				ptr = block;
 | 
		
	
		
			
			|  | 349 | +				VALGRIND_MAKE_MEM_UNDEFINED ( ptr, size );
 | 
		
	
		
			
			| 339 | 350 |  				goto done;
 | 
		
	
		
			
			| 340 | 351 |  			}
 | 
		
	
		
			
			| 341 | 352 |  		}
 | 
		
	
	
		
			
			|  | @@ -368,13 +379,16 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 368 | 379 |  	struct memory_block *freeing;
 | 
		
	
		
			
			| 369 | 380 |  	struct memory_block *block;
 | 
		
	
		
			
			| 370 | 381 |  	struct memory_block *tmp;
 | 
		
	
		
			
			|  | 382 | +	size_t actual_size;
 | 
		
	
		
			
			| 371 | 383 |  	ssize_t gap_before;
 | 
		
	
		
			
			| 372 | 384 |  	ssize_t gap_after = -1;
 | 
		
	
		
			
			| 373 | 385 |  
 | 
		
	
		
			
			| 374 | 386 |  	/* Allow for ptr==NULL */
 | 
		
	
		
			
			| 375 | 387 |  	if ( ! ptr )
 | 
		
	
		
			
			| 376 | 388 |  		return;
 | 
		
	
		
			
			|  | 389 | +	VALGRIND_MAKE_MEM_NOACCESS ( ptr, size );
 | 
		
	
		
			
			| 377 | 390 |  
 | 
		
	
		
			
			|  | 391 | +	/* Sanity checks */
 | 
		
	
		
			
			| 378 | 392 |  	valgrind_make_blocks_defined();
 | 
		
	
		
			
			| 379 | 393 |  	check_blocks();
 | 
		
	
		
			
			| 380 | 394 |  
 | 
		
	
	
		
			
			|  | @@ -382,9 +396,10 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 382 | 396 |  	 * would have used.
 | 
		
	
		
			
			| 383 | 397 |  	 */
 | 
		
	
		
			
			| 384 | 398 |  	assert ( size != 0 );
 | 
		
	
		
			
			| 385 |  | -	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
 | 
		
	
		
			
			|  | 399 | +	actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
 | 
		
	
		
			
			|  | 400 | +			~( MIN_MEMBLOCK_SIZE - 1 ) );
 | 
		
	
		
			
			| 386 | 401 |  	freeing = ptr;
 | 
		
	
		
			
			| 387 |  | -	VALGRIND_MAKE_MEM_DEFINED ( freeing, sizeof ( *freeing ) );
 | 
		
	
		
			
			|  | 402 | +	VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
 | 
		
	
		
			
			| 388 | 403 |  	DBGC2 ( &heap, "Freeing [%p,%p)\n",
 | 
		
	
		
			
			| 389 | 404 |  		freeing, ( ( ( void * ) freeing ) + size ) );
 | 
		
	
		
			
			| 390 | 405 |  
 | 
		
	
	
		
			
			|  | @@ -392,7 +407,7 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 392 | 407 |  	if ( ASSERTING ) {
 | 
		
	
		
			
			| 393 | 408 |  		list_for_each_entry ( block, &free_blocks, list ) {
 | 
		
	
		
			
			| 394 | 409 |  			if ( ( ( ( void * ) block ) <
 | 
		
	
		
			
			| 395 |  | -			       ( ( void * ) freeing + size ) ) &&
 | 
		
	
		
			
			|  | 410 | +			       ( ( void * ) freeing + actual_size ) ) &&
 | 
		
	
		
			
			| 396 | 411 |  			     ( ( void * ) freeing <
 | 
		
	
		
			
			| 397 | 412 |  			       ( ( void * ) block + block->size ) ) ) {
 | 
		
	
		
			
			| 398 | 413 |  				assert ( 0 );
 | 
		
	
	
		
			
			|  | @@ -407,7 +422,7 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 407 | 422 |  	}
 | 
		
	
		
			
			| 408 | 423 |  
 | 
		
	
		
			
			| 409 | 424 |  	/* Insert/merge into free list */
 | 
		
	
		
			
			| 410 |  | -	freeing->size = size;
 | 
		
	
		
			
			|  | 425 | +	freeing->size = actual_size;
 | 
		
	
		
			
			| 411 | 426 |  	list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
 | 
		
	
		
			
			| 412 | 427 |  		/* Calculate gaps before and after the "freeing" block */
 | 
		
	
		
			
			| 413 | 428 |  		gap_before = ( ( ( void * ) freeing ) - 
 | 
		
	
	
		
			
			|  | @@ -421,8 +436,10 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 421 | 436 |  				( ( ( void * ) freeing ) + freeing->size ),
 | 
		
	
		
			
			| 422 | 437 |  				block,
 | 
		
	
		
			
			| 423 | 438 |  				( ( ( void * ) freeing ) + freeing->size ) );
 | 
		
	
		
			
			| 424 |  | -			block->size += size;
 | 
		
	
		
			
			|  | 439 | +			block->size += actual_size;
 | 
		
	
		
			
			| 425 | 440 |  			list_del ( &block->list );
 | 
		
	
		
			
			|  | 441 | +			VALGRIND_MAKE_MEM_NOACCESS ( freeing,
 | 
		
	
		
			
			|  | 442 | +						     sizeof ( *freeing ) );
 | 
		
	
		
			
			| 426 | 443 |  			freeing = block;
 | 
		
	
		
			
			| 427 | 444 |  		}
 | 
		
	
		
			
			| 428 | 445 |  		/* Stop processing as soon as we reach a following block */
 | 
		
	
	
		
			
			|  | @@ -444,10 +461,11 @@ void free_memblock ( void *ptr, size_t size ) {
 | 
		
	
		
			
			| 444 | 461 |  			( ( ( void * ) block ) + block->size ) );
 | 
		
	
		
			
			| 445 | 462 |  		freeing->size += block->size;
 | 
		
	
		
			
			| 446 | 463 |  		list_del ( &block->list );
 | 
		
	
		
			
			|  | 464 | +		VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
 | 
		
	
		
			
			| 447 | 465 |  	}
 | 
		
	
		
			
			| 448 | 466 |  
 | 
		
	
		
			
			| 449 | 467 |  	/* Update free memory counter */
 | 
		
	
		
			
			| 450 |  | -	freemem += size;
 | 
		
	
		
			
			|  | 468 | +	freemem += actual_size;
 | 
		
	
		
			
			| 451 | 469 |  
 | 
		
	
		
			
			| 452 | 470 |  	check_blocks();
 | 
		
	
		
			
			| 453 | 471 |  	valgrind_make_blocks_noaccess();
 | 
		
	
	
		
			
			|  | @@ -490,9 +508,9 @@ void * realloc ( void *old_ptr, size_t new_size ) {
 | 
		
	
		
			
			| 490 | 508 |  		new_block = alloc_memblock ( new_total_size, 1, 0 );
 | 
		
	
		
			
			| 491 | 509 |  		if ( ! new_block )
 | 
		
	
		
			
			| 492 | 510 |  			return NULL;
 | 
		
	
		
			
			| 493 |  | -		VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );
 | 
		
	
		
			
			| 494 | 511 |  		new_block->size = new_total_size;
 | 
		
	
		
			
			| 495 |  | -		VALGRIND_MAKE_MEM_NOACCESS ( new_block, offsetof ( struct autosized_block, data ) );
 | 
		
	
		
			
			|  | 512 | +		VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
 | 
		
	
		
			
			|  | 513 | +					     sizeof ( new_block->size ) );
 | 
		
	
		
			
			| 496 | 514 |  		new_ptr = &new_block->data;
 | 
		
	
		
			
			| 497 | 515 |  		VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
 | 
		
	
		
			
			| 498 | 516 |  	}
 | 
		
	
	
		
			
			|  | @@ -505,16 +523,16 @@ void * realloc ( void *old_ptr, size_t new_size ) {
 | 
		
	
		
			
			| 505 | 523 |  	if ( old_ptr && ( old_ptr != NOWHERE ) ) {
 | 
		
	
		
			
			| 506 | 524 |  		old_block = container_of ( old_ptr, struct autosized_block,
 | 
		
	
		
			
			| 507 | 525 |  					   data );
 | 
		
	
		
			
			| 508 |  | -		VALGRIND_MAKE_MEM_DEFINED ( old_block, offsetof ( struct autosized_block, data ) );
 | 
		
	
		
			
			|  | 526 | +		VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
 | 
		
	
		
			
			|  | 527 | +					    sizeof ( old_block->size ) );
 | 
		
	
		
			
			| 509 | 528 |  		old_total_size = old_block->size;
 | 
		
	
		
			
			| 510 | 529 |  		assert ( old_total_size != 0 );
 | 
		
	
		
			
			| 511 | 530 |  		old_size = ( old_total_size -
 | 
		
	
		
			
			| 512 | 531 |  			     offsetof ( struct autosized_block, data ) );
 | 
		
	
		
			
			| 513 | 532 |  		memcpy ( new_ptr, old_ptr,
 | 
		
	
		
			
			| 514 | 533 |  			 ( ( old_size < new_size ) ? old_size : new_size ) );
 | 
		
	
		
			
			| 515 |  | -		free_memblock ( old_block, old_total_size );
 | 
		
	
		
			
			| 516 |  | -		VALGRIND_MAKE_MEM_NOACCESS ( old_block, offsetof ( struct autosized_block, data ) );
 | 
		
	
		
			
			| 517 | 534 |  		VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
 | 
		
	
		
			
			|  | 535 | +		free_memblock ( old_block, old_total_size );
 | 
		
	
		
			
			| 518 | 536 |  	}
 | 
		
	
		
			
			| 519 | 537 |  
 | 
		
	
		
			
			| 520 | 538 |  	if ( ASSERTED ) {
 | 
		
	
	
		
			
			|  | @@ -611,6 +629,7 @@ void mpopulate ( void *start, size_t len ) {
 | 
		
	
		
			
			| 611 | 629 |   */
 | 
		
	
		
			
			| 612 | 630 |  static void init_heap ( void ) {
 | 
		
	
		
			
			| 613 | 631 |  	VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) );
 | 
		
	
		
			
			|  | 632 | +	VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
 | 
		
	
		
			
			| 614 | 633 |  	mpopulate ( heap, sizeof ( heap ) );
 | 
		
	
		
			
			| 615 | 634 |  }
 | 
		
	
		
			
			| 616 | 635 |  
 |