@@ -23,6 +23,7 @@
#include <unistd.h>
#include <array_length.h>
#include <libc-pointer-arith.h>
+#include <support/address-diff.h>
#include <support/check.h>
#include "tst-malloc-aux.h"
@@ -82,9 +83,9 @@ do_test (void)
/* This should return the same chunk as was just free'd. */
tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, sz2);
CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment);
+ TEST_VERIFY (support_address_diff (
+ tcache_allocs[i].ptr1, tcache_allocs[i].ptr2) == 0);
free (tcache_allocs[i].ptr2);
-
- TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2);
}
/* Test for non-head tcache hits. This exercises the memalign
@@ -110,7 +111,7 @@ do_test (void)
count = 0;
for (i = 0; i < 10; ++ i)
- if (ptr[i] == p)
+ if (support_address_diff (ptr[i], p) == 0)
++ count;
free (p);
TEST_VERIFY (count > 0);
@@ -146,7 +147,8 @@ do_test (void)
{
int ok = 0;
for (j = 0; j < LN; ++ j)
- if (large_allocs[i].ptr1 == large_allocs[j].ptr2)
+ if (support_address_diff (large_allocs[i].ptr1, large_allocs[j].ptr2)
+ == 0)
ok = 1;
if (ok == 1)
count ++;
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <array_length.h>
#include <libc-pointer-arith.h>
+#include <support/address-diff.h>
#include <support/check.h>
#include <support/xthread.h>
#include "tst-malloc-aux.h"
@@ -85,9 +86,9 @@ mem_test (void *closure)
/* This should return the same chunk as was just free'd. */
tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, sz2);
CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment);
+ TEST_VERIFY (support_address_diff (
+ tcache_allocs[i].ptr1, tcache_allocs[i].ptr2) == 0);
free (tcache_allocs[i].ptr2);
-
- TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2);
}
/* Test for non-head tcache hits. */
@@ -112,7 +113,7 @@ mem_test (void *closure)
count = 0;
for (i = 0; i < 10; ++ i)
- if (ptr[i] == p)
+ if (support_address_diff (ptr[i], p) == 0)
++ count;
free (p);
TEST_VERIFY (count > 0);
@@ -146,7 +147,8 @@ mem_test (void *closure)
{
int ok = 0;
for (j = 0; j < LN; ++ j)
- if (large_allocs[i].ptr1 == large_allocs[j].ptr2)
+ if (support_address_diff (large_allocs[i].ptr1, large_allocs[j].ptr2)
+ == 0)
ok = 1;
if (ok == 1)
count ++;
@@ -22,6 +22,7 @@
#include <string.h>
#include <libc-diag.h>
#include <support/check.h>
+#include <support/address-diff.h>
#include "tst-malloc-aux.h"
@@ -155,9 +156,9 @@ do_test (void)
size_t newsz = malloc_usable_size (p);
printf ("size: %zu, usable size: %zu, extra: %zu\n",
sz, newsz, newsz - sz);
- uintptr_t oldp = (uintptr_t) p;
+ void *oldp = p;
void *new_p = realloc (p, newsz);
- if ((uintptr_t) new_p != oldp)
+ if (support_address_diff (new_p, oldp) != 0)
FAIL_EXIT1 ("Expanding (%zu bytes) to usable size (%zu) moved block",
sz, newsz);
free (new_p);
@@ -254,7 +254,7 @@ libsupport-routines = \
xwrite \
# libsupport-routines
-libsupport-static-only-routines := $(libsupport-routines)
+libsupport-static-only-routines = $(libsupport-routines) $(libsupport-sysdep_routines)
# Only build one variant of the library.
libsupport-inhibit-o := .os
ifeq ($(build-shared),yes)
new file mode 100644
@@ -0,0 +1,27 @@
+/* Support functions for pointer arithmetic.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _POINTER_ARITH_H
+#define _POINTER_ARITH_H 1
+
+#include <stddef.h>
+
+/* Returns difference in bytes between addresses of two pointers. */
+ptrdiff_t support_address_diff (const void *lhs, const void *rhs);
+
+#endif /* _POINTER_ARITH_H */
@@ -90,3 +90,9 @@ endif
ifeq ($(subdir),malloc)
sysdep_malloc_debug_routines = __mtag_tag_zero_region __mtag_tag_region
endif # malloc directory
+
+ifeq ($(subdir),support)
+libsupport-sysdep_routines += \
+ support-address-diff \
+ # libsupport-sysdep_routines
+endif
new file mode 100644
@@ -0,0 +1,50 @@
+/* Support functions for pointer arithmetic for AArch64.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "address-diff.h"
+
+#include <sys/ifunc.h>
+#include <sys/auxv.h>
+#include <libc-pointer-arith.h>
+
+static ptrdiff_t
+address_diff_mte (const void *lhs, const void *rhs)
+{
+ register const void *x0 asm ("x0") = lhs;
+ register const void *x1 asm ("x1") = rhs;
+ asm (".inst 0x9ac10000 /* subp x0, x0, x1 */" : "+r" (x0) : "r" (x1));
+ return (ptrdiff_t)x0;
+}
+
+static ptrdiff_t
+address_diff_generic (const void *lhs, const void *rhs)
+{
+ return PTR_DIFF (lhs, rhs);
+}
+
+static void * __attribute__ ((unused))
+address_diff_resolver (unsigned long a0, const unsigned long *a1)
+{
+ unsigned long hwcap2 = __ifunc_hwcap (_IFUNC_ARG_AT_HWCAP2, a0, a1);
+ if (hwcap2 & HWCAP2_MTE)
+ return (void *)address_diff_mte;
+ return (void *)address_diff_generic;
+}
+
+ptrdiff_t support_address_diff (const void *lhs, const void *rhs)
+__attribute__ ((ifunc ("address_diff_resolver")));
@@ -38,3 +38,9 @@ endif
ifeq ($(subdir),misc)
sysdep_routines += malloc-hugepages
endif
+
+ifeq ($(subdir),support)
+libsupport-sysdep_routines += \
+ support-address-diff \
+ # libsupport-sysdep_routines
+endif
new file mode 100644
@@ -0,0 +1,26 @@
+/* Support functions for pointer arithmetic.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "address-diff.h"
+
+#include <libc-pointer-arith.h>
+
+ptrdiff_t support_address_diff (const void *lhs, const void *rhs)
+{
+ return PTR_DIFF (lhs, rhs);
+}