[v6,04/13] LoongArch: ABI Implementation

Message ID 20220708065255.2316410-5-caiyinyu@loongson.cn
State Superseded
Headers
Series GLIBC LoongArch PATCHES |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

caiyinyu July 8, 2022, 6:52 a.m. UTC
  ---
 sysdeps/loongarch/__longjmp.S                |  52 ++++
 sysdeps/loongarch/bits/endianness.h          |  11 +
 sysdeps/loongarch/bits/link.h                |  58 ++++
 sysdeps/loongarch/bits/setjmp.h              |  42 +++
 sysdeps/loongarch/bsd-_setjmp.c              |   1 +
 sysdeps/loongarch/bsd-setjmp.c               |   1 +
 sysdeps/loongarch/dl-machine.h               | 287 +++++++++++++++++++
 sysdeps/loongarch/dl-trampoline.S            |  91 ++++++
 sysdeps/loongarch/jmpbuf-offsets.h           |  22 ++
 sysdeps/loongarch/jmpbuf-unwind.h            |  45 +++
 sysdeps/loongarch/ldsodefs.h                 |  41 +++
 sysdeps/loongarch/linkmap.h                  |  22 ++
 sysdeps/loongarch/machine-gmon.h             |  37 +++
 sysdeps/loongarch/setjmp.S                   |  66 +++++
 sysdeps/loongarch/sotruss-lib.c              |  50 ++++
 sysdeps/loongarch/start.S                    |  66 +++++
 sysdeps/loongarch/sys/asm.h                  |  59 ++++
 sysdeps/loongarch/tst-audit.h                |  23 ++
 sysdeps/unix/sysv/linux/loongarch/ldconfig.h |  26 ++
 19 files changed, 1000 insertions(+)
 create mode 100644 sysdeps/loongarch/__longjmp.S
 create mode 100644 sysdeps/loongarch/bits/endianness.h
 create mode 100644 sysdeps/loongarch/bits/link.h
 create mode 100644 sysdeps/loongarch/bits/setjmp.h
 create mode 100644 sysdeps/loongarch/bsd-_setjmp.c
 create mode 100644 sysdeps/loongarch/bsd-setjmp.c
 create mode 100644 sysdeps/loongarch/dl-machine.h
 create mode 100644 sysdeps/loongarch/dl-trampoline.S
 create mode 100644 sysdeps/loongarch/jmpbuf-offsets.h
 create mode 100644 sysdeps/loongarch/jmpbuf-unwind.h
 create mode 100644 sysdeps/loongarch/ldsodefs.h
 create mode 100644 sysdeps/loongarch/linkmap.h
 create mode 100644 sysdeps/loongarch/machine-gmon.h
 create mode 100644 sysdeps/loongarch/setjmp.S
 create mode 100644 sysdeps/loongarch/sotruss-lib.c
 create mode 100644 sysdeps/loongarch/start.S
 create mode 100644 sysdeps/loongarch/sys/asm.h
 create mode 100644 sysdeps/loongarch/tst-audit.h
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldconfig.h
  

Comments

Adhemerval Zanella Netto July 12, 2022, 8:39 p.m. UTC | #1
On 08/07/22 03:52, caiyinyu wrote:
> ---
>   sysdeps/loongarch/__longjmp.S                |  52 ++++
>   sysdeps/loongarch/bits/endianness.h          |  11 +
>   sysdeps/loongarch/bits/link.h                |  58 ++++
>   sysdeps/loongarch/bits/setjmp.h              |  42 +++
>   sysdeps/loongarch/bsd-_setjmp.c              |   1 +
>   sysdeps/loongarch/bsd-setjmp.c               |   1 +
>   sysdeps/loongarch/dl-machine.h               | 287 +++++++++++++++++++
>   sysdeps/loongarch/dl-trampoline.S            |  91 ++++++
>   sysdeps/loongarch/jmpbuf-offsets.h           |  22 ++
>   sysdeps/loongarch/jmpbuf-unwind.h            |  45 +++
>   sysdeps/loongarch/ldsodefs.h                 |  41 +++
>   sysdeps/loongarch/linkmap.h                  |  22 ++
>   sysdeps/loongarch/machine-gmon.h             |  37 +++
>   sysdeps/loongarch/setjmp.S                   |  66 +++++
>   sysdeps/loongarch/sotruss-lib.c              |  50 ++++
>   sysdeps/loongarch/start.S                    |  66 +++++
>   sysdeps/loongarch/sys/asm.h                  |  59 ++++
>   sysdeps/loongarch/tst-audit.h                |  23 ++
>   sysdeps/unix/sysv/linux/loongarch/ldconfig.h |  26 ++
>   19 files changed, 1000 insertions(+)
>   create mode 100644 sysdeps/loongarch/__longjmp.S
>   create mode 100644 sysdeps/loongarch/bits/endianness.h
>   create mode 100644 sysdeps/loongarch/bits/link.h
>   create mode 100644 sysdeps/loongarch/bits/setjmp.h
>   create mode 100644 sysdeps/loongarch/bsd-_setjmp.c
>   create mode 100644 sysdeps/loongarch/bsd-setjmp.c
>   create mode 100644 sysdeps/loongarch/dl-machine.h
>   create mode 100644 sysdeps/loongarch/dl-trampoline.S
>   create mode 100644 sysdeps/loongarch/jmpbuf-offsets.h
>   create mode 100644 sysdeps/loongarch/jmpbuf-unwind.h
>   create mode 100644 sysdeps/loongarch/ldsodefs.h
>   create mode 100644 sysdeps/loongarch/linkmap.h
>   create mode 100644 sysdeps/loongarch/machine-gmon.h
>   create mode 100644 sysdeps/loongarch/setjmp.S
>   create mode 100644 sysdeps/loongarch/sotruss-lib.c
>   create mode 100644 sysdeps/loongarch/start.S
>   create mode 100644 sysdeps/loongarch/sys/asm.h
>   create mode 100644 sysdeps/loongarch/tst-audit.h
>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldconfig.h
> 
> diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S
> new file mode 100644
> index 0000000000..b7690dd94f
> --- /dev/null
> +++ b/sysdeps/loongarch/__longjmp.S
> @@ -0,0 +1,52 @@
> +/* longjmp.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +
> +ENTRY (__longjmp)
> +	REG_L ra, a0, 0*SZREG
> +	REG_L sp, a0, 1*SZREG
> +	REG_L x,  a0, 2*SZREG
> +	REG_L fp, a0, 3*SZREG
> +	REG_L s0, a0, 4*SZREG
> +	REG_L s1, a0, 5*SZREG
> +	REG_L s2, a0, 6*SZREG
> +	REG_L s3, a0, 7*SZREG
> +	REG_L s4, a0, 8*SZREG
> +	REG_L s5, a0, 9*SZREG
> +	REG_L s6, a0, 10*SZREG
> +	REG_L s7, a0, 11*SZREG
> +	REG_L s8, a0, 12*SZREG
> +
> +#ifndef __loongarch_soft_float

The softfp is explicit disabled, so I think checking it on code does
not add much.  Once softfp is actually enabled we can add it back, it
also make is explicit in history what was required to enable the abi.

> +	FREG_L $f24, a0, 13*SZREG + 0*SZFREG
> +	FREG_L $f25, a0, 13*SZREG + 1*SZFREG
> +	FREG_L $f26, a0, 13*SZREG + 2*SZFREG
> +	FREG_L $f27, a0, 13*SZREG + 3*SZFREG
> +	FREG_L $f28, a0, 13*SZREG + 4*SZFREG
> +	FREG_L $f29, a0, 13*SZREG + 5*SZFREG
> +	FREG_L $f30, a0, 13*SZREG + 6*SZFREG
> +	FREG_L $f31, a0, 13*SZREG + 7*SZFREG
> +#endif
> +
> +	sltui	a0,a1,1
> +	ADD	a0, a0, a1	 # a0 = (a1 == 0) ? 1 : a1
> +	jirl	zero,ra,0
> +
> +END (__longjmp)
> diff --git a/sysdeps/loongarch/bits/endianness.h b/sysdeps/loongarch/bits/endianness.h
> new file mode 100644
> index 0000000000..7290be7b18
> --- /dev/null
> +++ b/sysdeps/loongarch/bits/endianness.h
> @@ -0,0 +1,11 @@
> +#ifndef _BITS_ENDIANNESS_H
> +#define _BITS_ENDIANNESS_H 1
> +
> +#ifndef _BITS_ENDIAN_H
> +#error "Never use <bits/endianness.h> directly; include <endian.h> instead."
> +#endif
> +
> +/* LoongArch is little-endian.  */
> +#define __BYTE_ORDER __LITTLE_ENDIAN
> +
> +#endif /* bits/endianness.h */
> diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h
> new file mode 100644
> index 0000000000..05c91575e9
> --- /dev/null
> +++ b/sysdeps/loongarch/bits/link.h
> @@ -0,0 +1,58 @@
> +/* Machine-specific declarations for dynamic linker interface.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _LINK_H
> +#error "Never include <bits/link.h> directly; use <link.h> instead."
> +#endif
> +
> +typedef struct La_loongarch_regs
> +{
> +  unsigned long int lr_reg[8]; /* a0 - a7 */
> +  double lr_fpreg[8];	       /* fa0 - fa7 */
> +  unsigned long int lr_ra;
> +  unsigned long int lr_sp;
> +} La_loongarch_regs;
> +
> +/* Return values for calls from PLT on LoongArch.  */
> +typedef struct La_loongarch_retval
> +{
> +  unsigned long int lrv_a0;
> +  unsigned long int lrv_a1;
> +  double lrv_fa0;
> +  double lrv_fa1;
> +} La_loongarch_retval;
> +
> +__BEGIN_DECLS
> +
> +extern ElfW (Addr) la_loongarch_gnu_pltenter (ElfW (Sym) *__sym,
> +					      unsigned int __ndx,
> +					      uintptr_t *__refcook,
> +					      uintptr_t *__defcook,
> +					      La_loongarch_regs *__regs,
> +					      unsigned int *__flags,
> +					      const char *__symname,
> +					      long int *__framesizep);
> +extern unsigned int la_loongarch_gnu_pltexit (ElfW (Sym) *__sym,
> +					      unsigned int __ndx,
> +					      uintptr_t *__refcook,
> +					      uintptr_t *__defcook,
> +					      const La_loongarch_regs *__inregs,
> +					      La_loongarch_retval *__outregs,
> +					      const char *__symname);
> +
> +__END_DECLS
> diff --git a/sysdeps/loongarch/bits/setjmp.h b/sysdeps/loongarch/bits/setjmp.h
> new file mode 100644
> index 0000000000..8b323ad2b6
> --- /dev/null
> +++ b/sysdeps/loongarch/bits/setjmp.h
> @@ -0,0 +1,42 @@
> +/* Define the machine-dependent type `jmp_buf'.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _LOONGARCH_BITS_SETJMP_H
> +#define _LOONGARCH_BITS_SETJMP_H
> +
> +typedef struct __jmp_buf_internal_tag
> +{
> +  /* Program counter.  */
> +  long int __pc;
> +  /* Stack pointer.  */
> +  long int __sp;
> +  /* Reserved */
> +  long int __x;
> +  /* Frame pointer.  */
> +  long int __fp;
> +  /* Callee-saved registers.  */
> +  long int __regs[9];
> +
> +#ifndef __loongarch_soft_float
> +  /* Callee-saved floating point registers.  */
> +  double __fpregs[8];
> +#endif

Same as before.

