about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux
diff options
context:
space:
mode:
authorcaiyinyu <caiyinyu@loongson.cn>2022-08-10 10:21:46 +0800
committercaiyinyu <caiyinyu@loongson.cn>2022-08-12 09:30:56 +0800
commit1c9bc1b6e50293a1b7037a7bfbf835868a55baed (patch)
tree33bcdaa52d913e1f09b959cba4eac20e6a11540f /sysdeps/unix/sysv/linux
parent12182ba18dabda791a4f63a11ee2e9d828f40f9b (diff)
downloadglibc-1c9bc1b6e50293a1b7037a7bfbf835868a55baed.tar.gz
glibc-1c9bc1b6e50293a1b7037a7bfbf835868a55baed.tar.xz
glibc-1c9bc1b6e50293a1b7037a7bfbf835868a55baed.zip
LoongArch: Add pointer mangling support.
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r--sysdeps/unix/sysv/linux/loongarch/sysdep.h63
1 files changed, 60 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
index 8a398adb70..157cbd6c6b 100644
--- a/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
@@ -314,8 +314,65 @@ extern long int __syscall_error (long int neg_errno);
 
 #endif /* ! __ASSEMBLER__ */
 
-/* Pointer mangling is not supported.  */
-#define PTR_MANGLE(var) (void) (var)
-#define PTR_DEMANGLE(var) (void) (var)
+/* Pointer mangling is supported for LoongArch.  */
+
+/* Load or store to/from a got-relative EXPR into/from G, using T.
+   Note G and T are register names.  */
+#define LDST_GLOBAL(OP, G, T,  EXPR) \
+  pcalau12i T, %got_pc_hi20(EXPR); \
+  OP	    T, T, %got_pc_lo12(EXPR); \
+  OP	    G, T, 0;
+
+/* Load or store to/from a pc-relative EXPR into/from G, using T.
+   Note G and T are register names.  */
+#define LDST_PCREL(OP, G, T,  EXPR) \
+  pcalau12i T, %pc_hi20(EXPR); \
+  OP	    G, T, %pc_lo12(EXPR);
+
+#if (IS_IN (rtld) \
+     || (!defined SHARED && (IS_IN (libc) \
+     || IS_IN (libpthread))))
+
+#ifdef __ASSEMBLER__
+#define PTR_MANGLE(dst, src, guard, tmp) \
+  LDST_PCREL (REG_L, guard, tmp, __pointer_chk_guard_local); \
+  PTR_MANGLE2 (dst, src, guard);
+#define PTR_DEMANGLE(dst, src, guard, tmp) \
+  LDST_PCREL (REG_L, guard, tmp, __pointer_chk_guard_local); \
+  PTR_DEMANGLE2 (dst, src, guard);
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
+#define PTR_MANGLE2(dst, src, guard) \
+  xor  dst, src, guard;
+#define PTR_DEMANGLE2(dst, src, guard) \
+  PTR_MANGLE2 (dst, src, guard);
+#else
+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
+#define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
+#define PTR_DEMANGLE(var) PTR_MANGLE (var)
+#endif
+
+#else
+
+#ifdef __ASSEMBLER__
+#define PTR_MANGLE(dst, src, guard, tmp) \
+  LDST_GLOBAL (REG_L, guard, tmp, __pointer_chk_guard); \
+  PTR_MANGLE2 (dst, src, guard);
+#define PTR_DEMANGLE(dst, src, guard, tmp) \
+  LDST_GLOBAL (REG_L, guard, tmp, __pointer_chk_guard); \
+  PTR_DEMANGLE2 (dst, src, guard);
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
+#define PTR_MANGLE2(dst, src, guard) \
+  xor dst, src, guard;
+#define PTR_DEMANGLE2(dst, src, guard) \
+  PTR_MANGLE2 (dst, src, guard);
+#else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
+#define PTR_DEMANGLE(var) PTR_MANGLE (var)
+#endif
+
+#endif
 
 #endif /* linux/loongarch/sysdep.h */