[libc-commits] [libc] draft: libc support for hexagon linux (PR #81815)

Brian Cain via libc-commits libc-commits at lists.llvm.org
Wed Feb 14 18:04:46 PST 2024


https://github.com/androm3da created https://github.com/llvm/llvm-project/pull/81815

<this PR not in a useful state for review>

>From 1d83962f70c2a28dc5c77d00cd2a099d28923469 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain at quicinc.com>
Date: Sat, 16 Sep 2023 15:21:03 -0700
Subject: [PATCH 1/4] [libc] Add support for hexagon architecture,
 hexagon-linux

The start.cpp is a WIP, might make sense to abstract some of the commonalities
among hexagon and x86_64?

The sin, cos, tan entrypoints are omitted to avoid a build error. I think we
might need a target-independent implementation of these?
---
 .../cmake/modules/LLVMLibCArchitectures.cmake |   4 +
 libc/config/linux/app.h                       |   6 +-
 libc/config/linux/hexagon/entrypoints.txt     | 543 ++++++++++++++++++
 libc/config/linux/hexagon/headers.txt         |  41 ++
 .../llvm-libc-macros/linux/signal-macros.h    |   2 +-
 libc/include/llvm-libc-types/fenv_t.h         |   2 +
 libc/include/llvm-libc-types/jmp_buf.h        |   3 +
 .../OSUtil/linux/hexagon/CMakeLists.txt       |   8 +
 .../__support/OSUtil/linux/hexagon/syscall.h  | 112 ++++
 libc/src/__support/OSUtil/linux/syscall.h     |   2 +
 libc/src/__support/RPC/rpc_util.h             |   2 +
 .../macros/properties/architectures.h         |   4 +
 libc/src/__support/macros/properties/float.h  |   3 +-
 libc/src/__support/threads/linux/thread.cpp   |   4 +-
 libc/src/__support/threads/thread.h           |   2 +
 libc/src/setjmp/hexagon/CMakeLists.txt        |  25 +
 libc/src/setjmp/hexagon/longjmp.cpp           |  37 ++
 libc/src/setjmp/hexagon/setjmp.cpp            |  36 ++
 libc/src/string/memory_utils/inline_bcmp.h    |   3 +-
 libc/src/string/memory_utils/inline_memcmp.h  |   3 +-
 libc/src/string/memory_utils/inline_memcpy.h  |   2 +-
 libc/src/string/memory_utils/inline_memmove.h |   2 +-
 libc/src/string/memory_utils/inline_memset.h  |   2 +-
 libc/startup/linux/hexagon/CMakeLists.txt     |  18 +
 libc/startup/linux/hexagon/start.cpp          | 235 ++++++++
 25 files changed, 1091 insertions(+), 10 deletions(-)
 create mode 100644 libc/config/linux/hexagon/entrypoints.txt
 create mode 100644 libc/config/linux/hexagon/headers.txt
 create mode 100644 libc/src/__support/OSUtil/linux/hexagon/CMakeLists.txt
 create mode 100644 libc/src/__support/OSUtil/linux/hexagon/syscall.h
 create mode 100644 libc/src/setjmp/hexagon/CMakeLists.txt
 create mode 100644 libc/src/setjmp/hexagon/longjmp.cpp
 create mode 100644 libc/src/setjmp/hexagon/setjmp.cpp
 create mode 100644 libc/startup/linux/hexagon/CMakeLists.txt
 create mode 100644 libc/startup/linux/hexagon/start.cpp

diff --git a/libc/cmake/modules/LLVMLibCArchitectures.cmake b/libc/cmake/modules/LLVMLibCArchitectures.cmake
index 10571101a34178..de223ce52963ed 100644
--- a/libc/cmake/modules/LLVMLibCArchitectures.cmake
+++ b/libc/cmake/modules/LLVMLibCArchitectures.cmake
@@ -59,6 +59,8 @@ function(get_arch_and_system_from_triple triple arch_var sys_var)
     set(target_arch "riscv32")
   elseif(target_arch MATCHES "^riscv64")
     set(target_arch "riscv64")
+  elseif(target_arch MATCHES "^hexagon")
+    set(target_arch "hexagon")
   else()
     return()
   endif()
@@ -156,6 +158,8 @@ elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv64")
 elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "riscv32")
   set(LIBC_TARGET_ARCHITECTURE_IS_RISCV32 TRUE)
   set(LIBC_TARGET_ARCHITECTURE "riscv")
+elseif(LIBC_TARGET_ARCHITECTURE STREQUAL "hexagon")
+  set(LIBC_TARGET_ARCHITECTURE_IS_HEXAGON TRUE)
 else()
   message(FATAL_ERROR
           "Unsupported libc target architecture ${LIBC_TARGET_ARCHITECTURE}")
diff --git a/libc/config/linux/app.h b/libc/config/linux/app.h
index b17026a7832a3c..dcbac7ed44a94f 100644
--- a/libc/config/linux/app.h
+++ b/libc/config/linux/app.h
@@ -37,11 +37,13 @@ struct TLSImage {
 
 #if defined(LIBC_TARGET_ARCH_IS_X86_64) ||                                     \
     defined(LIBC_TARGET_ARCH_IS_AARCH64) ||                                    \
-    defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
+    defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) ||                                  \
+    defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 // At the language level, argc is an int. But we use uint64_t as the x86_64
 // ABI specifies it as an 8 byte value. Likewise, in the ARM64 ABI, arguments
 // are usually passed in registers.  x0 is a doubleword register, so this is
-// 64 bit for aarch64 as well.
+// 64 bit for aarch64 as well.  For hexagon, argc is an int and uintptr_t
+// is 32-bits so the size will correspond.
 typedef uintptr_t ArgcType;
 
 // At the language level, argv is a char** value. However, we use uint64_t as
