2 * Allocation wrapper for test purposes.
4 * Copyright © 2024 Nick Bowler
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 #ifndef TEST_MALLOC_HOOK
26 # define TEST_MALLOC_HOOK 1
28 #include "cdecl-internal.h"
31 static union test_alloc {
44 #define ALLOC_STATE_ALLOCATED 0x7143u
45 #define ALLOC_STATE_FREED 0xdeadu
48 * Hook for testing allocation behaviour of the library, enabling a basic
49 * verification in test cases that the library does not leak memory.
51 * The library sources must be recompiled with -DTEST_MALLOC_HOOK to
52 * make use of this functionality.
54 * In this implementation, allocated memory is never freed, instead just
55 * marked with an indication that the memory is no longer live.
57 void *test_realloc_hook(void *p, size_t n)
59 union test_alloc *old_alloc = p, *alloc;
62 old_alloc = &old_alloc[-ALLOC_PAYLOAD];
63 if (old_alloc[ALLOC_STATE].v != ALLOC_STATE_ALLOCATED) {
64 printf("Bail out! %p is not a live allocation!\n", p);
68 old_alloc[ALLOC_STATE].v = ALLOC_STATE_FREED;
69 printf("# %p freed\n", p);
75 n = (n + sizeof *alloc - 1) / sizeof *alloc;
76 alloc = malloc((n + ALLOC_PAYLOAD) * sizeof *alloc);
80 alloc[ALLOC_NEXT_PTR].p = alloc_head;
83 alloc[ALLOC_STATE].v = ALLOC_STATE_ALLOCATED;
84 alloc[ALLOC_SIZE].v = n * sizeof *alloc;
87 n = old_alloc[ALLOC_SIZE].v;
88 memcpy(&alloc[ALLOC_PAYLOAD], &old_alloc[ALLOC_PAYLOAD], n);
91 p = &alloc[ALLOC_PAYLOAD];
92 printf("# %p allocated\n", p);
97 * Returns the total number of allocations that have not yet been freed.
99 size_t test_live_allocations(void)
104 for (a = alloc_head; a; a = a[ALLOC_NEXT_PTR].p) {
105 void *p = &a[ALLOC_PAYLOAD];
107 switch (a[ALLOC_STATE].v) {
108 case ALLOC_STATE_ALLOCATED:
109 printf("# %p still live\n", p);
112 case ALLOC_STATE_FREED:
115 printf("Bail out! detected %p state corruption\n", p);
124 * Function called from output.c but not needed for error messaging
125 * (only current user of this file)
127 const char *cdecl__token_name(unsigned token)
129 printf("Bail out! stub cdecl__token_name called\n");