| /* This test file is part of GDB, the GNU debugger. | |
| Copyright 2021-2022 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; | |
| } |