diff --git a/libc/config/linux/hexagon/entrypoints.txt b/libc/config/linux/hexagon/entrypoints.txt
new file mode 100644
index 00000000000000..053667edf6d866
--- /dev/null
+++ b/libc/config/linux/hexagon/entrypoints.txt
@@ -0,0 +1,543 @@
+set(TARGET_LIBC_ENTRYPOINTS
+    # ctype.h entrypoints
+    libc.src.ctype.isalnum
+    libc.src.ctype.isalpha
+    libc.src.ctype.isascii
+    libc.src.ctype.isblank
+    libc.src.ctype.iscntrl
+    libc.src.ctype.isdigit
+    libc.src.ctype.isgraph
+    libc.src.ctype.islower
+    libc.src.ctype.isprint
+    libc.src.ctype.ispunct
+    libc.src.ctype.isspace
+    libc.src.ctype.isupper
+    libc.src.ctype.isxdigit
+    libc.src.ctype.toascii
+    libc.src.ctype.tolower
+    libc.src.ctype.toupper
+
+    # errno.h entrypoints
+    libc.src.errno.errno
+
+    # fcntl.h entrypoints
+    libc.src.fcntl.creat
+    libc.src.fcntl.open
+    libc.src.fcntl.openat
+
+    # sched.h entrypoints
+    libc.src.sched.sched_get_priority_max
+    libc.src.sched.sched_get_priority_min
+    libc.src.sched.sched_getaffinity
+    libc.src.sched.sched_getparam
+    libc.src.sched.sched_getscheduler
+    libc.src.sched.sched_rr_get_interval
+    libc.src.sched.sched_setaffinity
+    libc.src.sched.sched_setparam
+    libc.src.sched.sched_setscheduler
+    libc.src.sched.sched_yield
+
+    # string.h entrypoints
+    libc.src.string.bcmp
+    libc.src.string.bcopy
+    libc.src.string.bzero
+    libc.src.string.index
+    libc.src.string.memccpy
+    libc.src.string.memchr
+    libc.src.string.memcmp
+    libc.src.string.memcpy
+    libc.src.string.memmem
+    libc.src.string.memmove
+    libc.src.string.mempcpy
+    libc.src.string.memrchr
+    libc.src.string.memset
+    libc.src.string.rindex
+    libc.src.string.stpcpy
+    libc.src.string.stpncpy
+    libc.src.string.strcasecmp
+    libc.src.string.strcasestr
+    libc.src.string.strcat
+    libc.src.string.strchr
+    libc.src.string.strchrnul
+    libc.src.string.strcmp
+    libc.src.string.strcoll
+    libc.src.string.strcpy
+    libc.src.string.strcspn
+    libc.src.string.strdup
+    libc.src.string.strerror
+    libc.src.string.strerror_r
+    libc.src.string.strlcat
+    libc.src.string.strlcpy
+    libc.src.string.strlen
+    libc.src.string.strncasecmp
+    libc.src.string.strncat
+    libc.src.string.strncmp
+    libc.src.string.strncpy
+    libc.src.string.strndup
+    libc.src.string.strnlen
+    libc.src.string.strpbrk
+    libc.src.string.strrchr
+    libc.src.string.strsep
+    libc.src.string.strsignal
+    libc.src.string.strspn
+    libc.src.string.strstr
+    libc.src.string.strtok
+    libc.src.string.strtok_r
+    libc.src.string.strxfrm
+
+    # inttypes.h entrypoints
+    libc.src.inttypes.imaxabs
+    libc.src.inttypes.imaxdiv
+    libc.src.inttypes.strtoimax
+    libc.src.inttypes.strtoumax
+
+    # stdlib.h entrypoints
+    libc.src.stdlib.abs
+    libc.src.stdlib.atoi
+    libc.src.stdlib.atof
+    libc.src.stdlib.atol
+    libc.src.stdlib.atoll
+    libc.src.stdlib.bsearch
+    libc.src.stdlib.div
+    libc.src.stdlib.labs
+    libc.src.stdlib.ldiv
+    libc.src.stdlib.llabs
+    libc.src.stdlib.lldiv
+    libc.src.stdlib.qsort
+    libc.src.stdlib.qsort_r
+    libc.src.stdlib.rand
+    libc.src.stdlib.srand
+    libc.src.stdlib.strtod
+    libc.src.stdlib.strtof
+    libc.src.stdlib.strtol
+    libc.src.stdlib.strtold
+    libc.src.stdlib.strtoll
+    libc.src.stdlib.strtoul
+    libc.src.stdlib.strtoull
+
+    # stdlib.h external entrypoints
+    libc.src.stdlib.malloc
+    libc.src.stdlib.calloc
+    libc.src.stdlib.realloc
+    libc.src.stdlib.aligned_alloc
+    libc.src.stdlib.free
+
+    # stdio.h entrypoints
+    libc.src.stdio.remove
+    libc.src.stdio.sprintf
+    libc.src.stdio.snprintf
+    libc.src.stdio.fprintf
+    libc.src.stdio.printf
+    libc.src.stdio.vsprintf
+    libc.src.stdio.vsnprintf
+    libc.src.stdio.vfprintf
+    libc.src.stdio.vprintf
+
+    # sys/mman.h entrypoints
+    libc.src.sys.mman.madvise
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.mprotect
+    libc.src.sys.mman.munmap
+    libc.src.sys.mman.posix_madvise
+
+    # sys/random.h entrypoints
+    libc.src.sys.random.getrandom
+
+    # sys/resource.h entrypoints
+    libc.src.sys.resource.getrlimit
+    libc.src.sys.resource.setrlimit
+
+    # sys/sendfile entrypoints
+    libc.src.sys.sendfile.sendfile
+
+    # sys/socket.h entrypoints
+    libc.src.sys.socket.socket
+
+    # sys/stat.h entrypoints
+    libc.src.sys.stat.chmod
+    libc.src.sys.stat.fchmod
+    libc.src.sys.stat.fchmodat
+    libc.src.sys.stat.fstat
+    libc.src.sys.stat.lstat
+    libc.src.sys.stat.mkdir
+    libc.src.sys.stat.mkdirat
+    libc.src.sys.stat.stat
+
+    # sys/utsname.h entrypoints
+    libc.src.sys.utsname.uname
+
+    # sys/wait.h entrypoints
+    libc.src.sys.wait.wait
+    libc.src.sys.wait.wait4
+    libc.src.sys.wait.waitpid
+
+    # termios.h entrypoints
+    libc.src.termios.cfgetispeed
+    libc.src.termios.cfgetospeed
+    libc.src.termios.cfsetispeed
+    libc.src.termios.cfsetospeed
+    libc.src.termios.tcgetattr
+    libc.src.termios.tcgetsid
+    libc.src.termios.tcdrain
+    libc.src.termios.tcflow
+    libc.src.termios.tcflush
+    libc.src.termios.tcsendbreak
+    libc.src.termios.tcsetattr
+
+    # unistd.h entrypoints
+    libc.src.unistd.access
+    libc.src.unistd.chdir
+    libc.src.unistd.close
+    libc.src.unistd.dup
+    libc.src.unistd.dup2
+    libc.src.unistd.dup3
+    libc.src.unistd.execve
+    libc.src.unistd.fchdir
+    libc.src.unistd.fsync
+    libc.src.unistd.ftruncate
+    libc.src.unistd.getcwd
+    libc.src.unistd.geteuid
+    libc.src.unistd.getpid
+    libc.src.unistd.getppid
+    libc.src.unistd.getuid
+    libc.src.unistd.isatty
+    libc.src.unistd.link
+    libc.src.unistd.linkat
+    libc.src.unistd.lseek
+    libc.src.unistd.pread
+    libc.src.unistd.pwrite
+    libc.src.unistd.read
+    libc.src.unistd.readlink
+    libc.src.unistd.readlinkat
+    libc.src.unistd.rmdir
+    libc.src.unistd.symlink
+    libc.src.unistd.symlinkat
+    libc.src.unistd.sysconf
+    libc.src.unistd.truncate
+    libc.src.unistd.unlink
+    libc.src.unistd.unlinkat
+    libc.src.unistd.write
+
+    # wchar.h entrypoints
+    libc.src.wchar.wctob
+)
+
+set(TARGET_LIBM_ENTRYPOINTS
+    # fenv.h entrypoints
+    libc.src.fenv.feclearexcept
+    libc.src.fenv.fedisableexcept
+    libc.src.fenv.feenableexcept
+    libc.src.fenv.fegetenv
+    libc.src.fenv.fegetexcept
+    libc.src.fenv.fegetexceptflag
+    libc.src.fenv.fegetround
+    libc.src.fenv.feholdexcept
+    libc.src.fenv.fesetenv
+    libc.src.fenv.fesetexceptflag
+    libc.src.fenv.fesetround
+    libc.src.fenv.feraiseexcept
+    libc.src.fenv.fetestexcept
+    libc.src.fenv.feupdateenv
+
+    # math.h entrypoints
+    libc.src.math.acosf
+    libc.src.math.acoshf
+    libc.src.math.asinf
+    libc.src.math.asinhf
+    libc.src.math.atanf
+    libc.src.math.atanhf
+    libc.src.math.copysign
+    libc.src.math.copysignf
+    libc.src.math.copysignl
+    libc.src.math.ceil
+    libc.src.math.ceilf
+    libc.src.math.ceill
+    #libc.src.math.cos FIXME
+    libc.src.math.coshf
+    libc.src.math.cosf
+    libc.src.math.erff
+    libc.src.math.exp
+    libc.src.math.expf
+    libc.src.math.exp10
+    libc.src.math.exp10f
+    libc.src.math.exp2
+    libc.src.math.exp2f
+    libc.src.math.expm1f
+    libc.src.math.fabs
+    libc.src.math.fabsf
+    libc.src.math.fabsl
+    libc.src.math.fdim
+    libc.src.math.fdimf
+    libc.src.math.fdiml
+    libc.src.math.floor
+    libc.src.math.floorf
+    libc.src.math.floorl
+    libc.src.math.fma
+    libc.src.math.fmaf
+    libc.src.math.fmin
+    libc.src.math.fminf
+    libc.src.math.fminl
+    libc.src.math.fmax
+    libc.src.math.fmaxf
+    libc.src.math.fmaxl
+    libc.src.math.fmod
+    libc.src.math.fmodf
+    libc.src.math.frexp
+    libc.src.math.frexpf
+    libc.src.math.frexpl
+    libc.src.math.hypot
+    libc.src.math.hypotf
+    libc.src.math.ilogb
+    libc.src.math.ilogbf
+    libc.src.math.ilogbl
+    libc.src.math.ldexp
+    libc.src.math.ldexpf
+    libc.src.math.ldexpl
+    libc.src.math.llrint
+    libc.src.math.llrintf
+    libc.src.math.llrintl
+    libc.src.math.llround
+    libc.src.math.llroundf
+    libc.src.math.llroundl
+    libc.src.math.log10
+    libc.src.math.log10f
+    libc.src.math.log1p
+    libc.src.math.log1pf
+    libc.src.math.log2
+    libc.src.math.log2f
+    libc.src.math.log
+    libc.src.math.logf
+    libc.src.math.logb
+    libc.src.math.logbf
+    libc.src.math.logbl
+    libc.src.math.lrint
+    libc.src.math.lrintf
+    libc.src.math.lrintl
+    libc.src.math.lround
+    libc.src.math.lroundf
+    libc.src.math.lroundl
+    libc.src.math.modf
+    libc.src.math.modff
+    libc.src.math.modfl
+    libc.src.math.nearbyint
+    libc.src.math.nearbyintf
+    libc.src.math.nearbyintl
+    libc.src.math.nextafter
+    libc.src.math.nextafterf
+    libc.src.math.nextafterl
+    libc.src.math.remainderf
+    libc.src.math.remainder
+    libc.src.math.remainderl
+    libc.src.math.remquof
+    libc.src.math.remquo
+    libc.src.math.remquol
+    libc.src.math.rint
+    libc.src.math.rintf
+    libc.src.math.rintl
+    libc.src.math.round
+    libc.src.math.roundf
+    libc.src.math.roundl
+    libc.src.math.scalbn
+    libc.src.math.scalbnf
+    libc.src.math.scalbnl
+    #libc.src.math.sin FIXME
+    libc.src.math.sincosf
+    libc.src.math.sinhf
+    libc.src.math.sinf
+    libc.src.math.sqrt
+    libc.src.math.sqrtf
+    libc.src.math.sqrtl
+    #libc.src.math.tan FIXME
+    libc.src.math.tanf
+    libc.src.math.tanhf
+    libc.src.math.trunc
+    libc.src.math.truncf
+    libc.src.math.truncl
+)
+
+if(LLVM_LIBC_FULL_BUILD)
+  list(APPEND TARGET_LIBC_ENTRYPOINTS
+    # assert.h entrypoints
+    libc.src.assert.__assert_fail
+
+    # dirent.h entrypoints
+    libc.src.dirent.closedir
+    libc.src.dirent.dirfd
+    libc.src.dirent.opendir
+    libc.src.dirent.readdir
+
+    # network.h entrypoints
+    libc.src.network.htonl
+    libc.src.network.htons
+    libc.src.network.ntohl
+    libc.src.network.ntohs
+
+    # pthread.h entrypoints
+    libc.src.pthread.pthread_atfork
+    libc.src.pthread.pthread_attr_destroy
+    libc.src.pthread.pthread_attr_init
+    libc.src.pthread.pthread_attr_getdetachstate
+    libc.src.pthread.pthread_attr_getguardsize
+    libc.src.pthread.pthread_attr_getstack
+    libc.src.pthread.pthread_attr_getstacksize
+    libc.src.pthread.pthread_attr_setdetachstate
+    libc.src.pthread.pthread_attr_setguardsize
+    libc.src.pthread.pthread_attr_setstack
+    libc.src.pthread.pthread_attr_setstacksize
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_detach
+    libc.src.pthread.pthread_equal
+    libc.src.pthread.pthread_exit
+    libc.src.pthread.pthread_getname_np
+    libc.src.pthread.pthread_getspecific
+    libc.src.pthread.pthread_join
+    libc.src.pthread.pthread_key_create
+    libc.src.pthread.pthread_key_delete
+    libc.src.pthread.pthread_self
+    libc.src.pthread.pthread_setname_np
+    libc.src.pthread.pthread_mutex_destroy
+    libc.src.pthread.pthread_mutex_init
+    libc.src.pthread.pthread_mutex_lock
+    libc.src.pthread.pthread_mutex_unlock
+    libc.src.pthread.pthread_mutexattr_destroy
+    libc.src.pthread.pthread_mutexattr_init
+    libc.src.pthread.pthread_mutexattr_getpshared
+    libc.src.pthread.pthread_mutexattr_getrobust
+    libc.src.pthread.pthread_mutexattr_gettype
+    libc.src.pthread.pthread_mutexattr_setpshared
+    libc.src.pthread.pthread_mutexattr_setrobust
+    libc.src.pthread.pthread_mutexattr_settype
+    libc.src.pthread.pthread_once
+    libc.src.pthread.pthread_setspecific
+
+    # sched.h entrypoints
+    libc.src.sched.__sched_getcpucount
+
+    # setjmp.h entrypoints
+    libc.src.setjmp.longjmp
+    libc.src.setjmp.setjmp
+
+    # stdio.h entrypoints
+    libc.src.stdio.clearerr
+    libc.src.stdio.clearerr_unlocked
+    libc.src.stdio.fclose
+    libc.src.stdio.flockfile
+    libc.src.stdio.feof
+    libc.src.stdio.feof_unlocked
+    libc.src.stdio.ferror
+    libc.src.stdio.ferror_unlocked
+    libc.src.stdio.fgetc
+    libc.src.stdio.fgetc_unlocked
+    libc.src.stdio.fgets
+    libc.src.stdio.fflush
+    libc.src.stdio.fopen
+    libc.src.stdio.fputc
+    libc.src.stdio.fputs
+    libc.src.stdio.fopencookie
+    libc.src.stdio.fread
+    libc.src.stdio.fread_unlocked
+    libc.src.stdio.fseek
+    libc.src.stdio.ftell
+    libc.src.stdio.funlockfile
+    libc.src.stdio.fwrite
+    libc.src.stdio.fwrite_unlocked
+    libc.src.stdio.getc
+    libc.src.stdio.getc_unlocked
+    libc.src.stdio.getchar
+    libc.src.stdio.getchar_unlocked
+    libc.src.stdio.sscanf
+    libc.src.stdio.scanf
+    libc.src.stdio.fscanf
+    libc.src.stdio.putc
+    libc.src.stdio.putchar
+    libc.src.stdio.puts
+    libc.src.stdio.setbuf
+    libc.src.stdio.setvbuf
+    libc.src.stdio.stderr
+    libc.src.stdio.stdin
+    libc.src.stdio.stdout
+    libc.src.stdio.ungetc
+
+    # stdlib.h entrypoints
+    libc.src.stdlib._Exit
+    libc.src.stdlib.abort
+    libc.src.stdlib.atexit
+    libc.src.stdlib.exit
+    libc.src.stdlib.getenv
+
+    # signal.h entrypoints
+    libc.src.signal.raise
+    libc.src.signal.kill
+    libc.src.signal.sigaction
+    libc.src.signal.sigaltstack
+    libc.src.signal.sigdelset
+    libc.src.signal.sigaddset
+    libc.src.signal.sigemptyset
+    libc.src.signal.sigprocmask
+    libc.src.signal.sigfillset
+    libc.src.signal.signal
+
+    # spawn.h entrypoints
+    libc.src.spawn.posix_spawn
+    libc.src.spawn.posix_spawn_file_actions_addclose
+    libc.src.spawn.posix_spawn_file_actions_adddup2
+    libc.src.spawn.posix_spawn_file_actions_addopen
+    libc.src.spawn.posix_spawn_file_actions_destroy
+    libc.src.spawn.posix_spawn_file_actions_init
+
+    # threads.h entrypoints
+    libc.src.threads.call_once
+    libc.src.threads.cnd_broadcast
+    libc.src.threads.cnd_destroy
+    libc.src.threads.cnd_init
+    libc.src.threads.cnd_signal
+    libc.src.threads.cnd_wait
+    libc.src.threads.mtx_destroy
+    libc.src.threads.mtx_init
+    libc.src.threads.mtx_lock
+    libc.src.threads.mtx_unlock
+    libc.src.threads.thrd_create
+    libc.src.threads.thrd_current
+    libc.src.threads.thrd_detach
+    libc.src.threads.thrd_equal
+    libc.src.threads.thrd_exit
+    libc.src.threads.thrd_join
+    libc.src.threads.tss_create
+    libc.src.threads.tss_delete
+    libc.src.threads.tss_get
+    libc.src.threads.tss_set
+
+    # time.h entrypoints
+    libc.src.time.asctime
+    libc.src.time.asctime_r
+    libc.src.time.clock_gettime
+    libc.src.time.clock
+    libc.src.time.difftime
+    libc.src.time.gettimeofday
+    libc.src.time.gmtime
+    libc.src.time.gmtime_r
+    libc.src.time.mktime
+    libc.src.time.nanosleep
+    libc.src.time.time
+
+    # unistd.h entrypoints
+    libc.src.unistd.environ
+    libc.src.unistd.execv
+    libc.src.unistd.fork
+    libc.src.unistd.__llvm_libc_syscall
+    libc.src.unistd.getopt
+    libc.src.unistd.optarg
+    libc.src.unistd.optind
+    libc.src.unistd.optopt
+    libc.src.unistd.opterr
+    libc.src.unistd.swab
+
+    # sys/select.h entrypoints
+    libc.src.sys.select.select
+  )
+endif()
+
+set(TARGET_LLVMLIBC_ENTRYPOINTS
+  ${TARGET_LIBC_ENTRYPOINTS}
+  ${TARGET_LIBM_ENTRYPOINTS}
+)
diff --git a/libc/config/linux/hexagon/headers.txt b/libc/config/linux/hexagon/headers.txt
new file mode 100644
index 00000000000000..aaa75a9dd08cbd
--- /dev/null
+++ b/libc/config/linux/hexagon/headers.txt
@@ -0,0 +1,41 @@
+set(TARGET_PUBLIC_HEADERS
+    libc.include.assert
+    libc.include.ctype
+    libc.include.dirent
+    libc.include.errno
+    libc.include.fcntl
+    libc.include.fenv
+    libc.include.inttypes
+    libc.include.math
+    libc.include.pthread
+    libc.include.sched
+    libc.include.signal
+    libc.include.spawn
+    libc.include.setjmp
+    libc.include.stdio
+    libc.include.stdlib
+    libc.include.string
+    libc.include.strings
+    libc.include.termios
+    libc.include.threads
+    libc.include.time
+    libc.include.unistd
+    libc.include.wchar
+
+    libc.include.arpa_inet
+
+    libc.include.sys_auxv
+    libc.include.sys_ioctl
+    libc.include.sys_mman
+    libc.include.sys_prctl
+    libc.include.sys_random
+    libc.include.sys_resource
+    libc.include.sys_select
+    libc.include.sys_socket
+    libc.include.sys_stat
+    libc.include.sys_syscall
+    libc.include.sys_time
+    libc.include.sys_types
+    libc.include.sys_utsname
+    libc.include.sys_wait
+)
diff --git a/libc/include/llvm-libc-macros/linux/signal-macros.h b/libc/include/llvm-libc-macros/linux/signal-macros.h
index deb190ec375998..1182544713f36e 100644
--- a/libc/include/llvm-libc-macros/linux/signal-macros.h
+++ b/libc/include/llvm-libc-macros/linux/signal-macros.h
@@ -82,7 +82,7 @@
 #elif defined(__aarch64__)
 #define MINSIGSTKSZ 5120
 #define SIGSTKSZ 16384
