Index: gcc-12-12.2.0/src/libsanitizer/configure.tgt
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/configure.tgt
+++ gcc-12-12.2.0/src/libsanitizer/configure.tgt
@@ -72,6 +72,8 @@ case "${target}" in
 	;;
   riscv64-*-linux*)
 	;;
+  x86_64-*-gnu* | i?86-*-gnu*)
+	;;
   *)
 	UNSUPPORTED=1
 	;;
Index: gcc-12-12.2.0/src/libsanitizer/ubsan/ubsan_platform.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/ubsan/ubsan_platform.h
+++ gcc-12-12.2.0/src/libsanitizer/ubsan/ubsan_platform.h
@@ -17,7 +17,7 @@
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||        \
     defined(__NetBSD__) || defined(__DragonFly__) ||                           \
     (defined(__sun__) && defined(__svr4__)) || defined(_WIN32) ||              \
-    defined(__Fuchsia__)
+    defined(__Fuchsia__) || defined(__GNU__)
 #define CAN_SANITIZE_UB 1
 #else
 # define CAN_SANITIZE_UB 0
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_platform.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -14,7 +14,7 @@
 
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) &&     \
-    !(defined(__sun__) && defined(__svr4__))
+    !(defined(__sun__) && defined(__svr4__)) && !defined(__GNU__)
 #  error "This operating system is not supported"
 #endif
 
@@ -116,9 +116,15 @@
 # define SANITIZER_FUCHSIA 0
 #endif
 