> +
> +} __jmp_buf[1];
> +
> +#endif /* _LOONGARCH_BITS_SETJMP_H */
> diff --git a/sysdeps/loongarch/bsd-_setjmp.c b/sysdeps/loongarch/bsd-_setjmp.c
> new file mode 100644
> index 0000000000..32f49441c3
> --- /dev/null
> +++ b/sysdeps/loongarch/bsd-_setjmp.c
> @@ -0,0 +1 @@
> +/* _setjmp is implemented in setjmp.S.  */
> diff --git a/sysdeps/loongarch/bsd-setjmp.c b/sysdeps/loongarch/bsd-setjmp.c
> new file mode 100644
> index 0000000000..45fd802aac
> --- /dev/null
> +++ b/sysdeps/loongarch/bsd-setjmp.c
> @@ -0,0 +1 @@
> +/* setjmp is implemented in setjmp.S.  */
> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
> new file mode 100644
> index 0000000000..a615e6774a
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-machine.h
> @@ -0,0 +1,287 @@
> +/* Machine-dependent ELF dynamic relocation inline functions.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef dl_machine_h
> +#define dl_machine_h
> +
> +#define ELF_MACHINE_NAME "LoongArch"
> +
> +#include <entry.h>
> +#include <elf/elf.h>
> +#include <sys/asm.h>
> +#include <dl-tls.h>
> +#include <dl-static-tls.h>
> +#include <dl-machine-rel.h>
> +
> +#ifndef _RTLD_PROLOGUE
> +# define _RTLD_PROLOGUE(entry)					\
> +	".globl\t" __STRING (entry) "\n\t"			\
> +	".type\t" __STRING (entry) ", @function\n\t"		\
> +	CFI_STARTPROC "\n"					\
> +	__STRING (entry) ":\n"
> +#endif
> +
> +#ifndef _RTLD_EPILOGUE
> +# define _RTLD_EPILOGUE(entry)					\
> +	CFI_ENDPROC "\n\t"					\
> +	".size\t" __STRING (entry) ", . - " __STRING (entry) "\n"
> +#endif
> +
> +#define ELF_MACHINE_JMP_SLOT R_LARCH_JUMP_SLOT
> +#define ELF_MACHINE_IRELATIVE R_LARCH_IRELATIVE
> +
> +#define elf_machine_type_class(type)				\
> +  ((ELF_RTYPE_CLASS_PLT *((type) == ELF_MACHINE_JMP_SLOT))	\
> +   | (ELF_RTYPE_CLASS_COPY *((type) == R_LARCH_COPY)))
> +
> +#define ELF_MACHINE_NO_REL 1
> +#define ELF_MACHINE_NO_RELA 0
> +
> +/* Return nonzero iff ELF header is compatible with the running host.  */
> +static inline int
> +elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
> +{
> +  /* We can only run LoongArch binaries.  */
> +  if (ehdr->e_machine != EM_LOONGARCH)
> +    return 0;
> +
> +  return 1;
> +}
> +
> +/* Return the run-time load address of the shared object.  */
> +static inline ElfW (Addr) elf_machine_load_address (void)
> +{
> +  extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
> +  return (ElfW(Addr)) &__ehdr_start;
> +}
> +
> +/* Return the link-time address of _DYNAMIC.  */
> +static inline ElfW (Addr) elf_machine_dynamic (void)
> +{
> +  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
> +  return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
> +}
> +
> +/* Initial entry point code for the dynamic linker.
> +   The C function `_dl_start' is the real entry point;
> +   its return value is the user program's entry point.  */
> +
> +#define RTLD_START \
> +  asm(".text\n\
> +      " _RTLD_PROLOGUE (ENTRY_POINT) "\
> +      .cfi_label .Ldummy   \n\
> +      " CFI_UNDEFINED (1) "   \n\
> +      or	$a0, $sp, $zero   \n\
> +      bl	_dl_start   \n\
> +      # Stash user entry point in s0.   \n\
> +      or	$s0, $v0, $zero   \n\
> +      # Load the original argument count.   \n\
> +      ld.d	$a1, $sp, 0   \n\
> +      # Call _dl_init (struct link_map *main_map, int argc, char **argv, \
> +		       char **env)    \n\
> +      la	$a0, _rtld_local   \n\
> +      ld.d	$a0, $a0, 0   \n\
> +      addi.d	$a2, $sp, 8   \n\
> +      slli.d	$a3, $a1, 3   \n\
> +      add.d	$a3, $a3, $a2   \n\
> +      addi.d	$a3, $a3, 8   \n\
> +      # Stash the stack pointer in s1.\n\
> +      or	$s1, $sp, $zero	\n\
> +      # Adjust $sp for 16-aligned   \n\
> +      bstrins.d	$sp, $zero, 3, 0  \n\
> +      # Call the function to run the initializers.   \n\
> +      bl	_dl_init   \n\
> +      # Restore the stack pointer for _start.\n\
> +      or	$sp, $s1, $zero	 \n\
> +      # Pass our finalizer function to _start.   \n\
> +      la	$a0, _dl_fini   \n\
> +      # Jump to the user entry point.   \n\
> +      jirl	$zero, $s0, 0   \n\
> +      " _RTLD_EPILOGUE (ENTRY_POINT) "\
> +      .previous");
> +
> +/* Names of the architecture-specific auditing callback functions.  */
> +#define ARCH_LA_PLTENTER loongarch_gnu_pltenter
> +#define ARCH_LA_PLTEXIT loongarch_gnu_pltexit
> +
> +/* Bias .got.plt entry by the offset requested by the PLT header.  */
> +#define elf_machine_plt_value(map, reloc, value) (value)
> +
> +static inline ElfW (Addr)
> +elf_machine_fixup_plt (struct link_map *map, lookup_t t,
> +			 const ElfW (Sym) *refsym, const ElfW (Sym) *sym,
> +			 const ElfW (Rela) *reloc, ElfW (Addr) *reloc_addr,
> +			 ElfW (Addr) value)
> +{
> +  return *reloc_addr = value;
> +}
> +
> +#endif /* !dl_machine_h */
> +
> +#ifdef RESOLVE_MAP
> +
> +/* Perform a relocation described by R_INFO at the location pointed to
> +   by RELOC_ADDR.  SYM is the relocation symbol specified by R_INFO and
> +   MAP is the object containing the reloc.  */
> +
> +static inline void __attribute__ ((always_inline))
> +elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
> +		  const ElfW (Rela) *reloc,
> +		  const ElfW (Sym) *sym,
> +		  const struct r_found_version *version,
> +		  void *const reloc_addr, int skip_ifunc)
> +{
> +  ElfW (Addr) r_info = reloc->r_info;
> +  const unsigned long int r_type = ELFW (R_TYPE) (r_info);
> +  ElfW (Addr) *addr_field = (ElfW (Addr) *) reloc_addr;
> +  const ElfW (Sym) *const __attribute__ ((unused)) refsym = sym;
> +  struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
> +  ElfW (Addr) value = 0;
> +  if (sym_map != NULL)
> +    value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
> +
> +  if (sym != NULL
> +      && __glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
> +      && __glibc_likely (sym->st_shndx != SHN_UNDEF)
> +      && __glibc_likely (!skip_ifunc))
> +    value = ((ElfW (Addr) (*) (int)) value) (GLRO (dl_hwcap));
> +
> +  switch (r_type)
> +    {
> +
> +    case R_LARCH_JUMP_SLOT:
> +    case __WORDSIZE == 64 ? R_LARCH_64:
> +    R_LARCH_32:
> +      *addr_field = value;
> +      break;
> +
> +#ifndef RTLD_BOOTSTRAP
> +    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64:
> +    R_LARCH_TLS_DTPMOD32:
> +      *addr_field = sym_map->l_tls_modid;
> +      break;
> +
> +    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64:
> +    R_LARCH_TLS_DTPREL32:
> +      *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
> +      break;
> +
> +    case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64:
> +    R_LARCH_TLS_TPREL32:
> +      CHECK_STATIC_TLS (map, sym_map);
> +      *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
> +      break;
> +
> +    case R_LARCH_COPY:
> +      {
> +	  if (sym == NULL)
> +	    /* This can happen in trace mode if an object could not be
> +	       found.  */
> +	    break;
> +	  if (__glibc_unlikely (sym->st_size > refsym->st_size)
> +	      || (__glibc_unlikely (sym->st_size < refsym->st_size)
> +		&& GLRO(dl_verbose)))
> +	  {
> +	    const char *strtab;
> +
> +	    strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
> +	    _dl_error_printf ("\
> +%s: Symbol `%s' has different size in shared object, consider re-linking\n",
> +	    rtld_progname ?: "<program name unknown>",
> +	    strtab + refsym->st_name);
> +	  }
> +	  memcpy (reloc_addr, (void *) value,
> +		  MIN (sym->st_size, refsym->st_size));
> +	    break;
> +      }
> +
> +    case R_LARCH_RELATIVE:
> +      *addr_field = map->l_addr + reloc->r_addend;
> +      break;
> +
> +    case R_LARCH_IRELATIVE:
> +      value = map->l_addr + reloc->r_addend;
> +      if (__glibc_likely (!skip_ifunc))
> +	value = ((ElfW (Addr) (*) (void)) value) ();
> +      *addr_field = value;
> +      break;
> +
> +    case R_LARCH_NONE:
> +      break;
> +#endif

 From previous discussion, R_LARCH_NONE dynamic relocations should be 
considered missing optimization (assuming input unrecognizable 
relocations are handled in static linker).  Since not handling it on
bootstrap generates unusable loader, I think it would be better to
handle on for RTLD_BOOTSTRAP.

> +
> +    default:
> +      _dl_reloc_bad_type (map, r_type, 0);
> +      break;
> +    }
> +}
> +
> +static inline void __attribute__ ((always_inline))
> +elf_machine_rela_relative (ElfW (Addr) l_addr, const ElfW (Rela) *reloc,
> +			   void *const reloc_addr)
> +{
> +  *(ElfW (Addr) *) reloc_addr = l_addr + reloc->r_addend;
> +}
> +
> +static inline void __attribute__ ((always_inline))
> +elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
> +		      ElfW (Addr) l_addr,
> +		      const ElfW (Rela) *reloc, int skip_ifunc)
> +{
> +  ElfW (Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
> +  const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
> +
> +  /* Check for unexpected PLT reloc type.  */
> +  if (__glibc_likely (r_type == R_LARCH_JUMP_SLOT))
> +    {
> +      if (__glibc_unlikely (map->l_mach.plt == 0))
> +	{
> +	  if (l_addr)
> +	    *reloc_addr += l_addr;
> +	}
> +      else
> +	*reloc_addr = map->l_mach.plt;
> +    }
> +  else
> +    _dl_reloc_bad_type (map, r_type, 1);
> +}
> +
> +/* Set up the loaded object described by L so its stub function
> +   will jump to the on-demand fixup code __dl_runtime_resolve.  */
> +
> +static inline int __attribute__ ((always_inline))
> +elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
> +			   int lazy, int profile)
> +{
> +#ifndef RTLD_BOOTSTRAP
> +  /* If using PLTs, fill in the first two entries of .got.plt.  */
> +  if (l->l_info[DT_JMPREL])
> +    {
> +      extern void _dl_runtime_resolve (void)
> +	__attribute__ ((visibility ("hidden")));
> +      ElfW (Addr) *gotplt = (ElfW (Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
> +      gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve;
> +      gotplt[1] = (ElfW (Addr)) l;
> +    }
> +#endif
> +
> +  return lazy;
> +}
> +
> +#endif /* RESOLVE_MAP */
> diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S
> new file mode 100644
> index 0000000000..eb610392f6
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-trampoline.S
> @@ -0,0 +1,91 @@
> +/* PLT trampolines.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +
> +/* Assembler veneer called from the PLT header code for lazy loading.
> +   The PLT header passes its own args in t0-t2.  */
> +
> +#ifdef __loongarch_soft_float
> +# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
> +#else
> +# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
> +#endif
> +
> +ENTRY (_dl_runtime_resolve)
> +
> +	/* Save arguments to stack. */
> +	ADDI	sp, sp, -FRAME_SIZE
> +
> +	REG_S	ra, sp, 9*SZREG
> +	REG_S	a0, sp, 1*SZREG
> +	REG_S	a1, sp, 2*SZREG
> +	REG_S	a2, sp, 3*SZREG
> +	REG_S	a3, sp, 4*SZREG
> +	REG_S	a4, sp, 5*SZREG
> +	REG_S	a5, sp, 6*SZREG
> +	REG_S	a6, sp, 7*SZREG
> +	REG_S	a7, sp, 8*SZREG
> +
> +#ifndef __loongarch_soft_float

Same as before.

> +	FREG_S	fa0, sp, 10*SZREG + 0*SZFREG
> +	FREG_S	fa1, sp, 10*SZREG + 1*SZFREG
> +	FREG_S	fa2, sp, 10*SZREG + 2*SZFREG
> +	FREG_S	fa3, sp, 10*SZREG + 3*SZFREG
> +	FREG_S	fa4, sp, 10*SZREG + 4*SZFREG
> +	FREG_S	fa5, sp, 10*SZREG + 5*SZFREG
> +	FREG_S	fa6, sp, 10*SZREG + 6*SZFREG
> +	FREG_S	fa7, sp, 10*SZREG + 7*SZFREG
> +#endif
> +
> +	/* Update .got.plt and obtain runtime address of callee */
> +	SLLI	a1, t1, 1
> +	or	a0, t0, zero
> +	ADD	a1, a1, t1
> +	la	a2, _dl_fixup
> +	jirl	ra, a2, 0
> +	or	t1, v0, zero
> +
> +	/* Restore arguments from stack. */
> +	REG_L	ra, sp, 9*SZREG
> +	REG_L	a0, sp, 1*SZREG
> +	REG_L	a1, sp, 2*SZREG
> +	REG_L	a2, sp, 3*SZREG
> +	REG_L	a3, sp, 4*SZREG
> +	REG_L	a4, sp, 5*SZREG
> +	REG_L	a5, sp, 6*SZREG
> +	REG_L	a6, sp, 7*SZREG
> +	REG_L	a7, sp, 8*SZREG
> +
> +#ifndef __loongarch_soft_float

Same as before.

> +	FREG_L	fa0, sp, 10*SZREG + 0*SZFREG
> +	FREG_L	fa1, sp, 10*SZREG + 1*SZFREG
> +	FREG_L	fa2, sp, 10*SZREG + 2*SZFREG
> +	FREG_L	fa3, sp, 10*SZREG + 3*SZFREG
> +	FREG_L	fa4, sp, 10*SZREG + 4*SZFREG
> +	FREG_L	fa5, sp, 10*SZREG + 5*SZFREG
> +	FREG_L	fa6, sp, 10*SZREG + 6*SZFREG
> +	FREG_L	fa7, sp, 10*SZREG + 7*SZFREG
> +#endif
> +
> +	ADDI	sp, sp, FRAME_SIZE
> +
> +	/* Invoke the callee. */
> +	jirl		zero, t1, 0
> +END (_dl_runtime_resolve)
> diff --git a/sysdeps/loongarch/jmpbuf-offsets.h b/sysdeps/loongarch/jmpbuf-offsets.h
> new file mode 100644
> index 0000000000..a4b8ea690e
> --- /dev/null
> +++ b/sysdeps/loongarch/jmpbuf-offsets.h
> @@ -0,0 +1,22 @@
> +/* Private macros for accessing __jmp_buf contents.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public License as
> +   published by the Free Software Foundation; either version 2.1 of the
> +   License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <jmpbuf-unwind.h>
> +
> +/* Helper for generic ____longjmp_chk().  */
> +#define JB_FRAME_ADDRESS(buf) ((void *) _jmpbuf_sp (buf))
> diff --git a/sysdeps/loongarch/jmpbuf-unwind.h b/sysdeps/loongarch/jmpbuf-unwind.h
> new file mode 100644
> index 0000000000..6fa509151d
> --- /dev/null
> +++ b/sysdeps/loongarch/jmpbuf-unwind.h
> @@ -0,0 +1,45 @@
> +/* Examine __jmp_buf for unwinding frames.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <setjmp.h>
> +#include <stdint.h>
> +#include <unwind.h>
> +#include <sysdep.h>
> +
> +/* Test if longjmp to JMPBUF would unwind the frame
> +   containing a local variable at ADDRESS.  */
> +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
> +  ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
> +
> +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
> +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
> +
> +static inline uintptr_t __attribute__ ((unused)) _jmpbuf_sp (__jmp_buf regs)
> +{
> +  uintptr_t sp = regs[0].__sp;
> +#ifdef PTR_DEMANGLE
> +  PTR_DEMANGLE (sp);
> +#endif
> +  return sp;
> +}
> +
> +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
> +  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
> +
> +/* We use the normal longjmp for unwinding.  */
> +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
> diff --git a/sysdeps/loongarch/ldsodefs.h b/sysdeps/loongarch/ldsodefs.h
> new file mode 100644
> index 0000000000..36b1b25b9f
> --- /dev/null
> +++ b/sysdeps/loongarch/ldsodefs.h
> @@ -0,0 +1,41 @@
> +/* Run-time dynamic linker data structures for loaded ELF shared objects.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _LOONGARCH_LDSODEFS_H
> +#define _LOONGARCH_LDSODEFS_H 1
> +
> +#include <elf.h>
> +
> +struct La_loongarch_regs;
> +struct La_loongarch_retval;
> +
> +#define ARCH_PLTENTER_MEMBERS \
> +  ElfW (Addr) (*loongarch_gnu_pltenter) (ElfW (Sym) *, unsigned int, \
> +					 uintptr_t *, uintptr_t *, \
> +					 const struct La_loongarch_regs *, \
> +					 unsigned int *, const char *name, \
> +					 long int *framesizep);
> +
> +#define ARCH_PLTEXIT_MEMBERS \
> +  unsigned int (*loongarch_gnu_pltexit) (ElfW (Sym) *, unsigned int, \
> +		uintptr_t *, uintptr_t *, const struct La_loongarch_regs *, \
> +		struct La_loongarch_retval *, const char *);
> +
> +#include_next <ldsodefs.h>
> +
> +#endif
> diff --git a/sysdeps/loongarch/linkmap.h b/sysdeps/loongarch/linkmap.h
> new file mode 100644
> index 0000000000..bbba73ed70
> --- /dev/null
> +++ b/sysdeps/loongarch/linkmap.h
> @@ -0,0 +1,22 @@
> +/* Definition of link_map_machine.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +struct link_map_machine
> +{
> +  ElfW (Addr) plt; /* Address of .plt.  */
> +};
> diff --git a/sysdeps/loongarch/machine-gmon.h b/sysdeps/loongarch/machine-gmon.h
> new file mode 100644
> index 0000000000..4a3cdd964e
> --- /dev/null
> +++ b/sysdeps/loongarch/machine-gmon.h
> @@ -0,0 +1,37 @@
> +/* LoongArch definitions for profiling support.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +/* Accept 'frompc' address as argument from the function that calls
> +   _mcount for profiling.  Use  __builtin_return_address (0)
> +   for the 'selfpc' address.  */
> +
> +#include <sysdep.h>
> +
> +static void mcount_internal (unsigned long int frompc,
> +			     unsigned long int selfpc);
> +
> +#define _MCOUNT_DECL(frompc, selfpc) \
> +  static inline void mcount_internal (unsigned long int frompc, \
> +				      unsigned long int selfpc)
> +
> +#define MCOUNT \
> +  void _mcount (void *frompc) \
> +  { \
> +    mcount_internal ((unsigned long int) frompc, \
> +		     (unsigned long int) RETURN_ADDRESS (0)); \
> +  }
> diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
> new file mode 100644
> index 0000000000..c081ff6b87
> --- /dev/null
> +++ b/sysdeps/loongarch/setjmp.S
> @@ -0,0 +1,66 @@
> +/* setjmp for LoongArch.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +
> +ENTRY (_setjmp)
> +	li.w		a1,0
> +	b		HIDDEN_JUMPTARGET (__sigsetjmp)
> +END (_setjmp)
> +
> +ENTRY (setjmp)
> +	li.w		a1,1
> +END (setjmp)
> +
> +ENTRY (__sigsetjmp)
> +	REG_S ra, a0, 0*SZREG
> +	REG_S sp, a0, 1*SZREG
> +	REG_S x,  a0, 2*SZREG
> +	REG_S fp, a0, 3*SZREG
> +	REG_S s0, a0, 4*SZREG
> +	REG_S s1, a0, 5*SZREG
> +	REG_S s2, a0, 6*SZREG
> +	REG_S s3, a0, 7*SZREG
> +	REG_S s4, a0, 8*SZREG
> +	REG_S s5, a0, 9*SZREG
> +	REG_S s6, a0, 10*SZREG
> +	REG_S s7, a0, 11*SZREG
> +	REG_S s8, a0, 12*SZREG
> +
> +#ifndef __loongarch_soft_float
> +	FREG_S $f24, a0, 13*SZREG + 0*SZFREG
> +	FREG_S $f25, a0, 13*SZREG + 1*SZFREG
> +	FREG_S $f26, a0, 13*SZREG + 2*SZFREG
> +	FREG_S $f27, a0, 13*SZREG + 3*SZFREG
> +	FREG_S $f28, a0, 13*SZREG + 4*SZFREG
> +	FREG_S $f29, a0, 13*SZREG + 5*SZFREG
> +	FREG_S $f30, a0, 13*SZREG + 6*SZFREG
> +	FREG_S $f31, a0, 13*SZREG + 7*SZFREG
> +#endif
> +
> +#if !IS_IN (libc) && IS_IN(rtld)
> +	li.w		v0, 0
> +	jirl		zero,ra,0
> +#else
> +	b		__sigjmp_save
> +#endif
> +END (__sigsetjmp)
> +
> +hidden_def (__sigsetjmp)
> +weak_alias (_setjmp, __GI__setjmp)
> diff --git a/sysdeps/loongarch/sotruss-lib.c b/sysdeps/loongarch/sotruss-lib.c
> new file mode 100644
> index 0000000000..ce752785f6
> --- /dev/null
> +++ b/sysdeps/loongarch/sotruss-lib.c
> @@ -0,0 +1,50 @@
> +/* Override generic sotruss-lib.c to define actual functions for LoongArch.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#define HAVE_ARCH_PLTENTER
> +#define HAVE_ARCH_PLTEXIT
> +
> +#include <elf/sotruss-lib.c>
> +
> +ElfW (Addr)
> +la_loongarch_gnu_pltenter (ElfW (Sym) *sym __attribute__ ((unused)),
> +			   unsigned int ndx __attribute__ ((unused)),
> +			   uintptr_t *refcook, uintptr_t *defcook,
> +			   La_loongarch_regs *regs, unsigned int *flags,
> +			   const char *symname, long int *framesizep)
> +{
> +  print_enter (refcook, defcook, symname, regs->lr_reg[0], regs->lr_reg[1],
> +		   regs->lr_reg[2], *flags);
> +
> +  /* No need to copy anything, we will not need the parameters in any case.  */
> +  *framesizep = 0;
> +
> +  return sym->st_value;
> +}
> +
> +unsigned int
> +la_loongarch_gnu_pltexit (ElfW (Sym) *sym, unsigned int ndx,
> +			  uintptr_t *refcook, uintptr_t *defcook,
> +			  const struct La_loongarch_regs *inregs,
> +			  struct La_loongarch_retval *outregs,
> +			  const char *symname)
> +{
> +  print_exit (refcook, defcook, symname, outregs->lrv_a0);
> +
> +  return 0;
> +}
> diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
> new file mode 100644
> index 0000000000..280b5fab8c
> --- /dev/null
> +++ b/sysdeps/loongarch/start.S
> @@ -0,0 +1,66 @@
> +/* Startup code compliant to the ELF LoongArch ABI.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#define __ASSEMBLY__ 1
> +#include <entry.h>
> +#include <sys/asm.h>
> +
> +/* The entry point's job is to call __libc_start_main.  Per the ABI,
> +   a0 contains the address of a function to be passed to atexit.
> +   __libc_start_main wants this in a5.  */
> +
> +/*
> +int
> +__libc_start_main (int (*main) (int, char **, char **),
> +		   int argc,
> +		   char **argv,
> +		   __typeof (main) init,
> +		   void (*fini) (void),
> +		   void (*rtld_fini) (void),
> +		   void *stack_end);
> + */
> +
> +ENTRY (ENTRY_POINT)
> +
> +/* Terminate call stack by noting ra is undefined.  Use a dummy
> +   .cfi_label to force starting the FDE.  */
> +	.cfi_label .Ldummy
> +	cfi_undefined (1)
> +	or		a5, a0, zero /* rtld_fini */
> +
> +/* We must get symbol main through GOT table, since main may not be local.
> +   For instance: googletest defines main in dynamic library.  */
> +	la.got		a0, t0, main
> +	REG_L		a1, sp, 0
> +	ADDI		a2, sp, SZREG
> +
> +	/* Adjust $sp for 16-aligned */
> +	BSTRINS		sp, zero, 3, 0
> +
> +	move		a3, zero /* used to be init */
> +	move		a4, zero /* used to be fini */
> +	or		a6, sp, zero /* stack_end */
> +
> +	la.got		ra, t0, __libc_start_main
> +	jirl		ra, ra, 0
> +
> +	la.got		ra, t0, abort
> +	jirl		ra, ra, 0
> +END (ENTRY_POINT)
> +
> diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h
> new file mode 100644
> index 0000000000..b41ee59694
> --- /dev/null
> +++ b/sysdeps/loongarch/sys/asm.h
> @@ -0,0 +1,59 @@
> +/* Miscellaneous macros.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SYS_ASM_H
> +#define _SYS_ASM_H
> +
> +#include <sys/regdef.h>
> +#include <sysdeps/generic/sysdep.h>
> +
> +/* Macros to handle different pointer/register sizes for 32/64-bit code.  */
> +#define SZREG 8
> +#define SZFREG 8
> +#define REG_L ld.d
> +#define REG_S st.d
> +#define SRLI srli.d
> +#define SLLI slli.d
> +#define ADDI addi.d
> +#define ADD  add.d
> +#define BSTRINS  bstrins.d
> +#define LI  li.d
> +#define FREG_L fld.d
> +#define FREG_S fst.d
> +
> +/* Declare leaf routine.  */
> +#define LEAF(symbol) \
> +  .text; \
> +  .globl symbol; \
> +  .align 3; \
> +  cfi_startproc; \
> +  .type symbol, @function; \
> +  symbol:
> +
> +#define ENTRY(symbol) LEAF (symbol)
> +
> +/* Mark end of function.  */
> +#undef END
> +#define END(function) \
> +  cfi_endproc; \
> +  .size function, .- function;
> +
> +/* Stack alignment.  */
> +#define ALMASK ~15
> +
> +#endif /* sys/asm.h */
> diff --git a/sysdeps/loongarch/tst-audit.h b/sysdeps/loongarch/tst-audit.h
> new file mode 100644
> index 0000000000..e71948c86e
> --- /dev/null
> +++ b/sysdeps/loongarch/tst-audit.h
> @@ -0,0 +1,23 @@
> +/* Definitions for testing PLT entry/exit auditing.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#define pltenter la_loongarch_gnu_pltenter
> +#define pltexit la_loongarch_gnu_pltexit
> +#define La_regs La_loongarch_regs
> +#define La_retval La_loongarch_retval
> +#define int_retval lrv_a0
> diff --git a/sysdeps/unix/sysv/linux/loongarch/ldconfig.h b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
> new file mode 100644
> index 0000000000..4887c30ca2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
> @@ -0,0 +1,26 @@
> +/* ldconfig default paths and libraries.
> +   Copyright (C) 2022 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <sysdeps/generic/ldconfig.h>
> +
> +#define SYSDEP_KNOWN_INTERPRETER_NAMES \
> +  { "/lib64/ld-linux-loongarch-lp64d.so.1", FLAG_ELF_LIBC6 },
> +
> +#define SYSDEP_KNOWN_LIBRARY_NAMES	\
> +  { "libc.so.6", FLAG_ELF_LIBC6 },	\
> +  { "libm.so.6", FLAG_ELF_LIBC6 },

This file is not required and and the idea is to eventually remove
it [1].  The default definitions already add the expected loader
and libc names, so SYSDEP_KNOWN_INTERPRETER_NAMES and
SYSDEP_KNOWN_LIBRARY_NAMES are redundant.

[1] 
https://patchwork.sourceware.org/project/glibc/patch/20220518130728.5cy6uutc5eiqxbwv@workbox/
  
caiyinyu July 15, 2022, 1:46 a.m. UTC | #2
+    REG_L s6, a0, 10*SZREG
+    REG_L s7, a0, 11*SZREG
+    REG_L s8, a0, 12*SZREG
+
+#ifndef __loongarch_soft_float

The softfp is explicit disabled, so I think checking it on code does
not add much.  Once softfp is actually enabled we can add it back, it
also make is explicit in history what was required to enable the abi.

*Fixed all by removing **__loongarch_soft_float.*

*>>>>>>>>>>>>>>>>>>*

*diff --git a/sysdeps/loongarch/dl-trampoline.S 
b/sysdeps/loongarch/dl-trampoline.S**
**index 72a068639b..ad8ab0fda7 100644**
**--- a/sysdeps/loongarch/dl-trampoline.S**
**+++ b/sysdeps/loongarch/dl-trampoline.S**
**@@ -22,11 +22,7 @@**
** /* Assembler veneer called from the PLT header code for lazy loading.**
**    The PLT header passes its own args in t0-t2.  */**
****
**-#ifdef __loongarch_soft_float**
**-# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))**
**-#else**
** # define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))**
**-#endif**
****
** ENTRY (_dl_runtime_resolve)**
****
*