-#elif defined(__riscv)
+#elif defined(__riscv) || defined(__hexagon__)
 #define MINSIGSTKSZ 2048
 #define SIGSTKSZ 8192
 #else
diff --git a/libc/include/llvm-libc-types/fenv_t.h b/libc/include/llvm-libc-types/fenv_t.h
index 86fcf2e49a7fff..6b096e23378aa1 100644
--- a/libc/include/llvm-libc-types/fenv_t.h
+++ b/libc/include/llvm-libc-types/fenv_t.h
@@ -25,6 +25,8 @@ typedef struct {
 } fenv_t;
 #elif defined(__riscv)
 typedef unsigned int fenv_t;
+#elif defined(__hexagon__)
+typedef unsigned int fenv_t;
 #elif defined(__AMDGPU__) || defined(__NVPTX__)
 typedef struct {
   unsigned int __fpc;
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index 6af4e8ebad92ca..f619759de3e81d 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -32,6 +32,9 @@ typedef struct {
 #elif defined(__riscv_float_abi_single)
 #error "__jmp_buf not available for your target architecture."
 #endif
+#elif defined(__hexagon__)
+  /* Callee-saved registers.  */
+  long int __regs[16];
 #else
 #error "__jmp_buf not available for your target architecture."
 #endif
diff --git a/libc/src/__support/OSUtil/linux/hexagon/CMakeLists.txt b/libc/src/__support/OSUtil/linux/hexagon/CMakeLists.txt
new file mode 100644
index 00000000000000..e2988d33cec2f6
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/hexagon/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_header_library(
+  linux_hexagon_util
+  HDRS
+    syscall.h
+  DEPENDS
+    libc.src.__support.common
+)
+
diff --git a/libc/src/__support/OSUtil/linux/hexagon/syscall.h b/libc/src/__support/OSUtil/linux/hexagon/syscall.h
new file mode 100644
index 00000000000000..3f1a609c8c6acc
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/hexagon/syscall.h
@@ -0,0 +1,112 @@
+//===--------- inline implementation of hexagon syscalls ----------* C++ *-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_HEXAGON_SYSCALL_H
+#define LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_HEXAGON_SYSCALL_H
+
+#include "src/__support/common.h"
+
+#define REGISTER_DECL_0                                                        \
+  register long r6 __asm__("r6") = number;                                     \
+  register long r0 __asm__("r0");
+#define REGISTER_DECL_1                                                        \
+  register long r6 __asm__("r6") = number;                                     \
+  register long r0 __asm__("r0") = arg1;
+#define REGISTER_DECL_2                                                        \
+  REGISTER_DECL_1                                                              \
+  register long r1 __asm__("r1") = arg2;
+#define REGISTER_DECL_3                                                        \
+  REGISTER_DECL_2                                                              \
+  register long r2 __asm__("r2") = arg3;
+#define REGISTER_DECL_4                                                        \
+  REGISTER_DECL_3                                                              \
+  register long r3 __asm__("r3") = arg4;
+#define REGISTER_DECL_5                                                        \
+  REGISTER_DECL_4                                                              \
+  register long r4 __asm__("r4") = arg5;
+#define REGISTER_DECL_6                                                        \
+  REGISTER_DECL_5                                                              \
+  register long r5 __asm__("r5") = arg6;
+
+#define REGISTER_CONSTRAINT_0 "r"(r6)
+#define REGISTER_CONSTRAINT_1 REGISTER_CONSTRAINT_0, "r"(r0)
+#define REGISTER_CONSTRAINT_2 REGISTER_CONSTRAINT_1, "r"(r1)
+#define REGISTER_CONSTRAINT_3 REGISTER_CONSTRAINT_2, "r"(r2)
+#define REGISTER_CONSTRAINT_4 REGISTER_CONSTRAINT_3, "r"(r3)
+#define REGISTER_CONSTRAINT_5 REGISTER_CONSTRAINT_4, "r"(r4)
+#define REGISTER_CONSTRAINT_6 REGISTER_CONSTRAINT_5, "r"(r5)
+
+#define SYSCALL_INSTR(input_constraint)                                        \
+  LIBC_INLINE_ASM("trap0(#1)" : "=r"(r0) : input_constraint : "memory", "cc")
+
+namespace LIBC_NAMESPACE {
+
+LIBC_INLINE long syscall_impl(long number) {
+  REGISTER_DECL_0;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_0);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1) {
+  REGISTER_DECL_1;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_1);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1, long arg2) {
+  REGISTER_DECL_2;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_2);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1, long arg2, long arg3) {
+  REGISTER_DECL_3;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_3);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1, long arg2, long arg3,
+                              long arg4) {
+  REGISTER_DECL_4;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_4);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1, long arg2, long arg3,
+                              long arg4, long arg5) {
+  REGISTER_DECL_5;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_5);
+  return r0;
+}
+
+LIBC_INLINE long syscall_impl(long number, long arg1, long arg2, long arg3,
+                              long arg4, long arg5, long arg6) {
+  REGISTER_DECL_6;
+  SYSCALL_INSTR(REGISTER_CONSTRAINT_6);
+  return r0;
+}
+
+} // namespace LIBC_NAMESPACE
+
+#undef REGISTER_DECL_0
+#undef REGISTER_DECL_1
+#undef REGISTER_DECL_2
+#undef REGISTER_DECL_3
+#undef REGISTER_DECL_4
+#undef REGISTER_DECL_5
+#undef REGISTER_DECL_6
+
+#undef REGISTER_CONSTRAINT_0
+#undef REGISTER_CONSTRAINT_1
+#undef REGISTER_CONSTRAINT_2
+#undef REGISTER_CONSTRAINT_3
+#undef REGISTER_CONSTRAINT_4
+#undef REGISTER_CONSTRAINT_5
+#undef REGISTER_CONSTRAINT_6
+
+#endif // LLVM_LIBC_SRC_SUPPORT_OSUTIL_LINUX_HEXAGON_SYSCALL_H
diff --git a/libc/src/__support/OSUtil/linux/syscall.h b/libc/src/__support/OSUtil/linux/syscall.h
index 2be3cefa906af1..e03b9144ad7004 100644
--- a/libc/src/__support/OSUtil/linux/syscall.h
+++ b/libc/src/__support/OSUtil/linux/syscall.h
@@ -21,6 +21,8 @@
 #include "arm/syscall.h"
 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
 #include "riscv/syscall.h"