+#if defined(__GNU__)
+# define SANITIZER_HURD 1
+#else
+# define SANITIZER_HURD 0
+#endif
+
 #define SANITIZER_POSIX \
   (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
-    SANITIZER_NETBSD || SANITIZER_SOLARIS)
+    SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HURD)
 
 #if __LP64__ || defined(_WIN64)
 #  define SANITIZER_WORDSIZE 64
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_errno.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_errno.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_errno.cpp
@@ -20,10 +20,10 @@
 
 namespace __sanitizer {
 
-COMPILER_CHECK(errno_ENOMEM == ENOMEM);
-COMPILER_CHECK(errno_EBUSY == EBUSY);
-COMPILER_CHECK(errno_EINVAL == EINVAL);
-
+extern const int errno_ENOMEM = ENOMEM;
+extern const int errno_EBUSY = EBUSY;
+extern const int errno_EINVAL = EINVAL;
+extern const int errno_ENAMETOOLONG = ENAMETOOLONG;
 // EOWNERDEAD is not present in some older platforms.
 #if defined(EOWNERDEAD)
 extern const int errno_EOWNERDEAD = EOWNERDEAD;
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_errno_codes.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_errno_codes.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_errno_codes.h
@@ -21,12 +21,11 @@
 
 namespace __sanitizer {
 
-#define errno_ENOMEM 12
-#define errno_EBUSY 16
-#define errno_EINVAL 22
-#define errno_ENAMETOOLONG 36
-
 // Those might not present or their value differ on different platforms.
+extern const int errno_ENOMEM;
+extern const int errno_EBUSY;
+extern const int errno_EINVAL;
+extern const int errno_ENAMETOOLONG;
 extern const int errno_EOWNERDEAD;
 
 }  // namespace __sanitizer
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -14,7 +14,7 @@
 #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
 #define SANITIZER_PLATFORM_LIMITS_POSIX_H
 
-#if SANITIZER_LINUX || SANITIZER_MAC
+#if SANITIZER_LINUX || SANITIZER_MAC || SANITIZER_HURD
 
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform.h"
@@ -190,11 +190,13 @@ struct __sanitizer_struct_mallinfo {
 };
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_HURD
 struct __sanitizer_struct_mallinfo {
   int v[10];
 };
+#endif
 
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned struct_ustat_sz;
 extern unsigned struct_rlimit64_sz;
 extern unsigned struct_statvfs64_sz;
@@ -293,6 +295,32 @@ struct __sanitizer_shmid_ds {
 };
 #endif
 
+#if SANITIZER_HURD
+struct __sanitizer_ipc_perm {
+  int __key;
+  unsigned short uid;
+  unsigned short gid;
+  unsigned short cuid;
+  unsigned short cgid;
+  unsigned short mode;
+  unsigned short __seq;
+};
+
+struct __sanitizer_shmid_ds {
+  __sanitizer_ipc_perm shm_perm;
+  uptr shm_segsz;
+  long shm_atime;
+  long shm_dtime;
+  long shm_ctime;
+  short int shm_cpid;
+  short int shm_lpid;
+  unsigned short shm_nattch;
+  unsigned short __shm_npages;
+  uptr __shm_pages;
+  uptr __attaches;
+};
+#endif
+
 #if SANITIZER_LINUX && !SANITIZER_ANDROID
 extern unsigned struct_msqid_ds_sz;
 extern unsigned struct_mq_attr_sz;
@@ -328,7 +356,7 @@ typedef unsigned long __sanitizer_pthrea
 typedef unsigned __sanitizer_pthread_key_t;
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_HURD
 
 struct __sanitizer_XDR {
   int x_op;
@@ -485,6 +513,12 @@ struct __sanitizer_dirent {
   unsigned short d_reclen;
   // more fields that we don't care about
 };
+#  elif SANITIZER_HURD
+struct __sanitizer_dirent {
+  uptr d_ino;
+  unsigned short d_reclen;
+  // more fields that we don't care about
+};
 #  else
 struct __sanitizer_dirent {
   uptr d_ino;
@@ -509,7 +543,7 @@ typedef long long __sanitizer_clock_t;
 typedef long __sanitizer_clock_t;
 #endif
 
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX || SANITIZER_HURD
 typedef int __sanitizer_clockid_t;
 #endif
 
@@ -557,6 +591,8 @@ typedef unsigned long __sanitizer_sigset
 # endif
 #elif SANITIZER_MAC
 typedef unsigned __sanitizer_sigset_t;
+#elif SANITIZER_HURD
+typedef unsigned long __sanitizer_sigset_t;
 #elif SANITIZER_LINUX
 struct __sanitizer_sigset_t {
   // The size is determined by looking at sizeof of real sigset_t on linux.
@@ -760,7 +796,7 @@ typedef unsigned long __sanitizer_nfds_t
 #endif
 
 #if !SANITIZER_ANDROID
-# if SANITIZER_LINUX
+# if SANITIZER_LINUX || SANITIZER_HURD
 struct __sanitizer_glob_t {
   uptr gl_pathc;
   char **gl_pathv;
@@ -775,7 +811,7 @@ struct __sanitizer_glob_t {
 };
 # endif  // SANITIZER_LINUX
 
-# if SANITIZER_LINUX
+# if SANITIZER_LINUX || SANITIZER_HURD
 extern int glob_nomatch;
 extern int glob_altdirfunc;
 # endif
@@ -793,7 +829,7 @@ struct __sanitizer_wordexp_t {
   uptr we_offs;
 };
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_HURD
 struct __sanitizer_FILE {
   int _flags;
   char *_IO_read_ptr;
@@ -874,7 +910,7 @@ struct __sanitizer_ifconf {
 };
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_HURD
 struct __sanitizer__obstack_chunk {
   char *limit;
   struct __sanitizer__obstack_chunk *prev;
Index: gcc-12-12.2.0/src/libsanitizer/interception/interception.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/interception/interception.h
+++ gcc-12-12.2.0/src/libsanitizer/interception/interception.h
@@ -18,7 +18,7 @@
 
 #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC &&      \
     !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
-    !SANITIZER_SOLARIS
+    !SANITIZER_SOLARIS && !SANITIZER_HURD
 #  error "Interception doesn't work on this operating system."
 #endif
 
@@ -272,7 +272,7 @@ typedef unsigned long uptr;
 #define INCLUDED_FROM_INTERCEPTION_LIB
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 
 # include "interception_linux.h"
 # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
Index: gcc-12-12.2.0/src/libsanitizer/interception/interception_linux.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/interception/interception_linux.h
+++ gcc-12-12.2.0/src/libsanitizer/interception/interception_linux.h
@@ -12,7 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 
 #if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
 # error "interception_linux.h should be included from interception library only"
@@ -50,4 +50,4 @@ bool InterceptFunction(const char *name,
 
 #endif  // INTERCEPTION_LINUX_H
 #endif  // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
-        // SANITIZER_SOLARIS
+        // SANITIZER_SOLARIS || SANITIZER_HURD
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_posix.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_posix.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_posix.cpp
@@ -27,7 +27,7 @@
 #include <signal.h>
 #include <sys/mman.h>
 
-#if SANITIZER_FREEBSD
+#if SANITIZER_FREEBSD || SANITIZER_HURD
 // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
 // that, it was never implemented.  So just define it to zero.
 #undef  MAP_NORESERVE
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -36,7 +36,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#if SANITIZER_FREEBSD
+#if SANITIZER_FREEBSD || SANITIZER_HURD
 // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
 // that, it was never implemented.  So just define it to zero.
 #undef MAP_NORESERVE
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -368,7 +368,7 @@ static void ioctl_table_fill() {
   _(VT_WAITACTIVE, NONE, 0);
 #endif
 
-#if SANITIZER_GLIBC
+#if SANITIZER_GLIBC && !SANITIZER_HURD
   // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
   _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
   _(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
Index: gcc-12-12.2.0/src/libsanitizer/interception/interception_linux.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/interception/interception_linux.cpp
+++ gcc-12-12.2.0/src/libsanitizer/interception/interception_linux.cpp
@@ -14,7 +14,7 @@
 #include "interception.h"
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 
 #include <dlfcn.h>   // for dlsym() and dlvsym()
 
@@ -80,4 +80,4 @@ bool InterceptFunction(const char *name,
 }  // namespace __interception
 
 #endif  // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
-        // SANITIZER_SOLARIS
+        // SANITIZER_SOLARIS || SANITIZER_HURD
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -126,6 +126,12 @@
 #define SI_SOLARIS32 0
 #endif
 
+#if SANITIZER_HURD
+#define SI_HURD 1
+#else
+#define SI_HURD 0
+#endif
+
 #if SANITIZER_POSIX && !SANITIZER_MAC
 #define SI_POSIX_NOT_MAC 1
 #else
@@ -317,7 +323,7 @@
 #define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS
 #define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS
 #define SANITIZER_INTERCEPT_SIGSETOPS \
-  (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+  (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS || SI_HURD)
 #define SANITIZER_INTERCEPT_SIGSET_LOGICOPS SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_SIGPENDING SI_POSIX
 #define SANITIZER_INTERCEPT_SIGPROCMASK SI_POSIX
@@ -527,7 +533,7 @@
 #define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_TTYENT (SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_TTYENTPATH SI_NETBSD
-#define SANITIZER_INTERCEPT_PROTOENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_PROTOENT (SI_LINUX || SI_NETBSD || SI_FREEBSD || SI_HURD)
 #define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC
 #define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
 #define SANITIZER_INTERCEPT_SETVBUF \
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_symbolizer_report.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_symbolizer_report.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_symbolizer_report.cpp
@@ -126,7 +126,7 @@ void ReportMmapWriteExec(int prot, int f
 #endif
 }
 
-#if !SANITIZER_FUCHSIA && !SANITIZER_GO
+#if !SANITIZER_FUCHSIA && !SANITIZER_GO && !SANITIZER_HURD
 void StartReportDeadlySignal() {
   // Write the first message using fd=2, just in case.
   // It may actually fail to write in case stderr is closed.
@@ -254,7 +254,7 @@ void HandleDeadlySignal(void *siginfo, v
   Die();
 }
 
-#endif  // !SANITIZER_FUCHSIA && !SANITIZER_GO
+#endif  // !SANITIZER_FUCHSIA && !SANITIZER_GO && !SANITIZER_HURD
 
 atomic_uintptr_t ScopedErrorReportLock::reporting_thread_ = {0};
 StaticSpinMutex ScopedErrorReportLock::mutex_;
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -23,7 +23,7 @@
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_platform.h"
 
-#if SANITIZER_LINUX || SANITIZER_MAC
+#if SANITIZER_LINUX || SANITIZER_MAC || SANITIZER_HURD
 // Must go after undef _FILE_OFFSET_BITS.
 #include "sanitizer_glibc_version.h"
 
@@ -59,8 +59,11 @@
 #include <net/route.h>
 #endif
 
-#if !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID && !SANITIZER_HURD
 #include <sys/mount.h>
+#endif
+
+#if !SANITIZER_ANDROID
 #include <sys/timeb.h>
 #include <utmpx.h>
 #endif
@@ -165,6 +168,17 @@ typedef struct user_fpregs elf_fpregset_
 #include <fstab.h>
 #endif // SANITIZER_LINUX
 
+#if SANITIZER_HURD
+#include <sys/statfs.h>
+#include <glob.h>
+#include <sys/ioctl.h>
+#include <net/ethernet.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <malloc.h>
+#include <obstack.h>
+#endif
+
 #if SANITIZER_MAC
 #include <net/ethernet.h>
 #include <sys/filio.h>
@@ -405,7 +419,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(El
 #endif // PTRACE_GETREGSET/PTRACE_SETREGSET
 #endif
 
+#if !SANITIZER_HURD
   unsigned path_max = PATH_MAX;
+#endif
 
   // ioctl arguments
   unsigned struct_ifreq_sz = sizeof(struct ifreq);
@@ -464,7 +480,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(El
   unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
 #endif // SANITIZER_LINUX
 
-#if SANITIZER_GLIBC
+#if SANITIZER_LINUX && SANITIZER_GLIBC
   unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
 #if EV_VERSION > (0x010000)
   unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry);
@@ -489,9 +505,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(El
 
   unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
   unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
-#endif  // SANITIZER_GLIBC
+#endif  // SANITIZER_LINUX && SANITIZER_GLIBC
 
-#if !SANITIZER_ANDROID && !SANITIZER_MAC
+#if !SANITIZER_ANDROID && !SANITIZER_MAC && !SANITIZER_HURD
   unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
   unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
 #endif
@@ -506,9 +522,13 @@ unsigned struct_ElfW_Phdr_sz = sizeof(El
   unsigned IOCTL_FIONBIO = FIONBIO;
   unsigned IOCTL_FIONCLEX = FIONCLEX;
   unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+#if !SANITIZER_HURD
   unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+#endif
   unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+#if !SANITIZER_HURD
   unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+#endif
   unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
   unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
   unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
@@ -1044,7 +1064,7 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent
 CHECK_SIZE_AND_OFFSET(dirent, d_ino);
 #if SANITIZER_MAC
 CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
-#elif SANITIZER_FREEBSD
+#elif SANITIZER_FREEBSD or SANITIZER_HURD
 // There is no 'd_off' field on FreeBSD.
 #else
 CHECK_SIZE_AND_OFFSET(dirent, d_off);
@@ -1180,7 +1200,7 @@ CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next)
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
 CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
-#if SANITIZER_LINUX || SANITIZER_FREEBSD
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_HURD
 // Compare against the union, because we can't reach into the union in a
 // compliant way.
 #ifdef ifa_dstaddr
@@ -1292,4 +1312,4 @@ CHECK_TYPE_SIZE(sem_t);
 COMPILER_CHECK(ARM_VFPREGS_SIZE == ARM_VFPREGS_SIZE_ASAN);
 #endif
 
-#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_HURD
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -14,7 +14,7 @@
 #include "sanitizer_platform.h"
 
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 
 #include "sanitizer_allocator_internal.h"
 #include "sanitizer_atomic.h"
@@ -49,6 +49,9 @@
 #include <osreldate.h>
 #include <sys/sysctl.h>
 #define pthread_getattr_np pthread_attr_get_np
+#endif
+
+#if SANITIZER_FREEBSD | SANITIZER_HURD
 // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
 // that, it was never implemented. So just define it to zero.
 #undef MAP_NORESERVE
@@ -216,7 +219,7 @@ void InitTlsSize() { }
 // On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
 // of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
 // to get the pointer to thread-specific data keys in the thread control block.
-#if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !SANITIZER_ANDROID
+#if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_HURD) && !SANITIZER_ANDROID
 // sizeof(struct pthread) from glibc.
 static atomic_uintptr_t thread_descriptor_size;
 
@@ -446,7 +449,7 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE void
                                                                       void **);
 #endif
 
-#if !SANITIZER_GO
+#if !SANITIZER_GO && !SANITIZER_HURD
 static void GetTls(uptr *addr, uptr *size) {
 #if SANITIZER_ANDROID
   if (&__libc_get_static_tls_bounds) {
@@ -482,7 +485,7 @@ static void GetTls(uptr *addr, uptr *siz
   const uptr pre_tcb_size = TlsPreTcbSize();
   *addr = tp - pre_tcb_size;
   *size = g_tls_size + pre_tcb_size;
-#elif SANITIZER_FREEBSD || SANITIZER_LINUX
+#elif SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_HURD
   uptr align;
   GetStaticTlsBoundary(addr, size, &align);
 #if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \
@@ -568,7 +571,7 @@ uptr GetTlsSize() {
 
 void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                           uptr *tls_addr, uptr *tls_size) {
-#if SANITIZER_GO
+#if SANITIZER_GO || SANITIZER_HURD
   // Stub implementation for Go.
   *stk_addr = *stk_size = *tls_addr = *tls_size = 0;
 #else
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
@@ -12,7 +12,7 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 #include "sanitizer_common.h"
 #include "sanitizer_stacktrace.h"
 
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_linux.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_linux.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_linux.h
@@ -14,7 +14,7 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||                \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
 #include "sanitizer_platform_limits_freebsd.h"
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_procmaps.h
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_procmaps.h
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_procmaps.h
@@ -17,7 +17,7 @@
 
 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
     SANITIZER_MAC || SANITIZER_SOLARIS ||  \
-    SANITIZER_FUCHSIA
+    SANITIZER_FUCHSIA || SANITIZER_HURD
 
 #include "sanitizer_common.h"
 #include "sanitizer_internal_defs.h"
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/Makefile.am
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/Makefile.am
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/Makefile.am
@@ -35,6 +35,7 @@ sanitizer_common_files = \
 	sanitizer_file.cpp \
 	sanitizer_flags.cpp \
 	sanitizer_flag_parser.cpp \
+	sanitizer_hurd.cpp \
 	sanitizer_libc.cpp \
 	sanitizer_libignore.cpp \
 	sanitizer_linux.cpp \
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_hurd.cpp
===================================================================
--- /dev/null
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_hurd.cpp
@@ -0,0 +1,312 @@
+//===-- sanitizer_hurd.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements Hurd-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_HURD
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_posix.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_procmaps.h"
+
+extern "C" {
+#include <mach.h>
+#include <mach/gnumach.h>
+}
+
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+namespace __sanitizer {
+
+#include "sanitizer_syscall_generic.inc"
+
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+                   u64 offset) {
+  return (uptr) mmap(addr, length, prot, flags, fd, offset);
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+  return munmap(addr, length);
+}
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+  return mprotect(addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+  return madvise((void*) addr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+  return close(fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+  return open(filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+  return open(filename, flags, mode);
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+  return read(fd, buf, count);
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+  if (fd == 2) {
+    char buf2[count+1];
+    internal_memcpy(buf2, buf, count);
+    buf2[count] = 0;
+    mach_print(buf2);
+  }
+  return write(fd, buf, count);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+  return fstat(fd, (struct stat*) buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+  struct stat st;
+  if (internal_fstat(fd, &st))
+    return -1;
+  return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+  return dup(oldfd);
+}
+uptr internal_dup2(int oldfd, int newfd) {
+  return dup2(oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+  return readlink(path, buf, bufsize);
+}
+
+uptr internal_sched_yield() {
+  swtch ();
+  return 0;
+}
+
+void internal__exit(int exitcode) {
+  _exit(exitcode);
+  task_terminate (mach_task_self ());
+  Die();  // Unreachable.
+}
+
+int internal_fork() {
+  return fork();
+}
+
+void internal_usleep(u64 useconds) {
+  usleep(useconds);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+                     char *const envp[]) {
+  return execve(filename, argv, envp);
+}
+
+extern "C" char *netfs_server_name __attribute__((weak));
+static bool IsProcFS(void) {
+  return &netfs_server_name && netfs_server_name && !internal_strcmp(netfs_server_name, "procfs");
+}
+
+uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
+  const char *default_module_name = "/proc/self/exe";
+  uptr module_name_len;
+  int readlink_error;
+  bool IsErr;
+
+  if (IsProcFS())
+    /* We are /proc, we cannot read ourself, but we know who we are */
+    return internal_snprintf(buf, buf_len, "procfs");
+
+  module_name_len = internal_readlink(default_module_name, buf, buf_len);
+  IsErr = internal_iserror(module_name_len, &readlink_error);
+  if (IsErr) {
+    // We can't read binary name for some reason, assume it's unknown.
+    Report("WARNING: reading executable name failed with errno %d, "
+           "some stack frames may not be symbolized\n", readlink_error);
+    module_name_len = internal_snprintf(buf, buf_len, "%s",
+                                        default_module_name);
+    CHECK_LT(module_name_len, buf_len);
+  }
+  return module_name_len;
+}
+
+uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
+  char *tmpbuf;
+  uptr tmpsize;
+  uptr tmplen;
+
+  if (IsProcFS())
+    /* We are /proc, we cannot read ourself, but we know who we are */
+    return internal_snprintf(buf, buf_len, "/hurd/procfs");
+
+  if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,
+                       1024 * 1024)) {
+    internal_strncpy(buf, tmpbuf, buf_len);
+    UnmapOrDie(tmpbuf, tmpsize);
+    return internal_strlen(buf);
+  }
+  return ReadBinaryName(buf, buf_len);
+}
+
+bool FileExists(const char *filename) {
+  if (ShouldMockFailureToOpen(filename))
+    return false;
+  struct stat st;
+  if (stat(filename, &st))
+    return false;
+  // Sanity check: filename is a regular file.
+  return S_ISREG(st.st_mode);
+}
+
+tid_t GetTid() {
+  return (tid_t) mach_thread_self();
+}
+
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+  return clock_gettime(clk_id, (struct timespec *) tp);
+}
+
+const char *GetEnv(const char *name) {
+  return NULL;
+}
+
+static void ReadNullSepFileToArray(const char *path, char ***arr,
+                                   int arr_size) {
+  char *buff;
+  uptr buff_size;
+  uptr buff_len;
+  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
+  if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
+    (*arr)[0] = nullptr;
+    return;
+  }
+  (*arr)[0] = buff;
+  int count, i;
+  for (count = 1, i = 1; ; i++) {
+    if (buff[i] == 0) {
+      if (buff[i+1] == 0) break;
+      (*arr)[count] = &buff[i+1];
+      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
+      count++;
+    }
+  }
+  (*arr)[count] = nullptr;
+}
+
+static void GetArgsAndEnv(char ***argv, char ***envp) {
+  static const int kMaxArgv = 2000, kMaxEnvp = 2000;
+
+  if (IsProcFS()) {
+    /* We are /proc, we cannot read ourself, but we know who we are */
+    char *procfs = (char *)MmapOrDie(7, "procfs");
+    internal_memcpy(procfs, "procfs", 7);
+    *argv = (char **)MmapOrDie(2 * sizeof(char *), "GetArgsAndEnv");
+    (*argv)[0] = procfs;
+    (*argv)[1] = nullptr;
+    *envp = (char **)MmapOrDie(1 * sizeof(char *), "GetArgsAndEnv");
+    (*argv)[0] = nullptr;
+    return;
+  }
+
+  ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
+  ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
+}
+
+char **GetArgv() {
+  char **argv, **envp;
+  GetArgsAndEnv(&argv, &envp);
+  return argv;
+}
+
+char **GetEnviron() {
+  char **argv, **envp;
+  GetArgsAndEnv(&argv, &envp);
+  return envp;
+}
+
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+  gsync_wait(mach_task_self(), (vm_address_t) p, cmp, 0, 0, 0);
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {
+  gsync_wake(mach_task_self(), (vm_address_t) p, 0, 0);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+  return waitpid(pid, status, options);
+}
+
+uptr internal_getpid() {
+  return getpid();
+}
+
+uptr GetPageSize() {
+  return EXEC_PAGESIZE;
+}
+
+static HandleSignalMode GetHandleSignalModeImpl(int signum) {
+  switch (signum) {
+    case SIGABRT:
+      return common_flags()->handle_abort;
+    case SIGILL:
+      return common_flags()->handle_sigill;
+    case SIGTRAP:
+      return common_flags()->handle_sigtrap;
+    case SIGFPE:
+      return common_flags()->handle_sigfpe;
+    case SIGSEGV:
+      return common_flags()->handle_segv;
+    case SIGBUS:
+      return common_flags()->handle_sigbus;
+  }
+  return kHandleSignalNo;
+}
+
+HandleSignalMode GetHandleSignalMode(int signum) {
+  HandleSignalMode result = GetHandleSignalModeImpl(signum);
+  if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
+    return kHandleSignalExclusive;
+  return result;
+}
+
+void InitializePlatformEarly() {
+  // Do nothing.
+}
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
+  // TODO: use vminfo
+}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+  // TODO: use vminfo
+  return false;
+}
+
+} // namespace __sanitizer
+
+#endif
Index: gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_procmaps_common.cpp
===================================================================
--- gcc-12-12.2.0.orig/src/libsanitizer/sanitizer_common/sanitizer_procmaps_common.cpp
+++ gcc-12-12.2.0/src/libsanitizer/sanitizer_common/sanitizer_procmaps_common.cpp
@@ -12,7 +12,7 @@
 #include "sanitizer_platform.h"
 
 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||                \
-    SANITIZER_SOLARIS
+    SANITIZER_SOLARIS || SANITIZER_HURD
 
 #include "sanitizer_common.h"
 #include "sanitizer_placement_new.h"