*diff --git a/sysdeps/loongarch/__longjmp.S 
b/sysdeps/loongarch/__longjmp.S**
**index b7690dd94f..37e7384413 100644**
**--- a/sysdeps/loongarch/__longjmp.S**
**+++ b/sysdeps/loongarch/__longjmp.S**
**@@ -34,7 +34,6 @@ ENTRY (__longjmp)**
**     REG_L s7, a0, 11*SZREG**
**     REG_L s8, a0, 12*SZREG**
****
**-#ifndef __loongarch_soft_float**
**     FREG_L $f24, a0, 13*SZREG + 0*SZFREG**
**     FREG_L $f25, a0, 13*SZREG + 1*SZFREG**
**     FREG_L $f26, a0, 13*SZREG + 2*SZFREG**
**@@ -43,7 +42,6 @@ ENTRY (__longjmp)**
**     FREG_L $f29, a0, 13*SZREG + 5*SZFREG**
**     FREG_L $f30, a0, 13*SZREG + 6*SZFREG**
**     FREG_L $f31, a0, 13*SZREG + 7*SZFREG**
**-#endif**
****
**     sltui    a0,a1,1**
**     ADD    a0, a0, a1     # a0 = (a1 == 0) ? 1 : a1**
**diff --git a/sysdeps/loongarch/bits/setjmp.h 
b/sysdeps/loongarch/bits/setjmp.h**
**index 8b323ad2b6..42f8fa7657 100644**
**--- a/sysdeps/loongarch/bits/setjmp.h**
**+++ b/sysdeps/loongarch/bits/setjmp.h**
**@@ -31,11 +31,8 @@ typedef struct __jmp_buf_internal_tag**
**   long int __fp;**
**   /* Callee-saved registers.  */**
**   long int __regs[9];**
**-**
**-#ifndef __loongarch_soft_float**
**   /* Callee-saved floating point registers.  */**
**   double __fpregs[8];**
**-#endif**
****
** } __jmp_buf[1];**
****
**diff --git a/sysdeps/loongarch/dl-trampoline.S 
b/sysdeps/loongarch/dl-trampoline.S**
**index eb610392f6..72a068639b 100644**
**--- a/sysdeps/loongarch/dl-trampoline.S**
**+++ b/sysdeps/loongarch/dl-trampoline.S**
**@@ -43,7 +43,6 @@ ENTRY (_dl_runtime_resolve)**
**     REG_S    a6, sp, 7*SZREG**
**     REG_S    a7, sp, 8*SZREG**
****
**-#ifndef __loongarch_soft_float**
**     FREG_S    fa0, sp, 10*SZREG + 0*SZFREG**
**     FREG_S    fa1, sp, 10*SZREG + 1*SZFREG**
**     FREG_S    fa2, sp, 10*SZREG + 2*SZFREG**
**@@ -52,7 +51,6 @@ ENTRY (_dl_runtime_resolve)**
**     FREG_S    fa5, sp, 10*SZREG + 5*SZFREG**
**     FREG_S    fa6, sp, 10*SZREG + 6*SZFREG**
**     FREG_S    fa7, sp, 10*SZREG + 7*SZFREG**
**-#endif**
****
**     /* Update .got.plt and obtain runtime address of callee */**
**     SLLI    a1, t1, 1**
**@@ -73,7 +71,6 @@ ENTRY (_dl_runtime_resolve)**
**     REG_L    a6, sp, 7*SZREG**
**     REG_L    a7, sp, 8*SZREG**
****
**-#ifndef __loongarch_soft_float**
**     FREG_L    fa0, sp, 10*SZREG + 0*SZFREG**
**     FREG_L    fa1, sp, 10*SZREG + 1*SZFREG**
**     FREG_L    fa2, sp, 10*SZREG + 2*SZFREG**
**@@ -82,7 +79,6 @@ ENTRY (_dl_runtime_resolve)**
**     FREG_L    fa5, sp, 10*SZREG + 5*SZFREG**
**     FREG_L    fa6, sp, 10*SZREG + 6*SZFREG**
**     FREG_L    fa7, sp, 10*SZREG + 7*SZFREG**
**-#endif**
****
**     ADDI    sp, sp, FRAME_SIZE**
****
**diff --git a/sysdeps/loongarch/fpu_control.h 
b/sysdeps/loongarch/fpu_control.h**
**index e302ae52b1..1eb8b1aab8 100644**
**--- a/sysdeps/loongarch/fpu_control.h**
**+++ b/sysdeps/loongarch/fpu_control.h**
**@@ -51,17 +51,6 @@**
****
** #include <features.h>**
****
**-#ifdef __loongarch_soft_float**
**-**
**-#define _FPU_RESERVED 0xffffffff**
**-#define _FPU_DEFAULT 0x00000000**
**-typedef unsigned int fpu_control_t;**
**-#define _FPU_GETCW(cw) (cw) = 0**
**-#define _FPU_SETCW(cw) (void) (cw)**
**-extern fpu_control_t __fpu_control;**
**-**
**-#else /* __loongarch_soft_float */**
**-**
** /* Masks for interrupts.  */**
** #define _FPU_MASK_V 0x10 /* Invalid operation */**
** #define _FPU_MASK_Z 0x08 /* Division by zero  */**
**@@ -97,6 +86,5 @@ extern void __loongarch_fpu_setcw (fpu_control_t) 
__THROW;**
** /* Default control word set at startup.  */**
** extern fpu_control_t __fpu_control;**
****
**-#endif /* __loongarch_soft_float */**
**-**
** #endif /* fpu_control.h */**
**+**
**diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S**
**index c081ff6b87..3afb9f3948 100644**
**--- a/sysdeps/loongarch/setjmp.S**
**+++ b/sysdeps/loongarch/setjmp.S**
**@@ -43,7 +43,6 @@ ENTRY (__sigsetjmp)**
**     REG_S s7, a0, 11*SZREG**
**     REG_S s8, a0, 12*SZREG**
****
**-#ifndef __loongarch_soft_float**
**     FREG_S $f24, a0, 13*SZREG + 0*SZFREG**
**     FREG_S $f25, a0, 13*SZREG + 1*SZFREG**
**     FREG_S $f26, a0, 13*SZREG + 2*SZFREG**
**@@ -52,7 +51,6 @@ ENTRY (__sigsetjmp)**
**     FREG_S $f29, a0, 13*SZREG + 5*SZFREG**
**     FREG_S $f30, a0, 13*SZREG + 6*SZFREG**
**     FREG_S $f31, a0, 13*SZREG + 7*SZFREG**
**-#endif**
****
** #if !IS_IN (libc) && IS_IN(rtld)**
**     li.w        v0, 0**
*