+#elif defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+#include "hexagon/syscall.h"
 #endif
 
 namespace LIBC_NAMESPACE {
diff --git a/libc/src/__support/RPC/rpc_util.h b/libc/src/__support/RPC/rpc_util.h
index 04620b0487f4ad..9c6b38daed5a30 100644
--- a/libc/src/__support/RPC/rpc_util.h
+++ b/libc/src/__support/RPC/rpc_util.h
@@ -27,6 +27,8 @@ LIBC_INLINE void sleep_briefly() {
   __builtin_amdgcn_s_sleep(2);
 #elif defined(LIBC_TARGET_ARCH_IS_X86)
   __builtin_ia32_pause();
+#elif defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+  LIBC_INLINE_ASM("pause(#255)");
 #else
   // Simply do nothing if sleeping isn't supported on this platform.
 #endif
diff --git a/libc/src/__support/macros/properties/architectures.h b/libc/src/__support/macros/properties/architectures.h
index c88956ff41148e..7284ed71d637fd 100644
--- a/libc/src/__support/macros/properties/architectures.h
+++ b/libc/src/__support/macros/properties/architectures.h
@@ -61,4 +61,8 @@
 #define LIBC_TARGET_ARCH_IS_ANY_RISCV
 #endif
 
+#if defined(__hexagon__)
+#define LIBC_TARGET_ARCH_IS_HEXAGON
+#endif
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_ARCHITECTURES_H
diff --git a/libc/src/__support/macros/properties/float.h b/libc/src/__support/macros/properties/float.h
index c40ca6120e4753..8585dcdefaaa02 100644
--- a/libc/src/__support/macros/properties/float.h
+++ b/libc/src/__support/macros/properties/float.h
@@ -18,11 +18,12 @@
 // https://developer.arm.com/documentation/dui0491/i/C-and-C---Implementation-Details/Basic-data-types
 // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
 // https://docs.amd.com/bundle/HIP-Programming-Guide-v5.1/page/Programming_with_HIP.html
+// https://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf
 #if defined(LIBC_TARGET_OS_IS_WINDOWS) ||                                      \
     (defined(LIBC_TARGET_OS_IS_MACOS) &&                                       \
      defined(LIBC_TARGET_ARCH_IS_AARCH64)) ||                                  \
     defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_NVPTX) ||  \
-    defined(LIBC_TARGET_ARCH_IS_AMDGPU)
+    defined(LIBC_TARGET_ARCH_IS_AMDGPU) || defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #define LONG_DOUBLE_IS_DOUBLE
 #endif
 
diff --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index 5c84266ee5d0ed..025f2f663c1bdf 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -61,6 +61,8 @@ static constexpr unsigned CLONE_SYSCALL_FLAGS =
 #define CLONE_RESULT_REGISTER "t0"
 #elif defined(LIBC_TARGET_ARCH_IS_X86_64)
 #define CLONE_RESULT_REGISTER "rax"
+#elif defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+#define CLONE_RESULT_REGISTER "r0"
 #else
 #error "CLONE_RESULT_REGISTER not defined for your target architecture"
 #endif
@@ -297,7 +299,7 @@ int Thread::run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
   // Also, we want the result of the syscall to be in a register as the child
   // thread gets a completely different stack after it is created. The stack
   // variables from this function will not be availalbe to the child thread.
-#if defined(LIBC_TARGET_ARCH_IS_X86_64)
+#if defined(LIBC_TARGET_ARCH_IS_X86_64) || defined(LIBC_TARGET_ARCH_IS_HEXAGON)
   long register clone_result asm(CLONE_RESULT_REGISTER);
   clone_result = LIBC_NAMESPACE::syscall_impl<long>(
       SYS_clone, CLONE_SYSCALL_FLAGS, adjusted_stack,
diff --git a/libc/src/__support/threads/thread.h b/libc/src/__support/threads/thread.h
index acfe33879f8783..42132941be4f35 100644
--- a/libc/src/__support/threads/thread.h
+++ b/libc/src/__support/threads/thread.h
@@ -43,6 +43,8 @@ union ThreadReturnValue {
      defined(LIBC_TARGET_ARCH_IS_X86_64) ||                                    \
      defined(LIBC_TARGET_ARCH_IS_ANY_RISCV))
 constexpr unsigned int STACK_ALIGNMENT = 16;
+#elif defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+constexpr unsigned int STACK_ALIGNMENT = 8;
 #endif
 // TODO: Provide stack alignment requirements for other architectures.
 
diff --git a/libc/src/setjmp/hexagon/CMakeLists.txt b/libc/src/setjmp/hexagon/CMakeLists.txt
new file mode 100644
index 00000000000000..8c6c8e204abd77
--- /dev/null
+++ b/libc/src/setjmp/hexagon/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_entrypoint_object(
+  setjmp
+  SRCS
+    setjmp.cpp
+  HDRS
+    ../setjmp_impl.h
+  DEPENDS
+    libc.include.setjmp
+  COMPILE_OPTIONS
+    -O3
+    -fomit-frame-pointer
+)
+
+add_entrypoint_object(
+  longjmp
+  SRCS
+    longjmp.cpp
+  HDRS
+    ../longjmp.h
+  DEPENDS
+    libc.include.setjmp
+  COMPILE_OPTIONS
+    -O3
+    -fomit-frame-pointer
+)
diff --git a/libc/src/setjmp/hexagon/longjmp.cpp b/libc/src/setjmp/hexagon/longjmp.cpp
new file mode 100644
index 00000000000000..ee334553155103
--- /dev/null
+++ b/libc/src/setjmp/hexagon/longjmp.cpp
@@ -0,0 +1,37 @@
+//===-- Hexagon implementation of longjmp ---------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/setjmp/longjmp.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/properties/architectures.h"
+
+#include <setjmp.h>
+
+#if !defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+#error "Invalid file include"
+#endif
+
+#define LOAD(reg, val) LIBC_INLINE_ASM(#reg " = memd(%0)\n\t" : : "r"(&val) :)
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
+  LOAD(r17:16, buf->__regs[0]);
+  LOAD(r19:18, buf->__regs[2]);
+  LOAD(r21:20, buf->__regs[4]);
+  LOAD(r23:22, buf->__regs[6]);
+  LOAD(r25:24, buf->__regs[8]);
+  LOAD(r27:26, buf->__regs[10]);
+  LOAD(r29:28, buf->__regs[12]);
+  LOAD(r31:30, buf->__regs[14]);
+
+  val = val == 0 ? 1 : val;
+  LIBC_INLINE_ASM("r0 = %0\n\t" : : "r"(val) :);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/setjmp/hexagon/setjmp.cpp b/libc/src/setjmp/hexagon/setjmp.cpp
new file mode 100644
index 00000000000000..5c936f29f7ed5d
--- /dev/null
+++ b/libc/src/setjmp/hexagon/setjmp.cpp
@@ -0,0 +1,36 @@
+//===-- Hexagon implementation of setjmp ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/common.h"
+#include "src/setjmp/setjmp_impl.h"
+
+#include <setjmp.h>
+
+#if !defined(LIBC_TARGET_ARCH_IS_HEXAGON)
+#error "Invalid file include"
+#endif
+
+#define STORE(reg, val)                                                        \
+  LIBC_INLINE_ASM("memd(%0) = " #reg "\n\t" : : "r"(&val) :)
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
+  STORE(r17:16, buf->__regs[0]);
+  STORE(r19:18, buf->__regs[2]);
+  STORE(r21:20, buf->__regs[4]);
+  STORE(r23:22, buf->__regs[6]);
+  STORE(r25:24, buf->__regs[8]);
+  STORE(r27:26, buf->__regs[10]);
+  STORE(r29:28, buf->__regs[12]);
+  STORE(r31:30, buf->__regs[14]);
+
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/string/memory_utils/inline_bcmp.h b/libc/src/string/memory_utils/inline_bcmp.h
index b1c981d859e022..49479ba17a6546 100644
--- a/libc/src/string/memory_utils/inline_bcmp.h
+++ b/libc/src/string/memory_utils/inline_bcmp.h
@@ -23,7 +23,8 @@
 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
 #include "src/string/memory_utils/riscv/inline_bcmp.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_BCMP inline_bcmp_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_GPU)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_GPU) ||  \
+    defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #include "src/string/memory_utils/generic/byte_per_byte.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_BCMP inline_bcmp_byte_per_byte
 #else
diff --git a/libc/src/string/memory_utils/inline_memcmp.h b/libc/src/string/memory_utils/inline_memcmp.h
index d88d43691daee8..e3421fb9b61dbc 100644
--- a/libc/src/string/memory_utils/inline_memcmp.h
+++ b/libc/src/string/memory_utils/inline_memcmp.h
@@ -24,7 +24,8 @@
 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
 #include "src/string/memory_utils/riscv/inline_memcmp.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP inline_memcmp_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_GPU)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_GPU) ||  \
+    defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #include "src/string/memory_utils/generic/byte_per_byte.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP inline_memcmp_byte_per_byte
 #else
diff --git a/libc/src/string/memory_utils/inline_memcpy.h b/libc/src/string/memory_utils/inline_memcpy.h
index a92bf4ddf881d5..75710d7c360455 100644
--- a/libc/src/string/memory_utils/inline_memcpy.h
+++ b/libc/src/string/memory_utils/inline_memcpy.h
@@ -28,7 +28,7 @@
 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
 #include "src/string/memory_utils/riscv/inline_memcpy.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY inline_memcpy_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_ARM)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #include "src/string/memory_utils/generic/byte_per_byte.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMCPY inline_memcpy_byte_per_byte
 #elif defined(LIBC_TARGET_ARCH_IS_GPU)
diff --git a/libc/src/string/memory_utils/inline_memmove.h b/libc/src/string/memory_utils/inline_memmove.h
index 30c2c3ddbf1bb7..753ffc09c77736 100644
--- a/libc/src/string/memory_utils/inline_memmove.h
+++ b/libc/src/string/memory_utils/inline_memmove.h
@@ -27,7 +27,7 @@
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_SMALL_SIZE                        \
   inline_memmove_no_small_size
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_FOLLOW_UP inline_memmove_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_ARM)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #include "src/string/memory_utils/generic/byte_per_byte.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMMOVE_SMALL_SIZE                        \
   inline_memmove_no_small_size
diff --git a/libc/src/string/memory_utils/inline_memset.h b/libc/src/string/memory_utils/inline_memset.h
index 1c07c1ca4bffc0..4d7b01479c421a 100644
--- a/libc/src/string/memory_utils/inline_memset.h
+++ b/libc/src/string/memory_utils/inline_memset.h
@@ -24,7 +24,7 @@
 #elif defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
 #include "src/string/memory_utils/riscv/inline_memset.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_riscv
-#elif defined(LIBC_TARGET_ARCH_IS_ARM)
+#elif defined(LIBC_TARGET_ARCH_IS_ARM) || defined(LIBC_TARGET_ARCH_IS_HEXAGON)
 #include "src/string/memory_utils/generic/byte_per_byte.h"
 #define LIBC_SRC_STRING_MEMORY_UTILS_MEMSET inline_memset_byte_per_byte
 #elif defined(LIBC_TARGET_ARCH_IS_GPU)
diff --git a/libc/startup/linux/hexagon/CMakeLists.txt b/libc/startup/linux/hexagon/CMakeLists.txt
new file mode 100644
index 00000000000000..b47db8eb5d23f3
--- /dev/null
+++ b/libc/startup/linux/hexagon/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_startup_object(
+  crt1
+  SRC
+    start.cpp
+  DEPENDS
+    libc.config.linux.app_h
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.__support.threads.thread
+    libc.src.__support.OSUtil.osutil
+    libc.src.stdlib.exit
+    libc.src.stdlib.atexit
+    libc.src.string.memory_utils.inline_memcpy
+    libc.src.unistd.environ
+  COMPILE_OPTIONS
+    -fno-omit-frame-pointer
+    -ffreestanding # To avoid compiler warnings about calling the main function.
+)
diff --git a/libc/startup/linux/hexagon/start.cpp b/libc/startup/linux/hexagon/start.cpp
new file mode 100644
index 00000000000000..14c6164b860568
--- /dev/null
+++ b/libc/startup/linux/hexagon/start.cpp
@@ -0,0 +1,235 @@
+//===-- Implementation of crt for hexagon
+//----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "config/linux/app.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/threads/thread.h"
+#include "src/stdlib/atexit.h"
+#include "src/stdlib/exit.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+
+#include <linux/auxvec.h>
+#include <linux/elf.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+extern "C" int main(int, char **, char **);
+
+namespace LIBC_NAMESPACE {
+
+#ifdef SYS_mmap2
+static constexpr long mmapSyscallNumber = SYS_mmap2;
+#elif SYS_mmap
+static constexpr long mmapSyscallNumber = SYS_mmap;
+#else
+#error "mmap and mmap2 syscalls not available."
+#endif
+
+AppProperties app;
+
+static ThreadAttributes main_thread_attrib;
+
+// TODO: The function is hexagon specific. Move it to config/linux/app.h
+// and generalize it. Also, dynamic loading is not handled currently.
+void init_tls(TLSDescriptor &tls_descriptor) {
+  if (app.tls.size == 0) {
+    tls_descriptor.size = 0;
+    tls_descriptor.tp = 0;
+    return;
+  }
+
+  // We will assume the alignment is always a power of two.
+  uintptr_t tlsSize = app.tls.size & -app.tls.align;
+  if (tlsSize != app.tls.size)
+    tlsSize += app.tls.align;
+
+  // Per the hexagon ABI, the entry pointed to by the thread pointer is the
+  // address of the TLS block. So, we add more size to accomodate this address
+  // entry.
+  uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t);
+
+  // We cannot call the mmap function here as the functions set errno on
+  // failure. Since errno is implemented via a thread local variable, we cannot
+  // use errno before TLS is setup.
+  long mmapRetVal = LIBC_NAMESPACE::syscall_impl<long>(
+      mmapSyscallNumber, nullptr, tlsSizeWithAddr, PROT_READ | PROT_WRITE,
+      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  // We cannot check the return value with MAP_FAILED as that is the return
+  // of the mmap function and not the mmap syscall.
+  if (mmapRetVal < 0 && static_cast<uintptr_t>(mmapRetVal) > -app.pageSize)
+    LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, 1);
+  uintptr_t *tlsAddr = reinterpret_cast<uintptr_t *>(mmapRetVal);
+
+  // hexagon TLS faces down from the thread pointer with the first entry
+  // pointing to the address of the first real TLS byte.
+  uintptr_t endPtr = reinterpret_cast<uintptr_t>(tlsAddr) + tlsSize;
+  *reinterpret_cast<uintptr_t *>(endPtr) = endPtr;
+
+  LIBC_NAMESPACE::inline_memcpy(reinterpret_cast<char *>(tlsAddr),
+                                reinterpret_cast<const char *>(app.tls.address),
+                                app.tls.init_size);
+
+  tls_descriptor = {tlsSizeWithAddr, uintptr_t(tlsAddr), endPtr};
+  return;
+}
+
+void cleanup_tls(uintptr_t addr, uintptr_t size) {
+  if (size == 0)
+    return;
+  LIBC_NAMESPACE::syscall_impl<long>(SYS_munmap, addr, size);
+}
+
+// Sets the thread pointer to |val|. Returns true on success, false on failure.
+static void set_thread_ptr(uintptr_t val) {
+  LIBC_INLINE_ASM("ugp = %0" : "=r"(val));
+}
+
+using InitCallback = void(int, char **, char **);
+using FiniCallback = void(void);
+
+extern "C" {
+// These arrays are present in the .init_array and .fini_array sections.
+// The symbols are inserted by linker when it sees references to them.
+extern uintptr_t __preinit_array_start[];
+extern uintptr_t __preinit_array_end[];
+extern uintptr_t __init_array_start[];
+extern uintptr_t __init_array_end[];
+extern uintptr_t __fini_array_start[];
+extern uintptr_t __fini_array_end[];
+}
+
+static void call_init_array_callbacks(int argc, char **argv, char **env) {
+  size_t preinit_array_size = __preinit_array_end - __preinit_array_start;
+  for (size_t i = 0; i < preinit_array_size; ++i)
+    reinterpret_cast<InitCallback *>(__preinit_array_start[i])(argc, argv, env);
+  size_t init_array_size = __init_array_end - __init_array_start;
+  for (size_t i = 0; i < init_array_size; ++i)
+    reinterpret_cast<InitCallback *>(__init_array_start[i])(argc, argv, env);
+}
+
+static void call_fini_array_callbacks() {
+  size_t fini_array_size = __fini_array_end - __fini_array_start;
+  for (size_t i = fini_array_size; i > 0; --i)
+    reinterpret_cast<FiniCallback *>(__fini_array_start[i - 1])();
+}
+
+} // namespace LIBC_NAMESPACE
+
+using LIBC_NAMESPACE::app;
+
+// TODO: Would be nice to use the aux entry structure from elf.h when available.
+struct AuxEntry {
+  uint64_t type;
+  uint64_t value;
+};
+
+extern "C" void _start() {
+#if 0
+  // This TU is compiled with -fno-omit-frame-pointer. Hence, the previous value
+  // of the base pointer is pushed on to the stack. So, we step over it (the
+  // "+ 1" below) to get to the args.
+  app.args = reinterpret_cast<LIBC_NAMESPACE::Args *>(
+      reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)) + 1);
+
+  // The hexagon ABI requires that the stack pointer is aligned to a 8-byte
+  // boundary. We align it here but we cannot use any local variables created
+  // before the following alignment. Best would be to not create any local
+  // variables before the alignment. Also, note that we are aligning the stack
+  // downwards as the hexagon stack grows downwards. This ensures that we don't
+  // tread on argc, argv etc.
+  // NOTE: Compiler attributes for alignment do not help here as the stack
+  // pointer on entry to this _start function is controlled by the OS. In fact,
+  // compilers can generate code assuming the alignment as required by the ABI.
+  // If the stack pointers as setup by the OS are already aligned, then the
+  // following code is a NOP.
+  __asm__ __volatile__("nop\n\t");
+
+  auto tid = LIBC_NAMESPACE::syscall_impl<long>(SYS_gettid);
+  if (tid <= 0)
+    LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, 1);
+  LIBC_NAMESPACE::main_thread_attrib.tid = static_cast<int>(tid);
+
+  // After the argv array, is a 8-byte long NULL value before the array of env
+  // values. The end of the env values is marked by another 8-byte long NULL
+  // value. We step over it (the "+ 1" below) to get to the env values.
+  uint32_t *env_ptr = app.args->argv + app.args->argc + 1;
+  uint32_t *env_end_marker = env_ptr;
+  app.envPtr = env_ptr;
+  while (*env_end_marker)
+    ++env_end_marker;
+
+  // Initialize the POSIX global declared in unistd.h
+  environ = reinterpret_cast<char **>(env_ptr);
+
+  // After the env array, is the aux-vector. The end of the aux-vector is
+  // denoted by an AT_NULL entry.
+  Elf64_Phdr *programHdrTable = nullptr;
+  uintptr_t programHdrCount;
+  for (AuxEntry *aux_entry = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
+       aux_entry->type != AT_NULL; ++aux_entry) {
+    switch (aux_entry->type) {
+    case AT_PHDR:
+      programHdrTable = reinterpret_cast<Elf64_Phdr *>(aux_entry->value);
+      break;
+    case AT_PHNUM:
+      programHdrCount = aux_entry->value;
+      break;
+    case AT_PAGESZ:
+      app.pageSize = aux_entry->value;
+      break;
+    default:
+      break; // TODO: Read other useful entries from the aux vector.
+    }
+  }
+
+  app.tls.size = 0;
+  for (uintptr_t i = 0; i < programHdrCount; ++i) {
+    Elf64_Phdr *phdr = programHdrTable + i;
+    if (phdr->p_type != PT_TLS)
+      continue;
+    // TODO: p_vaddr value has to be adjusted for static-pie executables.
+    app.tls.address = phdr->p_vaddr;
+    app.tls.size = phdr->p_memsz;
+    app.tls.init_size = phdr->p_filesz;
+    app.tls.align = phdr->p_align;
+  }
+
+  LIBC_NAMESPACE::TLSDescriptor tls;
+  LIBC_NAMESPACE::init_tls(tls);
+  if (tls.size != 0)
+    LIBC_NAMESPACE::set_thread_ptr(tls.tp);
+
+  LIBC_NAMESPACE::self.attrib = &LIBC_NAMESPACE::main_thread_attrib;
+  LIBC_NAMESPACE::main_thread_attrib.atexit_callback_mgr =
+      LIBC_NAMESPACE::internal::get_thread_atexit_callback_mgr();
+
+  // We want the fini array callbacks to be run after other atexit
+  // callbacks are run. So, we register them before running the init
+  // array callbacks as they can potentially register their own atexit
+  // callbacks.
+  LIBC_NAMESPACE::atexit(&LIBC_NAMESPACE::call_fini_array_callbacks);
+
+  LIBC_NAMESPACE::call_init_array_callbacks(
+      static_cast<int>(app.args->argc),
+      reinterpret_cast<char **>(app.args->argv),
+      reinterpret_cast<char **>(env_ptr));
+
+  int retval = main(static_cast<int>(app.args->argc),
+                    reinterpret_cast<char **>(app.args->argv),
+                    reinterpret_cast<char **>(env_ptr));
+
+  // TODO: TLS cleanup should be done after all other atexit callbacks
+  // are run. So, register a cleanup callback for it with atexit before
+  // everything else.
+  LIBC_NAMESPACE::cleanup_tls(tls.addr, tls.size);
+  LIBC_NAMESPACE::exit(retval);
+#endif
+}

