|  | /* This test file is part of GDB, the GNU debugger. | 
|  |  | 
|  | Copyright 2021-2024 Free Software Foundation, Inc. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <assert.h> | 
|  | #include <string.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | /* Return true if address P is ALIGNMENT-byte aligned.  */ | 
|  |  | 
|  | static int | 
|  | is_aligned (void *p, size_t alignment) | 
|  | { | 
|  | size_t mask = (alignment - 1); | 
|  | return ((uintptr_t)p & mask) == 0; | 
|  | } | 
|  |  | 
|  | /* Allocate SIZE memory with ALIGNMENT, and return it.  If FREE_POINTER, | 
|  | return in it the corresponding pointer to be passed to free. | 
|  |  | 
|  | Do the alignment precisely, in other words, if an alignment of 4 is | 
|  | requested, make sure the pointer is 4-byte aligned, but not 8-byte | 
|  | aligned.  In other words, make sure the pointer is not overaligned. | 
|  |  | 
|  | The benefit of using precise alignment is that accidentally specifying | 
|  | a too low alignment will not be compensated by accidental | 
|  | overalignment.  */ | 
|  |  | 
|  | static void * | 
|  | precise_aligned_alloc (size_t alignment, size_t size, void **free_pointer) | 
|  | { | 
|  | /* Allocate extra to compensate for "p += alignment".  */ | 
|  | size_t alloc_size = size + alignment; | 
|  |  | 
|  | /* Align extra, to be able to do precise align.  */ | 
|  | void *p = aligned_alloc (alignment * 2, alloc_size); | 
|  | assert (p != NULL); | 
|  | void *p_orig = p; | 
|  | void *p_end = p + alloc_size; | 
|  |  | 
|  | /* Make p precisely aligned.  */ | 
|  | p += alignment; | 
|  |  | 
|  | /* Verify p is without bounds, and points to large enough area.  */ | 
|  | assert (p >= p_orig); | 
|  | assert (p + size <= p_end); | 
|  |  | 
|  | /* Verify required alignment.  */ | 
|  | assert (is_aligned (p, alignment)); | 
|  |  | 
|  | /* Verify required alignment is precise.  */ | 
|  | assert (! is_aligned (p, 2 * alignment)); | 
|  |  | 
|  | if (free_pointer != NULL) | 
|  | *free_pointer = p_orig; | 
|  |  | 
|  | return p; | 
|  | } | 
|  |  | 
|  | /* Duplicate data SRC of size SIZE to a newly allocated, precisely aligned | 
|  | location with alignment ALIGNMENT.  */ | 
|  |  | 
|  | static void * | 
|  | precise_aligned_dup (size_t alignment, size_t size, void **free_pointer, | 
|  | void *src) | 
|  | { | 
|  | void *p = precise_aligned_alloc (alignment, size, free_pointer); | 
|  |  | 
|  | memcpy (p, src, size); | 
|  |  | 
|  | return p; | 
|  | } |