*
*

*<<<<<<<<<<<<<<<<*




+
+    case R_LARCH_NONE:
+      break;
+#endif

 From previous discussion, R_LARCH_NONE dynamic relocations should be 
considered missing optimization (assuming input unrecognizable 
relocations are handled in static linker).  Since not handling it on
bootstrap generates unusable loader, I think it would be better to
handle on for RTLD_BOOTSTRAP.

*
*

*Fixed.*

*>>>>>>>>>>>>>>>*

*
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index a615e6774a..968cd2fdd1 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -171,6 +171,9 @@ elf_machine_rela (struct link_map *map, struct 
r_scope_elem *scope[],
        *addr_field = value;
        break;

+    case R_LARCH_NONE:
+      break;
+
  #ifndef RTLD_BOOTSTRAP
      case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64:
      R_LARCH_TLS_DTPMOD32:
@@ -222,8 +225,6 @@ elf_machine_rela (struct link_map *map, struct 
r_scope_elem *scope[],
        *addr_field = value;
        break;

-    case R_LARCH_NONE:
-      break;
  #endif

      default:*

*<<<<<<<<<<<<<<<<<<<<<<<<<
*

*
*

diff --git a/sysdeps/unix/sysv/linux/loongarch/ldconfig.h 
b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
new file mode 100644
index 0000000000..4887c30ca2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
@@ -0,0 +1,26 @@

...


+  { "libm.so.6", FLAG_ELF_LIBC6 },

This file is not required and and the idea is to eventually remove
it [1].  The default definitions already add the expected loader
and libc names, so SYSDEP_KNOWN_INTERPRETER_NAMES and
SYSDEP_KNOWN_LIBRARY_NAMES are redundant.

*
*

*loongarch/ldconfig.h removed.*

*
*

*Thanks.
*


在 2022/7/13 上午4:39, Adhemerval Zanella Netto 写道:
>
>
> On 08/07/22 03:52, caiyinyu wrote:
>> ---
>>   sysdeps/loongarch/__longjmp.S                |  52 ++++
>>   sysdeps/loongarch/bits/endianness.h          |  11 +
>>   sysdeps/loongarch/bits/link.h                |  58 ++++
>>   sysdeps/loongarch/bits/setjmp.h              |  42 +++
>>   sysdeps/loongarch/bsd-_setjmp.c              |   1 +
>>   sysdeps/loongarch/bsd-setjmp.c               |   1 +
>>   sysdeps/loongarch/dl-machine.h               | 287 +++++++++++++++++++
>>   sysdeps/loongarch/dl-trampoline.S            |  91 ++++++
>>   sysdeps/loongarch/jmpbuf-offsets.h           |  22 ++
>>   sysdeps/loongarch/jmpbuf-unwind.h            |  45 +++
>>   sysdeps/loongarch/ldsodefs.h                 |  41 +++
>>   sysdeps/loongarch/linkmap.h                  |  22 ++
>>   sysdeps/loongarch/machine-gmon.h             |  37 +++
>>   sysdeps/loongarch/setjmp.S                   |  66 +++++
>>   sysdeps/loongarch/sotruss-lib.c              |  50 ++++
>>   sysdeps/loongarch/start.S                    |  66 +++++
>>   sysdeps/loongarch/sys/asm.h                  |  59 ++++
>>   sysdeps/loongarch/tst-audit.h                |  23 ++
>>   sysdeps/unix/sysv/linux/loongarch/ldconfig.h |  26 ++
>>   19 files changed, 1000 insertions(+)
>>   create mode 100644 sysdeps/loongarch/__longjmp.S
>>   create mode 100644 sysdeps/loongarch/bits/endianness.h
>>   create mode 100644 sysdeps/loongarch/bits/link.h
>>   create mode 100644 sysdeps/loongarch/bits/setjmp.h
>>   create mode 100644 sysdeps/loongarch/bsd-_setjmp.c
>>   create mode 100644 sysdeps/loongarch/bsd-setjmp.c
>>   create mode 100644 sysdeps/loongarch/dl-machine.h
>>   create mode 100644 sysdeps/loongarch/dl-trampoline.S
>>   create mode 100644 sysdeps/loongarch/jmpbuf-offsets.h
>>   create mode 100644 sysdeps/loongarch/jmpbuf-unwind.h
>>   create mode 100644 sysdeps/loongarch/ldsodefs.h
>>   create mode 100644 sysdeps/loongarch/linkmap.h
>>   create mode 100644 sysdeps/loongarch/machine-gmon.h
>>   create mode 100644 sysdeps/loongarch/setjmp.S
>>   create mode 100644 sysdeps/loongarch/sotruss-lib.c
>>   create mode 100644 sysdeps/loongarch/start.S
>>   create mode 100644 sysdeps/loongarch/sys/asm.h
>>   create mode 100644 sysdeps/loongarch/tst-audit.h
>>   create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldconfig.h
>>
>> diff --git a/sysdeps/loongarch/__longjmp.S 
>> b/sysdeps/loongarch/__longjmp.S
>> new file mode 100644
>> index 0000000000..b7690dd94f
>> --- /dev/null
>> +++ b/sysdeps/loongarch/__longjmp.S
>> @@ -0,0 +1,52 @@
>> +/* longjmp.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <sysdep.h>
>> +#include <sys/asm.h>
>> +
>> +ENTRY (__longjmp)
>> +    REG_L ra, a0, 0*SZREG
>> +    REG_L sp, a0, 1*SZREG
>> +    REG_L x,  a0, 2*SZREG
>> +    REG_L fp, a0, 3*SZREG
>> +    REG_L s0, a0, 4*SZREG
>> +    REG_L s1, a0, 5*SZREG
>> +    REG_L s2, a0, 6*SZREG
>> +    REG_L s3, a0, 7*SZREG
>> +    REG_L s4, a0, 8*SZREG
>> +    REG_L s5, a0, 9*SZREG
>> +    REG_L s6, a0, 10*SZREG
>> +    REG_L s7, a0, 11*SZREG
>> +    REG_L s8, a0, 12*SZREG
>> +
>> +#ifndef __loongarch_soft_float
>
> The softfp is explicit disabled, so I think checking it on code does
> not add much.  Once softfp is actually enabled we can add it back, it
> also make is explicit in history what was required to enable the abi.
>
>> +    FREG_L $f24, a0, 13*SZREG + 0*SZFREG
>> +    FREG_L $f25, a0, 13*SZREG + 1*SZFREG
>> +    FREG_L $f26, a0, 13*SZREG + 2*SZFREG
>> +    FREG_L $f27, a0, 13*SZREG + 3*SZFREG
>> +    FREG_L $f28, a0, 13*SZREG + 4*SZFREG
>> +    FREG_L $f29, a0, 13*SZREG + 5*SZFREG
>> +    FREG_L $f30, a0, 13*SZREG + 6*SZFREG
>> +    FREG_L $f31, a0, 13*SZREG + 7*SZFREG
>> +#endif
>> +
>> +    sltui    a0,a1,1
>> +    ADD    a0, a0, a1     # a0 = (a1 == 0) ? 1 : a1
>> +    jirl    zero,ra,0
>> +
>> +END (__longjmp)
>> diff --git a/sysdeps/loongarch/bits/endianness.h 
>> b/sysdeps/loongarch/bits/endianness.h
>> new file mode 100644
>> index 0000000000..7290be7b18
>> --- /dev/null
>> +++ b/sysdeps/loongarch/bits/endianness.h
>> @@ -0,0 +1,11 @@
>> +#ifndef _BITS_ENDIANNESS_H
>> +#define _BITS_ENDIANNESS_H 1
>> +
>> +#ifndef _BITS_ENDIAN_H
>> +#error "Never use <bits/endianness.h> directly; include <endian.h> 
>> instead."
>> +#endif
>> +
>> +/* LoongArch is little-endian.  */
>> +#define __BYTE_ORDER __LITTLE_ENDIAN
>> +
>> +#endif /* bits/endianness.h */
>> diff --git a/sysdeps/loongarch/bits/link.h 
>> b/sysdeps/loongarch/bits/link.h
>> new file mode 100644
>> index 0000000000..05c91575e9
>> --- /dev/null
>> +++ b/sysdeps/loongarch/bits/link.h
>> @@ -0,0 +1,58 @@
>> +/* Machine-specific declarations for dynamic linker interface.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef _LINK_H
>> +#error "Never include <bits/link.h> directly; use <link.h> instead."
>> +#endif
>> +
>> +typedef struct La_loongarch_regs
>> +{
>> +  unsigned long int lr_reg[8]; /* a0 - a7 */
>> +  double lr_fpreg[8];           /* fa0 - fa7 */
>> +  unsigned long int lr_ra;
>> +  unsigned long int lr_sp;
>> +} La_loongarch_regs;
>> +
>> +/* Return values for calls from PLT on LoongArch.  */
>> +typedef struct La_loongarch_retval
>> +{
>> +  unsigned long int lrv_a0;
>> +  unsigned long int lrv_a1;
>> +  double lrv_fa0;
>> +  double lrv_fa1;
>> +} La_loongarch_retval;
>> +
>> +__BEGIN_DECLS
>> +
>> +extern ElfW (Addr) la_loongarch_gnu_pltenter (ElfW (Sym) *__sym,
>> +                          unsigned int __ndx,
>> +                          uintptr_t *__refcook,
>> +                          uintptr_t *__defcook,
>> +                          La_loongarch_regs *__regs,
>> +                          unsigned int *__flags,
>> +                          const char *__symname,
>> +                          long int *__framesizep);
>> +extern unsigned int la_loongarch_gnu_pltexit (ElfW (Sym) *__sym,
>> +                          unsigned int __ndx,
>> +                          uintptr_t *__refcook,
>> +                          uintptr_t *__defcook,
>> +                          const La_loongarch_regs *__inregs,
>> +                          La_loongarch_retval *__outregs,
>> +                          const char *__symname);
>> +
>> +__END_DECLS
>> diff --git a/sysdeps/loongarch/bits/setjmp.h 
>> b/sysdeps/loongarch/bits/setjmp.h
>> new file mode 100644
>> index 0000000000..8b323ad2b6
>> --- /dev/null
>> +++ b/sysdeps/loongarch/bits/setjmp.h
>> @@ -0,0 +1,42 @@
>> +/* Define the machine-dependent type `jmp_buf'.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef _LOONGARCH_BITS_SETJMP_H
>> +#define _LOONGARCH_BITS_SETJMP_H
>> +
>> +typedef struct __jmp_buf_internal_tag
>> +{
>> +  /* Program counter.  */
>> +  long int __pc;
>> +  /* Stack pointer.  */
>> +  long int __sp;
>> +  /* Reserved */
>> +  long int __x;
>> +  /* Frame pointer.  */
>> +  long int __fp;
>> +  /* Callee-saved registers.  */
>> +  long int __regs[9];
>> +
>> +#ifndef __loongarch_soft_float
>> +  /* Callee-saved floating point registers.  */
>> +  double __fpregs[8];
>> +#endif
>
> Same as before.
>
>> +
>> +} __jmp_buf[1];
>> +
>> +#endif /* _LOONGARCH_BITS_SETJMP_H */
>> diff --git a/sysdeps/loongarch/bsd-_setjmp.c 
>> b/sysdeps/loongarch/bsd-_setjmp.c
>> new file mode 100644
>> index 0000000000..32f49441c3
>> --- /dev/null
>> +++ b/sysdeps/loongarch/bsd-_setjmp.c
>> @@ -0,0 +1 @@
>> +/* _setjmp is implemented in setjmp.S.  */
>> diff --git a/sysdeps/loongarch/bsd-setjmp.c 
>> b/sysdeps/loongarch/bsd-setjmp.c
>> new file mode 100644
>> index 0000000000..45fd802aac
>> --- /dev/null
>> +++ b/sysdeps/loongarch/bsd-setjmp.c
>> @@ -0,0 +1 @@
>> +/* setjmp is implemented in setjmp.S.  */
>> diff --git a/sysdeps/loongarch/dl-machine.h 
>> b/sysdeps/loongarch/dl-machine.h
>> new file mode 100644
>> index 0000000000..a615e6774a
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-machine.h
>> @@ -0,0 +1,287 @@
>> +/* Machine-dependent ELF dynamic relocation inline functions.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef dl_machine_h
>> +#define dl_machine_h
>> +
>> +#define ELF_MACHINE_NAME "LoongArch"
>> +
>> +#include <entry.h>
>> +#include <elf/elf.h>
>> +#include <sys/asm.h>
>> +#include <dl-tls.h>
>> +#include <dl-static-tls.h>
>> +#include <dl-machine-rel.h>
>> +
>> +#ifndef _RTLD_PROLOGUE
>> +# define _RTLD_PROLOGUE(entry)                    \
>> +    ".globl\t" __STRING (entry) "\n\t"            \
>> +    ".type\t" __STRING (entry) ", @function\n\t"        \
>> +    CFI_STARTPROC "\n"                    \
>> +    __STRING (entry) ":\n"
>> +#endif
>> +
>> +#ifndef _RTLD_EPILOGUE
>> +# define _RTLD_EPILOGUE(entry)                    \
>> +    CFI_ENDPROC "\n\t"                    \
>> +    ".size\t" __STRING (entry) ", . - " __STRING (entry) "\n"
>> +#endif
>> +
>> +#define ELF_MACHINE_JMP_SLOT R_LARCH_JUMP_SLOT
>> +#define ELF_MACHINE_IRELATIVE R_LARCH_IRELATIVE
>> +
>> +#define elf_machine_type_class(type)                \
>> +  ((ELF_RTYPE_CLASS_PLT *((type) == ELF_MACHINE_JMP_SLOT))    \
>> +   | (ELF_RTYPE_CLASS_COPY *((type) == R_LARCH_COPY)))
>> +
>> +#define ELF_MACHINE_NO_REL 1
>> +#define ELF_MACHINE_NO_RELA 0
>> +
>> +/* Return nonzero iff ELF header is compatible with the running 
>> host.  */
>> +static inline int
>> +elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
>> +{
>> +  /* We can only run LoongArch binaries.  */
>> +  if (ehdr->e_machine != EM_LOONGARCH)
>> +    return 0;
>> +
>> +  return 1;
>> +}
>> +
>> +/* Return the run-time load address of the shared object.  */
>> +static inline ElfW (Addr) elf_machine_load_address (void)
>> +{
>> +  extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
>> +  return (ElfW(Addr)) &__ehdr_start;
>> +}
>> +
>> +/* Return the link-time address of _DYNAMIC.  */
>> +static inline ElfW (Addr) elf_machine_dynamic (void)
>> +{
>> +  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
>> +  return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
>> +}
>> +
>> +/* Initial entry point code for the dynamic linker.
>> +   The C function `_dl_start' is the real entry point;
>> +   its return value is the user program's entry point.  */
>> +
>> +#define RTLD_START \
>> +  asm(".text\n\
>> +      " _RTLD_PROLOGUE (ENTRY_POINT) "\
>> +      .cfi_label .Ldummy   \n\
>> +      " CFI_UNDEFINED (1) "   \n\
>> +      or    $a0, $sp, $zero   \n\
>> +      bl    _dl_start   \n\
>> +      # Stash user entry point in s0.   \n\
>> +      or    $s0, $v0, $zero   \n\
>> +      # Load the original argument count.   \n\
>> +      ld.d    $a1, $sp, 0   \n\
>> +      # Call _dl_init (struct link_map *main_map, int argc, char 
>> **argv, \
>> +               char **env)    \n\
>> +      la    $a0, _rtld_local   \n\
>> +      ld.d    $a0, $a0, 0   \n\
>> +      addi.d    $a2, $sp, 8   \n\
>> +      slli.d    $a3, $a1, 3   \n\
>> +      add.d    $a3, $a3, $a2   \n\
>> +      addi.d    $a3, $a3, 8   \n\
>> +      # Stash the stack pointer in s1.\n\
>> +      or    $s1, $sp, $zero    \n\
>> +      # Adjust $sp for 16-aligned   \n\
>> +      bstrins.d    $sp, $zero, 3, 0  \n\
>> +      # Call the function to run the initializers.   \n\
>> +      bl    _dl_init   \n\
>> +      # Restore the stack pointer for _start.\n\
>> +      or    $sp, $s1, $zero     \n\
>> +      # Pass our finalizer function to _start.   \n\
>> +      la    $a0, _dl_fini   \n\
>> +      # Jump to the user entry point.   \n\
>> +      jirl    $zero, $s0, 0   \n\
>> +      " _RTLD_EPILOGUE (ENTRY_POINT) "\
>> +      .previous");
>> +
>> +/* Names of the architecture-specific auditing callback functions.  */
>> +#define ARCH_LA_PLTENTER loongarch_gnu_pltenter
>> +#define ARCH_LA_PLTEXIT loongarch_gnu_pltexit
>> +
>> +/* Bias .got.plt entry by the offset requested by the PLT header.  */
>> +#define elf_machine_plt_value(map, reloc, value) (value)
>> +
>> +static inline ElfW (Addr)
>> +elf_machine_fixup_plt (struct link_map *map, lookup_t t,
>> +             const ElfW (Sym) *refsym, const ElfW (Sym) *sym,
>> +             const ElfW (Rela) *reloc, ElfW (Addr) *reloc_addr,
>> +             ElfW (Addr) value)
>> +{
>> +  return *reloc_addr = value;
>> +}
>> +
>> +#endif /* !dl_machine_h */
>> +
>> +#ifdef RESOLVE_MAP
>> +
>> +/* Perform a relocation described by R_INFO at the location pointed to
>> +   by RELOC_ADDR.  SYM is the relocation symbol specified by R_INFO and
>> +   MAP is the object containing the reloc.  */
>> +
>> +static inline void __attribute__ ((always_inline))
>> +elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
>> +          const ElfW (Rela) *reloc,
>> +          const ElfW (Sym) *sym,
>> +          const struct r_found_version *version,
>> +          void *const reloc_addr, int skip_ifunc)
>> +{
>> +  ElfW (Addr) r_info = reloc->r_info;
>> +  const unsigned long int r_type = ELFW (R_TYPE) (r_info);
>> +  ElfW (Addr) *addr_field = (ElfW (Addr) *) reloc_addr;
>> +  const ElfW (Sym) *const __attribute__ ((unused)) refsym = sym;
>> +  struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, 
>> r_type);
>> +  ElfW (Addr) value = 0;
>> +  if (sym_map != NULL)
>> +    value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
>> +
>> +  if (sym != NULL
>> +      && __glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == 
>> STT_GNU_IFUNC)
>> +      && __glibc_likely (sym->st_shndx != SHN_UNDEF)
>> +      && __glibc_likely (!skip_ifunc))
>> +    value = ((ElfW (Addr) (*) (int)) value) (GLRO (dl_hwcap));
>> +
>> +  switch (r_type)
>> +    {
>> +
>> +    case R_LARCH_JUMP_SLOT:
>> +    case __WORDSIZE == 64 ? R_LARCH_64:
>> +    R_LARCH_32:
>> +      *addr_field = value;
>> +      break;
>> +
>> +#ifndef RTLD_BOOTSTRAP
>> +    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64:
>> +    R_LARCH_TLS_DTPMOD32:
>> +      *addr_field = sym_map->l_tls_modid;
>> +      break;
>> +
>> +    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64:
>> +    R_LARCH_TLS_DTPREL32:
>> +      *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
>> +      break;
>> +
>> +    case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64:
>> +    R_LARCH_TLS_TPREL32:
>> +      CHECK_STATIC_TLS (map, sym_map);
>> +      *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
>> +      break;
>> +
>> +    case R_LARCH_COPY:
>> +      {
>> +      if (sym == NULL)
>> +        /* This can happen in trace mode if an object could not be
>> +           found.  */
>> +        break;
>> +      if (__glibc_unlikely (sym->st_size > refsym->st_size)
>> +          || (__glibc_unlikely (sym->st_size < refsym->st_size)
>> +        && GLRO(dl_verbose)))
>> +      {
>> +        const char *strtab;
>> +
>> +        strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
>> +        _dl_error_printf ("\
>> +%s: Symbol `%s' has different size in shared object, consider 
>> re-linking\n",
>> +        rtld_progname ?: "<program name unknown>",
>> +        strtab + refsym->st_name);
>> +      }
>> +      memcpy (reloc_addr, (void *) value,
>> +          MIN (sym->st_size, refsym->st_size));
>> +        break;
>> +      }
>> +
>> +    case R_LARCH_RELATIVE:
>> +      *addr_field = map->l_addr + reloc->r_addend;
>> +      break;
>> +
>> +    case R_LARCH_IRELATIVE:
>> +      value = map->l_addr + reloc->r_addend;
>> +      if (__glibc_likely (!skip_ifunc))
>> +    value = ((ElfW (Addr) (*) (void)) value) ();
>> +      *addr_field = value;
>> +      break;
>> +
>> +    case R_LARCH_NONE:
>> +      break;
>> +#endif
>
> From previous discussion, R_LARCH_NONE dynamic relocations should be 
> considered missing optimization (assuming input unrecognizable 
> relocations are handled in static linker).  Since not handling it on
> bootstrap generates unusable loader, I think it would be better to
> handle on for RTLD_BOOTSTRAP.
>
>> +
>> +    default:
>> +      _dl_reloc_bad_type (map, r_type, 0);
>> +      break;
>> +    }
>> +}
>> +
>> +static inline void __attribute__ ((always_inline))
>> +elf_machine_rela_relative (ElfW (Addr) l_addr, const ElfW (Rela) 
>> *reloc,
>> +               void *const reloc_addr)
>> +{
>> +  *(ElfW (Addr) *) reloc_addr = l_addr + reloc->r_addend;
>> +}
>> +
>> +static inline void __attribute__ ((always_inline))
>> +elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem 
>> *scope[],
>> +              ElfW (Addr) l_addr,
>> +              const ElfW (Rela) *reloc, int skip_ifunc)
>> +{
>> +  ElfW (Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
>> +  const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
>> +
>> +  /* Check for unexpected PLT reloc type.  */
>> +  if (__glibc_likely (r_type == R_LARCH_JUMP_SLOT))
>> +    {
>> +      if (__glibc_unlikely (map->l_mach.plt == 0))
>> +    {
>> +      if (l_addr)
>> +        *reloc_addr += l_addr;
>> +    }
>> +      else
>> +    *reloc_addr = map->l_mach.plt;
>> +    }
>> +  else
>> +    _dl_reloc_bad_type (map, r_type, 1);
>> +}
>> +
>> +/* Set up the loaded object described by L so its stub function
>> +   will jump to the on-demand fixup code __dl_runtime_resolve. */
>> +
>> +static inline int __attribute__ ((always_inline))
>> +elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem 
>> *scope[],
>> +               int lazy, int profile)
>> +{
>> +#ifndef RTLD_BOOTSTRAP
>> +  /* If using PLTs, fill in the first two entries of .got.plt. */
>> +  if (l->l_info[DT_JMPREL])
>> +    {
>> +      extern void _dl_runtime_resolve (void)
>> +    __attribute__ ((visibility ("hidden")));
>> +      ElfW (Addr) *gotplt = (ElfW (Addr) *) D_PTR (l, 
>> l_info[DT_PLTGOT]);
>> +      gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve;
>> +      gotplt[1] = (ElfW (Addr)) l;
>> +    }
>> +#endif
>> +
>> +  return lazy;
>> +}
>> +
>> +#endif /* RESOLVE_MAP */
>> diff --git a/sysdeps/loongarch/dl-trampoline.S 
>> b/sysdeps/loongarch/dl-trampoline.S
>> new file mode 100644
>> index 0000000000..eb610392f6
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-trampoline.S
>> @@ -0,0 +1,91 @@
>> +/* PLT trampolines.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <sysdep.h>
>> +#include <sys/asm.h>
>> +
>> +/* Assembler veneer called from the PLT header code for lazy loading.
>> +   The PLT header passes its own args in t0-t2.  */
>> +
>> +#ifdef __loongarch_soft_float
>> +# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
>> +#else
>> +# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
>> +#endif
>> +
>> +ENTRY (_dl_runtime_resolve)
>> +
>> +    /* Save arguments to stack. */
>> +    ADDI    sp, sp, -FRAME_SIZE
>> +
>> +    REG_S    ra, sp, 9*SZREG
>> +    REG_S    a0, sp, 1*SZREG
>> +    REG_S    a1, sp, 2*SZREG
>> +    REG_S    a2, sp, 3*SZREG
>> +    REG_S    a3, sp, 4*SZREG
>> +    REG_S    a4, sp, 5*SZREG
>> +    REG_S    a5, sp, 6*SZREG
>> +    REG_S    a6, sp, 7*SZREG
>> +    REG_S    a7, sp, 8*SZREG
>> +
>> +#ifndef __loongarch_soft_float
>
> Same as before.
>
>> +    FREG_S    fa0, sp, 10*SZREG + 0*SZFREG
>> +    FREG_S    fa1, sp, 10*SZREG + 1*SZFREG
>> +    FREG_S    fa2, sp, 10*SZREG + 2*SZFREG
>> +    FREG_S    fa3, sp, 10*SZREG + 3*SZFREG
>> +    FREG_S    fa4, sp, 10*SZREG + 4*SZFREG
>> +    FREG_S    fa5, sp, 10*SZREG + 5*SZFREG
>> +    FREG_S    fa6, sp, 10*SZREG + 6*SZFREG
>> +    FREG_S    fa7, sp, 10*SZREG + 7*SZFREG
>> +#endif
>> +
>> +    /* Update .got.plt and obtain runtime address of callee */
>> +    SLLI    a1, t1, 1
>> +    or    a0, t0, zero
>> +    ADD    a1, a1, t1
>> +    la    a2, _dl_fixup
>> +    jirl    ra, a2, 0
>> +    or    t1, v0, zero
>> +
>> +    /* Restore arguments from stack. */
>> +    REG_L    ra, sp, 9*SZREG
>> +    REG_L    a0, sp, 1*SZREG
>> +    REG_L    a1, sp, 2*SZREG
>> +    REG_L    a2, sp, 3*SZREG
>> +    REG_L    a3, sp, 4*SZREG
>> +    REG_L    a4, sp, 5*SZREG
>> +    REG_L    a5, sp, 6*SZREG
>> +    REG_L    a6, sp, 7*SZREG
>> +    REG_L    a7, sp, 8*SZREG
>> +
>> +#ifndef __loongarch_soft_float
>
> Same as before.
>
>> +    FREG_L    fa0, sp, 10*SZREG + 0*SZFREG
>> +    FREG_L    fa1, sp, 10*SZREG + 1*SZFREG
>> +    FREG_L    fa2, sp, 10*SZREG + 2*SZFREG
>> +    FREG_L    fa3, sp, 10*SZREG + 3*SZFREG
>> +    FREG_L    fa4, sp, 10*SZREG + 4*SZFREG
>> +    FREG_L    fa5, sp, 10*SZREG + 5*SZFREG
>> +    FREG_L    fa6, sp, 10*SZREG + 6*SZFREG
>> +    FREG_L    fa7, sp, 10*SZREG + 7*SZFREG
>> +#endif
>> +
>> +    ADDI    sp, sp, FRAME_SIZE
>> +
>> +    /* Invoke the callee. */
>> +    jirl        zero, t1, 0
>> +END (_dl_runtime_resolve)
>> diff --git a/sysdeps/loongarch/jmpbuf-offsets.h 
>> b/sysdeps/loongarch/jmpbuf-offsets.h
>> new file mode 100644
>> index 0000000000..a4b8ea690e
>> --- /dev/null
>> +++ b/sysdeps/loongarch/jmpbuf-offsets.h
>> @@ -0,0 +1,22 @@
>> +/* Private macros for accessing __jmp_buf contents.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public 
>> License as
>> +   published by the Free Software Foundation; either version 2.1 of the
>> +   License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <jmpbuf-unwind.h>
>> +
>> +/* Helper for generic ____longjmp_chk().  */
>> +#define JB_FRAME_ADDRESS(buf) ((void *) _jmpbuf_sp (buf))
>> diff --git a/sysdeps/loongarch/jmpbuf-unwind.h 
>> b/sysdeps/loongarch/jmpbuf-unwind.h
>> new file mode 100644
>> index 0000000000..6fa509151d
>> --- /dev/null
>> +++ b/sysdeps/loongarch/jmpbuf-unwind.h
>> @@ -0,0 +1,45 @@
>> +/* Examine __jmp_buf for unwinding frames.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <setjmp.h>
>> +#include <stdint.h>
>> +#include <unwind.h>
>> +#include <sysdep.h>
>> +
>> +/* Test if longjmp to JMPBUF would unwind the frame
>> +   containing a local variable at ADDRESS.  */
>> +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
>> +  ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
>> +
>> +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
>> +  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), 
>> _adj)
>> +
>> +static inline uintptr_t __attribute__ ((unused)) _jmpbuf_sp 
>> (__jmp_buf regs)
>> +{
>> +  uintptr_t sp = regs[0].__sp;
>> +#ifdef PTR_DEMANGLE
>> +  PTR_DEMANGLE (sp);
>> +#endif
>> +  return sp;
>> +}
>> +
>> +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
>> +  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
>> +
>> +/* We use the normal longjmp for unwinding.  */
>> +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
>> diff --git a/sysdeps/loongarch/ldsodefs.h b/sysdeps/loongarch/ldsodefs.h
>> new file mode 100644
>> index 0000000000..36b1b25b9f
>> --- /dev/null
>> +++ b/sysdeps/loongarch/ldsodefs.h
>> @@ -0,0 +1,41 @@
>> +/* Run-time dynamic linker data structures for loaded ELF shared 
>> objects.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef _LOONGARCH_LDSODEFS_H
>> +#define _LOONGARCH_LDSODEFS_H 1
>> +
>> +#include <elf.h>
>> +
>> +struct La_loongarch_regs;
>> +struct La_loongarch_retval;
>> +
>> +#define ARCH_PLTENTER_MEMBERS \
>> +  ElfW (Addr) (*loongarch_gnu_pltenter) (ElfW (Sym) *, unsigned int, \
>> +                     uintptr_t *, uintptr_t *, \
>> +                     const struct La_loongarch_regs *, \
>> +                     unsigned int *, const char *name, \
>> +                     long int *framesizep);
>> +
>> +#define ARCH_PLTEXIT_MEMBERS \
>> +  unsigned int (*loongarch_gnu_pltexit) (ElfW (Sym) *, unsigned int, \
>> +        uintptr_t *, uintptr_t *, const struct La_loongarch_regs *, \
>> +        struct La_loongarch_retval *, const char *);
>> +
>> +#include_next <ldsodefs.h>
>> +
>> +#endif
>> diff --git a/sysdeps/loongarch/linkmap.h b/sysdeps/loongarch/linkmap.h
>> new file mode 100644
>> index 0000000000..bbba73ed70
>> --- /dev/null
>> +++ b/sysdeps/loongarch/linkmap.h
>> @@ -0,0 +1,22 @@
>> +/* Definition of link_map_machine.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +struct link_map_machine
>> +{
>> +  ElfW (Addr) plt; /* Address of .plt.  */
>> +};
>> diff --git a/sysdeps/loongarch/machine-gmon.h 
>> b/sysdeps/loongarch/machine-gmon.h
>> new file mode 100644
>> index 0000000000..4a3cdd964e
>> --- /dev/null
>> +++ b/sysdeps/loongarch/machine-gmon.h
>> @@ -0,0 +1,37 @@
>> +/* LoongArch definitions for profiling support.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +/* Accept 'frompc' address as argument from the function that calls
>> +   _mcount for profiling.  Use  __builtin_return_address (0)
>> +   for the 'selfpc' address.  */
>> +
>> +#include <sysdep.h>
>> +
>> +static void mcount_internal (unsigned long int frompc,
>> +                 unsigned long int selfpc);
>> +
>> +#define _MCOUNT_DECL(frompc, selfpc) \
>> +  static inline void mcount_internal (unsigned long int frompc, \
>> +                      unsigned long int selfpc)
>> +
>> +#define MCOUNT \
>> +  void _mcount (void *frompc) \
>> +  { \
>> +    mcount_internal ((unsigned long int) frompc, \
>> +             (unsigned long int) RETURN_ADDRESS (0)); \
>> +  }
>> diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
>> new file mode 100644
>> index 0000000000..c081ff6b87
>> --- /dev/null
>> +++ b/sysdeps/loongarch/setjmp.S
>> @@ -0,0 +1,66 @@
>> +/* setjmp for LoongArch.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <sysdep.h>
>> +#include <sys/asm.h>
>> +
>> +ENTRY (_setjmp)
>> +    li.w        a1,0
>> +    b        HIDDEN_JUMPTARGET (__sigsetjmp)
>> +END (_setjmp)
>> +
>> +ENTRY (setjmp)
>> +    li.w        a1,1
>> +END (setjmp)
>> +
>> +ENTRY (__sigsetjmp)
>> +    REG_S ra, a0, 0*SZREG
>> +    REG_S sp, a0, 1*SZREG
>> +    REG_S x,  a0, 2*SZREG
>> +    REG_S fp, a0, 3*SZREG
>> +    REG_S s0, a0, 4*SZREG
>> +    REG_S s1, a0, 5*SZREG
>> +    REG_S s2, a0, 6*SZREG
>> +    REG_S s3, a0, 7*SZREG
>> +    REG_S s4, a0, 8*SZREG
>> +    REG_S s5, a0, 9*SZREG
>> +    REG_S s6, a0, 10*SZREG
>> +    REG_S s7, a0, 11*SZREG
>> +    REG_S s8, a0, 12*SZREG
>> +
>> +#ifndef __loongarch_soft_float
>> +    FREG_S $f24, a0, 13*SZREG + 0*SZFREG
>> +    FREG_S $f25, a0, 13*SZREG + 1*SZFREG
>> +    FREG_S $f26, a0, 13*SZREG + 2*SZFREG
>> +    FREG_S $f27, a0, 13*SZREG + 3*SZFREG
>> +    FREG_S $f28, a0, 13*SZREG + 4*SZFREG
>> +    FREG_S $f29, a0, 13*SZREG + 5*SZFREG
>> +    FREG_S $f30, a0, 13*SZREG + 6*SZFREG
>> +    FREG_S $f31, a0, 13*SZREG + 7*SZFREG
>> +#endif
>> +
>> +#if !IS_IN (libc) && IS_IN(rtld)
>> +    li.w        v0, 0
>> +    jirl        zero,ra,0
>> +#else
>> +    b        __sigjmp_save
>> +#endif
>> +END (__sigsetjmp)
>> +
>> +hidden_def (__sigsetjmp)
>> +weak_alias (_setjmp, __GI__setjmp)
>> diff --git a/sysdeps/loongarch/sotruss-lib.c 
>> b/sysdeps/loongarch/sotruss-lib.c
>> new file mode 100644
>> index 0000000000..ce752785f6
>> --- /dev/null
>> +++ b/sysdeps/loongarch/sotruss-lib.c
>> @@ -0,0 +1,50 @@
>> +/* Override generic sotruss-lib.c to define actual functions for 
>> LoongArch.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#define HAVE_ARCH_PLTENTER
>> +#define HAVE_ARCH_PLTEXIT
>> +
>> +#include <elf/sotruss-lib.c>
>> +
>> +ElfW (Addr)
>> +la_loongarch_gnu_pltenter (ElfW (Sym) *sym __attribute__ ((unused)),
>> +               unsigned int ndx __attribute__ ((unused)),
>> +               uintptr_t *refcook, uintptr_t *defcook,
>> +               La_loongarch_regs *regs, unsigned int *flags,
>> +               const char *symname, long int *framesizep)
>> +{
>> +  print_enter (refcook, defcook, symname, regs->lr_reg[0], 
>> regs->lr_reg[1],
>> +           regs->lr_reg[2], *flags);
>> +
>> +  /* No need to copy anything, we will not need the parameters in 
>> any case.  */
>> +  *framesizep = 0;
>> +
>> +  return sym->st_value;
>> +}
>> +
>> +unsigned int
>> +la_loongarch_gnu_pltexit (ElfW (Sym) *sym, unsigned int ndx,
>> +              uintptr_t *refcook, uintptr_t *defcook,
>> +              const struct La_loongarch_regs *inregs,
>> +              struct La_loongarch_retval *outregs,
>> +              const char *symname)
>> +{
>> +  print_exit (refcook, defcook, symname, outregs->lrv_a0);
>> +
>> +  return 0;
>> +}
>> diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
>> new file mode 100644
>> index 0000000000..280b5fab8c
>> --- /dev/null
>> +++ b/sysdeps/loongarch/start.S
>> @@ -0,0 +1,66 @@
>> +/* Startup code compliant to the ELF LoongArch ABI.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#define __ASSEMBLY__ 1
>> +#include <entry.h>
>> +#include <sys/asm.h>
>> +
>> +/* The entry point's job is to call __libc_start_main.  Per the ABI,
>> +   a0 contains the address of a function to be passed to atexit.
>> +   __libc_start_main wants this in a5.  */
>> +
>> +/*
>> +int
>> +__libc_start_main (int (*main) (int, char **, char **),
>> +           int argc,
>> +           char **argv,
>> +           __typeof (main) init,
>> +           void (*fini) (void),
>> +           void (*rtld_fini) (void),
>> +           void *stack_end);
>> + */
>> +
>> +ENTRY (ENTRY_POINT)
>> +
>> +/* Terminate call stack by noting ra is undefined.  Use a dummy
>> +   .cfi_label to force starting the FDE.  */
>> +    .cfi_label .Ldummy
>> +    cfi_undefined (1)
>> +    or        a5, a0, zero /* rtld_fini */
>> +
>> +/* We must get symbol main through GOT table, since main may not be 
>> local.
>> +   For instance: googletest defines main in dynamic library. */
>> +    la.got        a0, t0, main
>> +    REG_L        a1, sp, 0
>> +    ADDI        a2, sp, SZREG
>> +
>> +    /* Adjust $sp for 16-aligned */
>> +    BSTRINS        sp, zero, 3, 0
>> +
>> +    move        a3, zero /* used to be init */
>> +    move        a4, zero /* used to be fini */
>> +    or        a6, sp, zero /* stack_end */
>> +
>> +    la.got        ra, t0, __libc_start_main
>> +    jirl        ra, ra, 0
>> +
>> +    la.got        ra, t0, abort
>> +    jirl        ra, ra, 0
>> +END (ENTRY_POINT)
>> +
>> diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h
>> new file mode 100644
>> index 0000000000..b41ee59694
>> --- /dev/null
>> +++ b/sysdeps/loongarch/sys/asm.h
>> @@ -0,0 +1,59 @@
>> +/* Miscellaneous macros.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#ifndef _SYS_ASM_H
>> +#define _SYS_ASM_H
>> +
>> +#include <sys/regdef.h>
>> +#include <sysdeps/generic/sysdep.h>
>> +
>> +/* Macros to handle different pointer/register sizes for 32/64-bit 
>> code.  */
>> +#define SZREG 8
>> +#define SZFREG 8
>> +#define REG_L ld.d
>> +#define REG_S st.d
>> +#define SRLI srli.d
>> +#define SLLI slli.d
>> +#define ADDI addi.d
>> +#define ADD  add.d
>> +#define BSTRINS  bstrins.d
>> +#define LI  li.d
>> +#define FREG_L fld.d
>> +#define FREG_S fst.d
>> +
>> +/* Declare leaf routine.  */
>> +#define LEAF(symbol) \
>> +  .text; \
>> +  .globl symbol; \
>> +  .align 3; \
>> +  cfi_startproc; \
>> +  .type symbol, @function; \
>> +  symbol:
>> +
>> +#define ENTRY(symbol) LEAF (symbol)
>> +
>> +/* Mark end of function.  */
>> +#undef END
>> +#define END(function) \
>> +  cfi_endproc; \
>> +  .size function, .- function;
>> +
>> +/* Stack alignment.  */
>> +#define ALMASK ~15
>> +
>> +#endif /* sys/asm.h */
>> diff --git a/sysdeps/loongarch/tst-audit.h 
>> b/sysdeps/loongarch/tst-audit.h
>> new file mode 100644
>> index 0000000000..e71948c86e
>> --- /dev/null
>> +++ b/sysdeps/loongarch/tst-audit.h
>> @@ -0,0 +1,23 @@
>> +/* Definitions for testing PLT entry/exit auditing.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#define pltenter la_loongarch_gnu_pltenter
>> +#define pltexit la_loongarch_gnu_pltexit
>> +#define La_regs La_loongarch_regs
>> +#define La_retval La_loongarch_retval
>> +#define int_retval lrv_a0
>> diff --git a/sysdeps/unix/sysv/linux/loongarch/ldconfig.h 
>> b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
>> new file mode 100644
>> index 0000000000..4887c30ca2
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
>> @@ -0,0 +1,26 @@
>> +/* ldconfig default paths and libraries.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library.  If not, see
>> + <http://www.gnu.org/licenses/>. */
>> +
>> +#include <sysdeps/generic/ldconfig.h>
>> +
>> +#define SYSDEP_KNOWN_INTERPRETER_NAMES \
>> +  { "/lib64/ld-linux-loongarch-lp64d.so.1", FLAG_ELF_LIBC6 },
>> +
>> +#define SYSDEP_KNOWN_LIBRARY_NAMES    \
>> +  { "libc.so.6", FLAG_ELF_LIBC6 },    \
>> +  { "libm.so.6", FLAG_ELF_LIBC6 },
>
> This file is not required and and the idea is to eventually remove
> it [1].  The default definitions already add the expected loader
> and libc names, so SYSDEP_KNOWN_INTERPRETER_NAMES and
> SYSDEP_KNOWN_LIBRARY_NAMES are redundant.
>
> [1] 
> https://patchwork.sourceware.org/project/glibc/patch/20220518130728.5cy6uutc5eiqxbwv@workbox/
  