>From 0f5b4b41fb43a94a5e4363cee5671d38eff16c96 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain at quicinc.com>
Date: Fri, 20 Oct 2023 19:09:41 -0700
Subject: [PATCH 2/4] hacks to make tests build/pass - DO NOT MERGE

These are all useful for making the build / tests pass but need some official
resolution.

* explicit CMAKE_CROSSCOMPILING_EMULATOR - normally this shouldn't be required
* missing `wint_t` typedef.  known/outstanding issue https://github.com/llvm/llvm-project/issues/63510 ?
* workaround for missing `-nolibc` in the toolchain
* adjust timeouts for LibcDeathTestExecutors - test under emulation takes longer
---
 libc/CMakeLists.txt                           | 5 +++++
 libc/cmake/modules/LLVMLibCTestRules.cmake    | 9 ++++++---
 libc/include/llvm-libc-types/wint_t.h         | 4 ++++
 libc/test/UnitTest/LibcDeathTestExecutors.cpp | 8 ++++----
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 9c82db754b5f73..b3107b95d396fc 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -269,6 +269,11 @@ if(LLVM_LIBC_ENABLE_LINTING)
   endif()
 endif()
 
+if(LIBC_TARGET_ARCHITECTURE STREQUAL "hexagon")
+    add_compile_options(-mlong-calls)
+endif()
+
+
 option(LLVM_LIBC_INCLUDE_SCUDO "Include the SCUDO standalone as the allocator for LLVM libc" OFF)
 if(LLVM_LIBC_INCLUDE_SCUDO)
   if (NOT ("compiler-rt" IN_LIST LLVM_ENABLE_PROJECTS OR "compiler-rt" IN_LIST LLVM_ENABLE_RUNTIMES))
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 6cae0859149d54..45647106d19c4b 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -212,7 +212,7 @@ function(create_libc_unittest fq_target_name)
   if(NOT LIBC_UNITTEST_NO_RUN_POSTBUILD)
     add_custom_target(
       ${fq_target_name}
-      COMMAND ${fq_build_target_name}
+      COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} ${fq_build_target_name}
       COMMENT "Running unit test ${fq_target_name}"
     )
   endif()
