xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/lib/precise-aligned-alloc.c (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1 /* This test file is part of GDB, the GNU debugger.
2 
3    Copyright 2021-2023 Free Software Foundation, Inc.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <stdlib.h>
20 #include <assert.h>
21 #include <string.h>
22 #include <stdint.h>
23 
24 /* Return true if address P is ALIGNMENT-byte aligned.  */
25 
26 static int
27 is_aligned (void *p, size_t alignment)
28 {
29   size_t mask = (alignment - 1);
30   return ((uintptr_t)p & mask) == 0;
31 }
32 
33 /* Allocate SIZE memory with ALIGNMENT, and return it.  If FREE_POINTER,
34    return in it the corresponding pointer to be passed to free.
35 
36    Do the alignment precisely, in other words, if an alignment of 4 is
37    requested, make sure the pointer is 4-byte aligned, but not 8-byte
38    aligned.  In other words, make sure the pointer is not overaligned.
39 
40    The benefit of using precise alignment is that accidentally specifying
41    a too low alignment will not be compensated by accidental
42    overalignment.  */
43 
44 static void *
45 precise_aligned_alloc (size_t alignment, size_t size, void **free_pointer)
46 {
47   /* Allocate extra to compensate for "p += alignment".  */
48   size_t alloc_size = size + alignment;
49 
50   /* Align extra, to be able to do precise align.  */
51   void *p = aligned_alloc (alignment * 2, alloc_size);
52   assert (p != NULL);
53   void *p_orig = p;
54   void *p_end = p + alloc_size;
55 
56   /* Make p precisely aligned.  */
57   p += alignment;
58 
59   /* Verify p is without bounds, and points to large enough area.  */
60   assert (p >= p_orig);
61   assert (p + size <= p_end);
62 
63   /* Verify required alignment.  */
64   assert (is_aligned (p, alignment));
65 
66   /* Verify required alignment is precise.  */
67   assert (! is_aligned (p, 2 * alignment));
68 
69   if (free_pointer != NULL)
70     *free_pointer = p_orig;
71 
72   return p;
73 }
74 
75 /* Duplicate data SRC of size SIZE to a newly allocated, precisely aligned
76    location with alignment ALIGNMENT.  */
77 
78 static void *
79 precise_aligned_dup (size_t alignment, size_t size, void **free_pointer,
80 		     void *src)
81 {
82   void *p = precise_aligned_alloc (alignment, size, free_pointer);
83 
84   memcpy (p, src, size);
85 
86   return p;
87 }
88