Patch

diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S
new file mode 100644
index 0000000000..b7690dd94f
--- /dev/null
+++ b/sysdeps/loongarch/__longjmp.S
@@ -0,0 +1,52 @@ 
+/* longjmp.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+ENTRY (__longjmp)
+	REG_L ra, a0, 0*SZREG
+	REG_L sp, a0, 1*SZREG
+	REG_L x,  a0, 2*SZREG
+	REG_L fp, a0, 3*SZREG
+	REG_L s0, a0, 4*SZREG
+	REG_L s1, a0, 5*SZREG
+	REG_L s2, a0, 6*SZREG
+	REG_L s3, a0, 7*SZREG
+	REG_L s4, a0, 8*SZREG
+	REG_L s5, a0, 9*SZREG
+	REG_L s6, a0, 10*SZREG
+	REG_L s7, a0, 11*SZREG
+	REG_L s8, a0, 12*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_L $f24, a0, 13*SZREG + 0*SZFREG
+	FREG_L $f25, a0, 13*SZREG + 1*SZFREG
+	FREG_L $f26, a0, 13*SZREG + 2*SZFREG
+	FREG_L $f27, a0, 13*SZREG + 3*SZFREG
+	FREG_L $f28, a0, 13*SZREG + 4*SZFREG
+	FREG_L $f29, a0, 13*SZREG + 5*SZFREG
+	FREG_L $f30, a0, 13*SZREG + 6*SZFREG
+	FREG_L $f31, a0, 13*SZREG + 7*SZFREG
+#endif
+
+	sltui	a0,a1,1
+	ADD	a0, a0, a1	 # a0 = (a1 == 0) ? 1 : a1
+	jirl	zero,ra,0
+
+END (__longjmp)
diff --git a/sysdeps/loongarch/bits/endianness.h b/sysdeps/loongarch/bits/endianness.h
new file mode 100644
index 0000000000..7290be7b18
--- /dev/null
+++ b/sysdeps/loongarch/bits/endianness.h
@@ -0,0 +1,11 @@ 
+#ifndef _BITS_ENDIANNESS_H
+#define _BITS_ENDIANNESS_H 1
+
+#ifndef _BITS_ENDIAN_H
+#error "Never use <bits/endianness.h> directly; include <endian.h> instead."
+#endif
+
+/* LoongArch is little-endian.  */
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* bits/endianness.h */
diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h
new file mode 100644
index 0000000000..05c91575e9
--- /dev/null
+++ b/sysdeps/loongarch/bits/link.h
@@ -0,0 +1,58 @@ 
+/* Machine-specific declarations for dynamic linker interface.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LINK_H
+#error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+typedef struct La_loongarch_regs
+{
+  unsigned long int lr_reg[8]; /* a0 - a7 */
+  double lr_fpreg[8];	       /* fa0 - fa7 */
+  unsigned long int lr_ra;
+  unsigned long int lr_sp;
+} La_loongarch_regs;
+
+/* Return values for calls from PLT on LoongArch.  */
+typedef struct La_loongarch_retval
+{
+  unsigned long int lrv_a0;
+  unsigned long int lrv_a1;
+  double lrv_fa0;
+  double lrv_fa1;
+} La_loongarch_retval;
+
+__BEGIN_DECLS
+
+extern ElfW (Addr) la_loongarch_gnu_pltenter (ElfW (Sym) *__sym,
+					      unsigned int __ndx,
+					      uintptr_t *__refcook,
+					      uintptr_t *__defcook,
+					      La_loongarch_regs *__regs,
+					      unsigned int *__flags,
+					      const char *__symname,
+					      long int *__framesizep);
+extern unsigned int la_loongarch_gnu_pltexit (ElfW (Sym) *__sym,
+					      unsigned int __ndx,
+					      uintptr_t *__refcook,
+					      uintptr_t *__defcook,
+					      const La_loongarch_regs *__inregs,
+					      La_loongarch_retval *__outregs,
+					      const char *__symname);
+
+__END_DECLS
diff --git a/sysdeps/loongarch/bits/setjmp.h b/sysdeps/loongarch/bits/setjmp.h
new file mode 100644
index 0000000000..8b323ad2b6
--- /dev/null
+++ b/sysdeps/loongarch/bits/setjmp.h
@@ -0,0 +1,42 @@ 
+/* Define the machine-dependent type `jmp_buf'.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LOONGARCH_BITS_SETJMP_H
+#define _LOONGARCH_BITS_SETJMP_H
+
+typedef struct __jmp_buf_internal_tag
+{
+  /* Program counter.  */
+  long int __pc;
+  /* Stack pointer.  */
+  long int __sp;
+  /* Reserved */
+  long int __x;
+  /* Frame pointer.  */
+  long int __fp;
+  /* Callee-saved registers.  */
+  long int __regs[9];
+
+#ifndef __loongarch_soft_float
+  /* Callee-saved floating point registers.  */
+  double __fpregs[8];
+#endif
+
+} __jmp_buf[1];
+
+#endif /* _LOONGARCH_BITS_SETJMP_H */
diff --git a/sysdeps/loongarch/bsd-_setjmp.c b/sysdeps/loongarch/bsd-_setjmp.c
new file mode 100644
index 0000000000..32f49441c3
--- /dev/null
+++ b/sysdeps/loongarch/bsd-_setjmp.c
@@ -0,0 +1 @@ 
+/* _setjmp is implemented in setjmp.S.  */
diff --git a/sysdeps/loongarch/bsd-setjmp.c b/sysdeps/loongarch/bsd-setjmp.c
new file mode 100644
index 0000000000..45fd802aac
--- /dev/null
+++ b/sysdeps/loongarch/bsd-setjmp.c
@@ -0,0 +1 @@ 
+/* setjmp is implemented in setjmp.S.  */
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
new file mode 100644
index 0000000000..a615e6774a
--- /dev/null
+++ b/sysdeps/loongarch/dl-machine.h
@@ -0,0 +1,287 @@ 
+/* Machine-dependent ELF dynamic relocation inline functions.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef dl_machine_h
+#define dl_machine_h
+
+#define ELF_MACHINE_NAME "LoongArch"
+
+#include <entry.h>
+#include <elf/elf.h>
+#include <sys/asm.h>
+#include <dl-tls.h>
+#include <dl-static-tls.h>
+#include <dl-machine-rel.h>
+
+#ifndef _RTLD_PROLOGUE
+# define _RTLD_PROLOGUE(entry)					\
+	".globl\t" __STRING (entry) "\n\t"			\
+	".type\t" __STRING (entry) ", @function\n\t"		\
+	CFI_STARTPROC "\n"					\
+	__STRING (entry) ":\n"
+#endif
+
+#ifndef _RTLD_EPILOGUE
+# define _RTLD_EPILOGUE(entry)					\
+	CFI_ENDPROC "\n\t"					\
+	".size\t" __STRING (entry) ", . - " __STRING (entry) "\n"
+#endif
+
+#define ELF_MACHINE_JMP_SLOT R_LARCH_JUMP_SLOT
+#define ELF_MACHINE_IRELATIVE R_LARCH_IRELATIVE
+
+#define elf_machine_type_class(type)				\
+  ((ELF_RTYPE_CLASS_PLT *((type) == ELF_MACHINE_JMP_SLOT))	\
+   | (ELF_RTYPE_CLASS_COPY *((type) == R_LARCH_COPY)))
+
+#define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
+
+/* Return nonzero iff ELF header is compatible with the running host.  */
+static inline int
+elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
+{
+  /* We can only run LoongArch binaries.  */
+  if (ehdr->e_machine != EM_LOONGARCH)
+    return 0;
+
+  return 1;
+}
+
+/* Return the run-time load address of the shared object.  */
+static inline ElfW (Addr) elf_machine_load_address (void)
+{
+  extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+  return (ElfW(Addr)) &__ehdr_start;
+}
+
+/* Return the link-time address of _DYNAMIC.  */
+static inline ElfW (Addr) elf_machine_dynamic (void)
+{
+  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+  return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+}
+
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
+
+#define RTLD_START \
+  asm(".text\n\
+      " _RTLD_PROLOGUE (ENTRY_POINT) "\
+      .cfi_label .Ldummy   \n\
+      " CFI_UNDEFINED (1) "   \n\
+      or	$a0, $sp, $zero   \n\
+      bl	_dl_start   \n\
+      # Stash user entry point in s0.   \n\
+      or	$s0, $v0, $zero   \n\
+      # Load the original argument count.   \n\
+      ld.d	$a1, $sp, 0   \n\
+      # Call _dl_init (struct link_map *main_map, int argc, char **argv, \
+		       char **env)    \n\
+      la	$a0, _rtld_local   \n\
+      ld.d	$a0, $a0, 0   \n\
+      addi.d	$a2, $sp, 8   \n\
+      slli.d	$a3, $a1, 3   \n\
+      add.d	$a3, $a3, $a2   \n\
+      addi.d	$a3, $a3, 8   \n\
+      # Stash the stack pointer in s1.\n\
+      or	$s1, $sp, $zero	\n\
+      # Adjust $sp for 16-aligned   \n\
+      bstrins.d	$sp, $zero, 3, 0  \n\
+      # Call the function to run the initializers.   \n\
+      bl	_dl_init   \n\
+      # Restore the stack pointer for _start.\n\
+      or	$sp, $s1, $zero	 \n\
+      # Pass our finalizer function to _start.   \n\
+      la	$a0, _dl_fini   \n\
+      # Jump to the user entry point.   \n\
+      jirl	$zero, $s0, 0   \n\
+      " _RTLD_EPILOGUE (ENTRY_POINT) "\
+      .previous");
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER loongarch_gnu_pltenter
+#define ARCH_LA_PLTEXIT loongarch_gnu_pltexit
+
+/* Bias .got.plt entry by the offset requested by the PLT header.  */
+#define elf_machine_plt_value(map, reloc, value) (value)
+
+static inline ElfW (Addr)
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+			 const ElfW (Sym) *refsym, const ElfW (Sym) *sym,
+			 const ElfW (Rela) *reloc, ElfW (Addr) *reloc_addr,
+			 ElfW (Addr) value)
+{
+  return *reloc_addr = value;
+}
+
+#endif /* !dl_machine_h */
+
+#ifdef RESOLVE_MAP
+
+/* Perform a relocation described by R_INFO at the location pointed to
+   by RELOC_ADDR.  SYM is the relocation symbol specified by R_INFO and
+   MAP is the object containing the reloc.  */
+
+static inline void __attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
+		  const ElfW (Rela) *reloc,
+		  const ElfW (Sym) *sym,
+		  const struct r_found_version *version,
+		  void *const reloc_addr, int skip_ifunc)
+{
+  ElfW (Addr) r_info = reloc->r_info;
+  const unsigned long int r_type = ELFW (R_TYPE) (r_info);
+  ElfW (Addr) *addr_field = (ElfW (Addr) *) reloc_addr;
+  const ElfW (Sym) *const __attribute__ ((unused)) refsym = sym;
+  struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
+  ElfW (Addr) value = 0;
+  if (sym_map != NULL)
+    value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
+
+  if (sym != NULL
+      && __glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
+      && __glibc_likely (sym->st_shndx != SHN_UNDEF)
+      && __glibc_likely (!skip_ifunc))
+    value = ((ElfW (Addr) (*) (int)) value) (GLRO (dl_hwcap));
+
+  switch (r_type)
+    {
+
+    case R_LARCH_JUMP_SLOT:
+    case __WORDSIZE == 64 ? R_LARCH_64:
+    R_LARCH_32:
+      *addr_field = value;
+      break;
+
+#ifndef RTLD_BOOTSTRAP
+    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64:
+    R_LARCH_TLS_DTPMOD32:
+      *addr_field = sym_map->l_tls_modid;
+      break;
+
+    case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64:
+    R_LARCH_TLS_DTPREL32:
+      *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
+      break;
+
+    case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64:
+    R_LARCH_TLS_TPREL32:
+      CHECK_STATIC_TLS (map, sym_map);
+      *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
+      break;
+
+    case R_LARCH_COPY:
+      {
+	  if (sym == NULL)
+	    /* This can happen in trace mode if an object could not be
+	       found.  */
+	    break;
+	  if (__glibc_unlikely (sym->st_size > refsym->st_size)
+	      || (__glibc_unlikely (sym->st_size < refsym->st_size)
+		&& GLRO(dl_verbose)))
+	  {
+	    const char *strtab;
+
+	    strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
+	    _dl_error_printf ("\
+%s: Symbol `%s' has different size in shared object, consider re-linking\n",
+	    rtld_progname ?: "<program name unknown>",
+	    strtab + refsym->st_name);
+	  }
+	  memcpy (reloc_addr, (void *) value,
+		  MIN (sym->st_size, refsym->st_size));
+	    break;
+      }
+
+    case R_LARCH_RELATIVE:
+      *addr_field = map->l_addr + reloc->r_addend;
+      break;
+
+    case R_LARCH_IRELATIVE:
+      value = map->l_addr + reloc->r_addend;
+      if (__glibc_likely (!skip_ifunc))
+	value = ((ElfW (Addr) (*) (void)) value) ();
+      *addr_field = value;
+      break;
+
+    case R_LARCH_NONE:
+      break;
+#endif
+
+    default:
+      _dl_reloc_bad_type (map, r_type, 0);
+      break;
+    }
+}
+
+static inline void __attribute__ ((always_inline))
+elf_machine_rela_relative (ElfW (Addr) l_addr, const ElfW (Rela) *reloc,
+			   void *const reloc_addr)
+{
+  *(ElfW (Addr) *) reloc_addr = l_addr + reloc->r_addend;
+}
+
+static inline void __attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
+		      ElfW (Addr) l_addr,
+		      const ElfW (Rela) *reloc, int skip_ifunc)
+{
+  ElfW (Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+  const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
+
+  /* Check for unexpected PLT reloc type.  */
+  if (__glibc_likely (r_type == R_LARCH_JUMP_SLOT))
+    {
+      if (__glibc_unlikely (map->l_mach.plt == 0))
+	{
+	  if (l_addr)
+	    *reloc_addr += l_addr;
+	}
+      else
+	*reloc_addr = map->l_mach.plt;
+    }
+  else
+    _dl_reloc_bad_type (map, r_type, 1);
+}
+
+/* Set up the loaded object described by L so its stub function
+   will jump to the on-demand fixup code __dl_runtime_resolve.  */
+
+static inline int __attribute__ ((always_inline))
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+			   int lazy, int profile)
+{
+#ifndef RTLD_BOOTSTRAP
+  /* If using PLTs, fill in the first two entries of .got.plt.  */
+  if (l->l_info[DT_JMPREL])
+    {
+      extern void _dl_runtime_resolve (void)
+	__attribute__ ((visibility ("hidden")));
+      ElfW (Addr) *gotplt = (ElfW (Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+      gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve;
+      gotplt[1] = (ElfW (Addr)) l;
+    }
+#endif
+
+  return lazy;
+}
+
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S
new file mode 100644
index 0000000000..eb610392f6
--- /dev/null
+++ b/sysdeps/loongarch/dl-trampoline.S
@@ -0,0 +1,91 @@ 
+/* PLT trampolines.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+/* Assembler veneer called from the PLT header code for lazy loading.
+   The PLT header passes its own args in t0-t2.  */
+
+#ifdef __loongarch_soft_float
+# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
+#else
+# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
+#endif
+
+ENTRY (_dl_runtime_resolve)
+
+	/* Save arguments to stack. */
+	ADDI	sp, sp, -FRAME_SIZE
+
+	REG_S	ra, sp, 9*SZREG
+	REG_S	a0, sp, 1*SZREG
+	REG_S	a1, sp, 2*SZREG
+	REG_S	a2, sp, 3*SZREG
+	REG_S	a3, sp, 4*SZREG
+	REG_S	a4, sp, 5*SZREG
+	REG_S	a5, sp, 6*SZREG
+	REG_S	a6, sp, 7*SZREG
+	REG_S	a7, sp, 8*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_S	fa0, sp, 10*SZREG + 0*SZFREG
+	FREG_S	fa1, sp, 10*SZREG + 1*SZFREG
+	FREG_S	fa2, sp, 10*SZREG + 2*SZFREG
+	FREG_S	fa3, sp, 10*SZREG + 3*SZFREG
+	FREG_S	fa4, sp, 10*SZREG + 4*SZFREG
+	FREG_S	fa5, sp, 10*SZREG + 5*SZFREG
+	FREG_S	fa6, sp, 10*SZREG + 6*SZFREG
+	FREG_S	fa7, sp, 10*SZREG + 7*SZFREG
+#endif
+
+	/* Update .got.plt and obtain runtime address of callee */
+	SLLI	a1, t1, 1
+	or	a0, t0, zero
+	ADD	a1, a1, t1
+	la	a2, _dl_fixup
+	jirl	ra, a2, 0
+	or	t1, v0, zero
+
+	/* Restore arguments from stack. */
+	REG_L	ra, sp, 9*SZREG
+	REG_L	a0, sp, 1*SZREG
+	REG_L	a1, sp, 2*SZREG
+	REG_L	a2, sp, 3*SZREG
+	REG_L	a3, sp, 4*SZREG
+	REG_L	a4, sp, 5*SZREG
+	REG_L	a5, sp, 6*SZREG
+	REG_L	a6, sp, 7*SZREG
+	REG_L	a7, sp, 8*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_L	fa0, sp, 10*SZREG + 0*SZFREG
+	FREG_L	fa1, sp, 10*SZREG + 1*SZFREG
+	FREG_L	fa2, sp, 10*SZREG + 2*SZFREG
+	FREG_L	fa3, sp, 10*SZREG + 3*SZFREG
+	FREG_L	fa4, sp, 10*SZREG + 4*SZFREG
+	FREG_L	fa5, sp, 10*SZREG + 5*SZFREG
+	FREG_L	fa6, sp, 10*SZREG + 6*SZFREG
+	FREG_L	fa7, sp, 10*SZREG + 7*SZFREG
+#endif
+
+	ADDI	sp, sp, FRAME_SIZE
+
+	/* Invoke the callee. */
+	jirl		zero, t1, 0
+END (_dl_runtime_resolve)
diff --git a/sysdeps/loongarch/jmpbuf-offsets.h b/sysdeps/loongarch/jmpbuf-offsets.h
new file mode 100644
index 0000000000..a4b8ea690e
--- /dev/null
+++ b/sysdeps/loongarch/jmpbuf-offsets.h
@@ -0,0 +1,22 @@ 
+/* Private macros for accessing __jmp_buf contents.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <jmpbuf-unwind.h>
+
+/* Helper for generic ____longjmp_chk().  */
+#define JB_FRAME_ADDRESS(buf) ((void *) _jmpbuf_sp (buf))
diff --git a/sysdeps/loongarch/jmpbuf-unwind.h b/sysdeps/loongarch/jmpbuf-unwind.h
new file mode 100644
index 0000000000..6fa509151d
--- /dev/null
+++ b/sysdeps/loongarch/jmpbuf-unwind.h
@@ -0,0 +1,45 @@ 
+/* Examine __jmp_buf for unwinding frames.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <setjmp.h>
+#include <stdint.h>
+#include <unwind.h>
+#include <sysdep.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
+  ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+  _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused)) _jmpbuf_sp (__jmp_buf regs)
+{
+  uintptr_t sp = regs[0].__sp;
+#ifdef PTR_DEMANGLE
+  PTR_DEMANGLE (sp);
+#endif
+  return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+/* We use the normal longjmp for unwinding.  */
+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
diff --git a/sysdeps/loongarch/ldsodefs.h b/sysdeps/loongarch/ldsodefs.h
new file mode 100644
index 0000000000..36b1b25b9f
--- /dev/null
+++ b/sysdeps/loongarch/ldsodefs.h
@@ -0,0 +1,41 @@ 
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LOONGARCH_LDSODEFS_H
+#define _LOONGARCH_LDSODEFS_H 1
+
+#include <elf.h>
+
+struct La_loongarch_regs;
+struct La_loongarch_retval;
+
+#define ARCH_PLTENTER_MEMBERS \
+  ElfW (Addr) (*loongarch_gnu_pltenter) (ElfW (Sym) *, unsigned int, \
+					 uintptr_t *, uintptr_t *, \
+					 const struct La_loongarch_regs *, \
+					 unsigned int *, const char *name, \
+					 long int *framesizep);
+
+#define ARCH_PLTEXIT_MEMBERS \
+  unsigned int (*loongarch_gnu_pltexit) (ElfW (Sym) *, unsigned int, \
+		uintptr_t *, uintptr_t *, const struct La_loongarch_regs *, \
+		struct La_loongarch_retval *, const char *);
+
+#include_next <ldsodefs.h>
+
+#endif
diff --git a/sysdeps/loongarch/linkmap.h b/sysdeps/loongarch/linkmap.h
new file mode 100644
index 0000000000..bbba73ed70
--- /dev/null
+++ b/sysdeps/loongarch/linkmap.h
@@ -0,0 +1,22 @@ 
+/* Definition of link_map_machine.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+struct link_map_machine
+{
+  ElfW (Addr) plt; /* Address of .plt.  */
+};
diff --git a/sysdeps/loongarch/machine-gmon.h b/sysdeps/loongarch/machine-gmon.h
new file mode 100644
index 0000000000..4a3cdd964e
--- /dev/null
+++ b/sysdeps/loongarch/machine-gmon.h
@@ -0,0 +1,37 @@ 
+/* LoongArch definitions for profiling support.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Accept 'frompc' address as argument from the function that calls
+   _mcount for profiling.  Use  __builtin_return_address (0)
+   for the 'selfpc' address.  */
+
+#include <sysdep.h>
+
+static void mcount_internal (unsigned long int frompc,
+			     unsigned long int selfpc);
+
+#define _MCOUNT_DECL(frompc, selfpc) \
+  static inline void mcount_internal (unsigned long int frompc, \
+				      unsigned long int selfpc)
+
+#define MCOUNT \
+  void _mcount (void *frompc) \
+  { \
+    mcount_internal ((unsigned long int) frompc, \
+		     (unsigned long int) RETURN_ADDRESS (0)); \
+  }
diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
new file mode 100644
index 0000000000..c081ff6b87
--- /dev/null
+++ b/sysdeps/loongarch/setjmp.S
@@ -0,0 +1,66 @@ 
+/* setjmp for LoongArch.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+
+ENTRY (_setjmp)
+	li.w		a1,0
+	b		HIDDEN_JUMPTARGET (__sigsetjmp)
+END (_setjmp)
+
+ENTRY (setjmp)
+	li.w		a1,1
+END (setjmp)
+
+ENTRY (__sigsetjmp)
+	REG_S ra, a0, 0*SZREG
+	REG_S sp, a0, 1*SZREG
+	REG_S x,  a0, 2*SZREG
+	REG_S fp, a0, 3*SZREG
+	REG_S s0, a0, 4*SZREG
+	REG_S s1, a0, 5*SZREG
+	REG_S s2, a0, 6*SZREG
+	REG_S s3, a0, 7*SZREG
+	REG_S s4, a0, 8*SZREG
+	REG_S s5, a0, 9*SZREG
+	REG_S s6, a0, 10*SZREG
+	REG_S s7, a0, 11*SZREG
+	REG_S s8, a0, 12*SZREG
+
+#ifndef __loongarch_soft_float
+	FREG_S $f24, a0, 13*SZREG + 0*SZFREG
+	FREG_S $f25, a0, 13*SZREG + 1*SZFREG
+	FREG_S $f26, a0, 13*SZREG + 2*SZFREG
+	FREG_S $f27, a0, 13*SZREG + 3*SZFREG
+	FREG_S $f28, a0, 13*SZREG + 4*SZFREG
+	FREG_S $f29, a0, 13*SZREG + 5*SZFREG
+	FREG_S $f30, a0, 13*SZREG + 6*SZFREG
+	FREG_S $f31, a0, 13*SZREG + 7*SZFREG
+#endif
+
+#if !IS_IN (libc) && IS_IN(rtld)
+	li.w		v0, 0
+	jirl		zero,ra,0
+#else
+	b		__sigjmp_save
+#endif
+END (__sigsetjmp)
+
+hidden_def (__sigsetjmp)
+weak_alias (_setjmp, __GI__setjmp)
diff --git a/sysdeps/loongarch/sotruss-lib.c b/sysdeps/loongarch/sotruss-lib.c
new file mode 100644
index 0000000000..ce752785f6
--- /dev/null
+++ b/sysdeps/loongarch/sotruss-lib.c
@@ -0,0 +1,50 @@ 
+/* Override generic sotruss-lib.c to define actual functions for LoongArch.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define HAVE_ARCH_PLTENTER
+#define HAVE_ARCH_PLTEXIT
+
+#include <elf/sotruss-lib.c>
+
+ElfW (Addr)
+la_loongarch_gnu_pltenter (ElfW (Sym) *sym __attribute__ ((unused)),
+			   unsigned int ndx __attribute__ ((unused)),
+			   uintptr_t *refcook, uintptr_t *defcook,
+			   La_loongarch_regs *regs, unsigned int *flags,
+			   const char *symname, long int *framesizep)
+{
+  print_enter (refcook, defcook, symname, regs->lr_reg[0], regs->lr_reg[1],
+		   regs->lr_reg[2], *flags);
+
+  /* No need to copy anything, we will not need the parameters in any case.  */
+  *framesizep = 0;
+
+  return sym->st_value;
+}
+
+unsigned int
+la_loongarch_gnu_pltexit (ElfW (Sym) *sym, unsigned int ndx,
+			  uintptr_t *refcook, uintptr_t *defcook,
+			  const struct La_loongarch_regs *inregs,
+			  struct La_loongarch_retval *outregs,
+			  const char *symname)
+{
+  print_exit (refcook, defcook, symname, outregs->lrv_a0);
+
+  return 0;
+}
diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
new file mode 100644
index 0000000000..280b5fab8c
--- /dev/null
+++ b/sysdeps/loongarch/start.S
@@ -0,0 +1,66 @@ 
+/* Startup code compliant to the ELF LoongArch ABI.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __ASSEMBLY__ 1
+#include <entry.h>
+#include <sys/asm.h>
+
+/* The entry point's job is to call __libc_start_main.  Per the ABI,
+   a0 contains the address of a function to be passed to atexit.
+   __libc_start_main wants this in a5.  */
+
+/*
+int
+__libc_start_main (int (*main) (int, char **, char **),
+		   int argc,
+		   char **argv,
+		   __typeof (main) init,
+		   void (*fini) (void),
+		   void (*rtld_fini) (void),
+		   void *stack_end);
+ */
+
+ENTRY (ENTRY_POINT)
+
+/* Terminate call stack by noting ra is undefined.  Use a dummy
+   .cfi_label to force starting the FDE.  */
+	.cfi_label .Ldummy
+	cfi_undefined (1)
+	or		a5, a0, zero /* rtld_fini */
+
+/* We must get symbol main through GOT table, since main may not be local.
+   For instance: googletest defines main in dynamic library.  */
+	la.got		a0, t0, main
+	REG_L		a1, sp, 0
+	ADDI		a2, sp, SZREG
+
+	/* Adjust $sp for 16-aligned */
+	BSTRINS		sp, zero, 3, 0
+
+	move		a3, zero /* used to be init */
+	move		a4, zero /* used to be fini */
+	or		a6, sp, zero /* stack_end */
+
+	la.got		ra, t0, __libc_start_main
+	jirl		ra, ra, 0
+
+	la.got		ra, t0, abort
+	jirl		ra, ra, 0
+END (ENTRY_POINT)
+
diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h
new file mode 100644
index 0000000000..b41ee59694
--- /dev/null
+++ b/sysdeps/loongarch/sys/asm.h
@@ -0,0 +1,59 @@ 
+/* Miscellaneous macros.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_ASM_H
+#define _SYS_ASM_H
+
+#include <sys/regdef.h>
+#include <sysdeps/generic/sysdep.h>
+
+/* Macros to handle different pointer/register sizes for 32/64-bit code.  */
+#define SZREG 8
+#define SZFREG 8
+#define REG_L ld.d
+#define REG_S st.d
+#define SRLI srli.d
+#define SLLI slli.d
+#define ADDI addi.d
+#define ADD  add.d
+#define BSTRINS  bstrins.d
+#define LI  li.d
+#define FREG_L fld.d
+#define FREG_S fst.d
+
+/* Declare leaf routine.  */
+#define LEAF(symbol) \
+  .text; \
+  .globl symbol; \
+  .align 3; \
+  cfi_startproc; \
+  .type symbol, @function; \
+  symbol:
+
+#define ENTRY(symbol) LEAF (symbol)
+
+/* Mark end of function.  */
+#undef END
+#define END(function) \
+  cfi_endproc; \
+  .size function, .- function;
+
+/* Stack alignment.  */
+#define ALMASK ~15
+
+#endif /* sys/asm.h */
diff --git a/sysdeps/loongarch/tst-audit.h b/sysdeps/loongarch/tst-audit.h
new file mode 100644
index 0000000000..e71948c86e
--- /dev/null
+++ b/sysdeps/loongarch/tst-audit.h
@@ -0,0 +1,23 @@ 
+/* Definitions for testing PLT entry/exit auditing.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define pltenter la_loongarch_gnu_pltenter
+#define pltexit la_loongarch_gnu_pltexit
+#define La_regs La_loongarch_regs
+#define La_retval La_loongarch_retval
+#define int_retval lrv_a0
diff --git a/sysdeps/unix/sysv/linux/loongarch/ldconfig.h b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
new file mode 100644
index 0000000000..4887c30ca2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
@@ -0,0 +1,26 @@ 
+/* ldconfig default paths and libraries.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdeps/generic/ldconfig.h>
+
+#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+  { "/lib64/ld-linux-loongarch-lp64d.so.1", FLAG_ELF_LIBC6 },
+
+#define SYSDEP_KNOWN_LIBRARY_NAMES	\
+  { "libc.so.6", FLAG_ELF_LIBC6 },	\
+  { "libm.so.6", FLAG_ELF_LIBC6 },