@@ -538,9 +538,12 @@ function(add_integration_test test_name)
 
   if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
     target_link_options(${fq_build_target_name} PRIVATE -nostdlib -static)
+  elseif(LIBC_TARGET_ARCHITECTURE_IS_HEXAGON)
+    target_link_options(${fq_build_target_name} PRIVATE -nostdlib -static -lclang_rt.builtins-hexagon)
   else()
     target_link_options(${fq_build_target_name} PRIVATE -nolibc -nostartfiles -nostdlib++ -static)
   endif()
+
   target_link_libraries(
     ${fq_build_target_name}
     # The NVIDIA 'nvlink' linker does not currently support static libraries.
@@ -571,7 +574,7 @@ function(add_integration_test test_name)
       $<TARGET_FILE:${fq_build_target_name}> ${INTEGRATION_TEST_ARGS})
   add_custom_target(
     ${fq_target_name}
-    COMMAND ${test_cmd}
+    COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} ${test_cmd}
     COMMAND_EXPAND_LISTS
     COMMENT "Running integration test ${fq_target_name}"
   )
@@ -737,7 +740,7 @@ function(add_libc_hermetic_test test_name)
       $<TARGET_FILE:${fq_build_target_name}> ${HERMETIC_TEST_ARGS})
   add_custom_target(
     ${fq_target_name}
-    COMMAND ${test_cmd}
+    COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} ${test_cmd}
     COMMAND_EXPAND_LISTS
     COMMENT "Running hermetic test ${fq_target_name}"
     ${LIBC_HERMETIC_TEST_JOB_POOL}
diff --git a/libc/include/llvm-libc-types/wint_t.h b/libc/include/llvm-libc-types/wint_t.h
index cf6ccd7e1ae765..abfa6103941561 100644
--- a/libc/include/llvm-libc-types/wint_t.h
+++ b/libc/include/llvm-libc-types/wint_t.h
@@ -12,6 +12,10 @@
 // Since __need_wint_t is defined, we get the definition of wint_t from the
 // standalone C header stddef.h. Also, because __need_wint_t is defined,
 // including stddef.h will pull only the type wint_t and nothing else.
+#if defined(__hexagon__)
+typedef int wint_t;
+#endif
+
 #define __need_wint_t
 #include <stddef.h>
 #undef __need_wint_t
diff --git a/libc/test/UnitTest/LibcDeathTestExecutors.cpp b/libc/test/UnitTest/LibcDeathTestExecutors.cpp
index e891c4e3c0b586..4deff4614987eb 100644
--- a/libc/test/UnitTest/LibcDeathTestExecutors.cpp
+++ b/libc/test/UnitTest/LibcDeathTestExecutors.cpp
@@ -19,7 +19,7 @@ namespace testing {
 bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
                              const char *LHSStr, const char *RHSStr,
                              internal::Location Loc) {
-  testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
+  testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 5000);
 
   if (const char *error = Result.get_error()) {
     Ctx->markFail();
@@ -31,7 +31,7 @@ bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
   if (Result.timed_out()) {
     Ctx->markFail();
     tlog << Loc;
-    tlog << "Process timed out after " << 500 << " milliseconds.\n";
+    tlog << "Process timed out after " << 5000 << " milliseconds.\n";
     return false;
   }
 
@@ -62,7 +62,7 @@ bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
 bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
                             const char *LHSStr, const char *RHSStr,
                             internal::Location Loc) {
-  testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
+  testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 5000);
 
   if (const char *error = Result.get_error()) {
     Ctx->markFail();
@@ -74,7 +74,7 @@ bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
   if (Result.timed_out()) {
     Ctx->markFail();
     tlog << Loc;
-    tlog << "Process timed out after " << 500 << " milliseconds.\n";
+    tlog << "Process timed out after " << 5000 << " milliseconds.\n";
     return false;
   }
 

>From 5566d88cadfb8317ec68798a355e63383b21cc73 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain at quicinc.com>
Date: Fri, 24 Nov 2023 19:06:22 -0800
Subject: [PATCH 3/4] Fix "undeclared identifier" error

This change is required to fix this error:

    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/stdio/printf_core/converter.cpp:9:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/stdio/printf_core/converter.h:12:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/stdio/printf_core/core_structs.h:13:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/__support/FPUtil/FPBits.h:17:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/__support/FPUtil/FloatProperties.h:12:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/__support/UInt128.h:12:
    In file included from /local/mnt/workspace/upstream/llvm-project/libc/src/__support/UInt.h:17:
    /local/mnt/workspace/upstream/llvm-project/libc/src/__support/integer_utils.h:51:13: error: use of undeclared identifier 'add_with_carry'
       51 |   auto r1 = add_with_carry(prod.lo, lo_hi.lo << 32, uint64_t(0));
          |             ^
    /local/mnt/workspace/upstream/llvm-project/libc/src/__support/integer_utils.h:55:13: error: use of undeclared identifier 'add_with_carry'
       55 |   auto r2 = add_with_carry(prod.lo, hi_lo.lo << 32, uint64_t(0));
          |             ^
---
 libc/src/__support/integer_utils.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libc/src/__support/integer_utils.h b/libc/src/__support/integer_utils.h
index 433e99227bcfd4..661318f03bfd31 100644
--- a/libc/src/__support/integer_utils.h
+++ b/libc/src/__support/integer_utils.h
@@ -13,6 +13,7 @@
 #include "src/__support/common.h"
 
 #include "bit.h"
+#include "math_extras.h"
 #include "number_pair.h"
 
 #include <stdint.h>

>From 1343ea126775d77ad97223b2b86aae0dab6c8ac8 Mon Sep 17 00:00:00 2001
From: Brian Cain <bcain at quicinc.com>
Date: Fri, 22 Sep 2023 10:19:56 -0700
Subject: [PATCH 4/4] fixes for startup

---
 libc/startup/linux/hexagon/start.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/libc/startup/linux/hexagon/start.cpp b/libc/startup/linux/hexagon/start.cpp
index 14c6164b860568..b913dd404d7baf 100644
--- a/libc/startup/linux/hexagon/start.cpp
+++ b/libc/startup/linux/hexagon/start.cpp
@@ -127,12 +127,12 @@ using LIBC_NAMESPACE::app;
 
 // TODO: Would be nice to use the aux entry structure from elf.h when available.
 struct AuxEntry {
-  uint64_t type;
-  uint64_t value;
+  uint32_t type;
+  uint32_t value;
 };
 
 extern "C" void _start() {
-#if 0
+#if 1
   // This TU is compiled with -fno-omit-frame-pointer. Hence, the previous value
   // of the base pointer is pushed on to the stack. So, we step over it (the
   // "+ 1" below) to get to the args.
@@ -150,7 +150,7 @@ extern "C" void _start() {
   // compilers can generate code assuming the alignment as required by the ABI.
   // If the stack pointers as setup by the OS are already aligned, then the
   // following code is a NOP.
-  __asm__ __volatile__("nop\n\t");
+  LIBC_INLINE_ASM("r29 = and(r29, #0xfffffff8)\n\t" :::);
 
   auto tid = LIBC_NAMESPACE::syscall_impl<long>(SYS_gettid);
   if (tid <= 0)
@@ -171,13 +171,13 @@ extern "C" void _start() {
 
   // After the env array, is the aux-vector. The end of the aux-vector is
   // denoted by an AT_NULL entry.
-  Elf64_Phdr *programHdrTable = nullptr;
+  Elf32_Phdr *programHdrTable = nullptr;
   uintptr_t programHdrCount;
   for (AuxEntry *aux_entry = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
        aux_entry->type != AT_NULL; ++aux_entry) {
     switch (aux_entry->type) {
     case AT_PHDR:
-      programHdrTable = reinterpret_cast<Elf64_Phdr *>(aux_entry->value);
+      programHdrTable = reinterpret_cast<Elf32_Phdr *>(aux_entry->value);
       break;
     case AT_PHNUM:
       programHdrCount = aux_entry->value;
@@ -192,7 +192,7 @@ extern "C" void _start() {
 
   app.tls.size = 0;
   for (uintptr_t i = 0; i < programHdrCount; ++i) {
-    Elf64_Phdr *phdr = programHdrTable + i;
+    Elf32_Phdr *phdr = programHdrTable + i;
     if (phdr->p_type != PT_TLS)
       continue;
     // TODO: p_vaddr value has to be adjusted for static-pie executables.



More information about the libc-commits mailing list