diff mbox series

[uclibc-ng-devel,v3] Static PIE support for mips

Message ID CANP1oa35BSAKkK5onBdv_zkSG+iW0W8xMd4AT3+BR6hNXFTxTQ@mail.gmail.com
State Accepted
Headers show
Series [uclibc-ng-devel,v3] Static PIE support for mips | expand

Commit Message

linted Sept. 2, 2022, 4:24 p.m. UTC
Hello,
This is a slight update to the v2 patch. I realized that I left some
extraneous comments in crt1.S. This patch removes those comments.

--------
From f5a4f77a396631bfceea2967b6a9100b09802f6c Mon Sep 17 00:00:00 2001
From: linted <linted@users.noreply.github.com>
Date: Sat, 20 Aug 2022 16:41:38 -0400
Subject: [PATCH] Added support for creation of Static Position-Independent
 Executables (PIE) on mips

Updated config to allow compilation of rcrt1.o for mips and modified it's
crt1.S to perform relocates in __start.

The mips architecture performs relocations differently then most other
architectures. reloc_static_pie was rewritten, taking code from
dl-startup.c, in order to perfrom the additional relocations. Modifications
were made to mips' dl-startup.h to allow for the use of contained macros
without including _start definition.

Signed-off-by: linted <linted@users.noreply.github.com>
---
 extra/Configs/Config.in                |  2 +-
 ldso/ldso/mips/dl-startup.h            |  3 +-
 libc/misc/internals/Makefile.in        |  2 +-
 libc/misc/internals/reloc_static_pie.c | 93 +++++++++++++++++++++-----
 libc/sysdeps/linux/mips/crt1.S         | 23 +++++++
 5 files changed, 105 insertions(+), 18 deletions(-)

Comments

Lance Fredrickson Sept. 2, 2022, 5:43 p.m. UTC | #1
Now works for me, great job!

On 9/2/2022 10:24 AM, linted wrote:
> Hello,
> This is a slight update to the v2 patch. I realized that I left some 
> extraneous comments in crt1.S. This patch removes those comments.
>
> --------
> From f5a4f77a396631bfceea2967b6a9100b09802f6c Mon Sep 17 00:00:00 2001
> From: linted <linted@users.noreply.github.com>
> Date: Sat, 20 Aug 2022 16:41:38 -0400
> Subject: [PATCH] Added support for creation of Static Position-Independent
>  Executables (PIE) on mips
>
> Updated config to allow compilation of rcrt1.o for mips and modified 
> it's crt1.S to perform relocates in __start.
>
> The mips architecture performs relocations differently then most other 
> architectures. reloc_static_pie was rewritten, taking code from 
> dl-startup.c, in order to perfrom the additional relocations. 
> Modifications were made to mips' dl-startup.h to allow for the use of 
> contained macros without including _start definition.
>
> Signed-off-by: linted <linted@users.noreply.github.com>
> ---
>  extra/Configs/Config.in                |  2 +-
>  ldso/ldso/mips/dl-startup.h            |  3 +-
>  libc/misc/internals/Makefile.in        |  2 +-
>  libc/misc/internals/reloc_static_pie.c | 93 +++++++++++++++++++++-----
>  libc/sysdeps/linux/mips/crt1.S         | 23 +++++++
>  5 files changed, 105 insertions(+), 18 deletions(-)
>
> diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> index e0905e956..43c04fd0a 100644
> --- a/extra/Configs/Config.in
> +++ b/extra/Configs/Config.in
> @@ -324,7 +324,7 @@ config DOPIC
>  config STATIC_PIE
>   bool "Add support for Static Position Independent Executables (PIE)"
>   default n
> - depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || 
> TARGET_i386 || TARGET_x86_64 || TARGET_aarch64)
> + depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || 
> TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips)
>
>  config ARCH_HAS_NO_SHARED
>   bool
> diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
> index 8026f1702..c2168d774 100644
> --- a/ldso/ldso/mips/dl-startup.h
> +++ b/ldso/ldso/mips/dl-startup.h
> @@ -7,6 +7,7 @@
>
>
>  #include <sgidefs.h>
> +#ifndef L_rcrt1
>  __asm__(""
>      " .text\n"
>      " .globl _start\n"
> @@ -114,6 +115,7 @@ __asm__(""
>      "\n\n"
>      ".previous\n"
>  );
> +#endif
>
>  /*
>   * Get a pointer to the argv array.  On many platforms this can be just
> @@ -191,6 +193,5 @@ do { \
>   case R_MIPS_NONE: \
>   break; \
>   default: \
> - SEND_STDERR("Aiieeee!"); \
>   _dl_exit(1); \
>   }
> diff --git a/libc/misc/internals/Makefile.in 
> b/libc/misc/internals/Makefile.in
> index 69af8b76e..908b18321 100644
> --- a/libc/misc/internals/Makefile.in
> +++ b/libc/misc/internals/Makefile.in
> @@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst 
> %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y))
>  MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y))
>
>  CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS)
> -CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS)
> +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1
>
>  libc-y += $(MISC_INTERNALS_OBJ)
>  ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y)
> diff --git a/libc/misc/internals/reloc_static_pie.c 
> b/libc/misc/internals/reloc_static_pie.c
> index 578202d23..c0027de6f 100644
> --- a/libc/misc/internals/reloc_static_pie.c
> +++ b/libc/misc/internals/reloc_static_pie.c
> @@ -15,33 +15,96 @@
>     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 IS_IN_rtld      // force inline function calls
>  #include <link.h>
>  #include <elf.h>
>  #include <dl-elf.h>
>
> +#include <ldso.h>
> +#ifdef __mips__
> +#include <dl-startup.h>
> +#endif
> +
>  ElfW(Addr) _dl_load_base = NULL;
>
>  void
>  reloc_static_pie (ElfW(Addr) load_addr);
>
>  void
> -reloc_static_pie (ElfW(Addr) load_addr)
> +reloc_static_pie(ElfW(Addr) load_addr)
>  {
> -    ElfW(Word) relative_count = 0;
> -    ElfW(Addr) rel_addr = 0;
> -    ElfW(Dyn) * dyn_addr = NULL;
> -    unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
> +    int indx;
> +    ElfW(Addr) got;
> +    ElfW(Dyn) *dpnt;
> +    struct elf_resolve tpnt_tmp;
> + struct elf_resolve *tpnt = &tpnt_tmp;
> +
> +    DL_BOOT_COMPUTE_GOT(got);
> +    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);
> +
> +    _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
> +    tpnt->loadaddr = load_addr;
> +    tpnt->dynamic_addr = dpnt;
> +
> +    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
> +
> +#if defined(PERFORM_BOOTSTRAP_GOT)
> + /* some arches (like MIPS) we have to tweak the GOT before 
> relocations */
> + PERFORM_BOOTSTRAP_GOT(tpnt);
> +#endif
> +
> +
> +#if defined(ELF_MACHINE_PLTREL_OVERLAP)
> +# define INDX_MAX 1
> +#else
> +# define INDX_MAX 2
> +#endif
> +
> +    for (indx = 0; indx < INDX_MAX; indx++) {
> +        unsigned long rel_addr, rel_size;
> +        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
> +
> +        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
> + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
> +        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
> +               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
> +
> +        if (!rel_addr)
> +            continue;
>
> -    /* Read our own dynamic section and fill in the info array.  */
> -    dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
> +        if((0 == indx) && relative_count) {
> + rel_size -= relative_count * sizeof(ELF_RELOC);
> +            elf_machine_relative(load_addr, rel_addr, relative_count);
> + rel_addr += relative_count * sizeof(ELF_RELOC);
> +        }
>
> -    /* Use the underlying function to avoid TLS access before 
> initialization */
> -    __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
> +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
> + {
> + ELF_RELOC *rpnt;
> + unsigned int i;
> + ElfW(Sym) *sym;
> + unsigned long symbol_addr;
> + int symtab_index;
> + unsigned long *reloc_addr;
>
> -    /* Perform relocations */
> -    relative_count = dynamic_info[DT_RELCONT_IDX];
> -    rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
> -    elf_machine_relative(load_addr, rel_addr, relative_count);
> + /* Now parse the relocation information */
> + rpnt = (ELF_RELOC *) rel_addr;
> + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
> + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned 
> long)rpnt->r_offset);
> + symtab_index = ELF_R_SYM(rpnt->r_info);
> + symbol_addr = 0;
> + sym = NULL;
> + if (symtab_index) {
> + ElfW(Sym) *symtab;
> + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
> + sym = &symtab[symtab_index];
> + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);
> + }
> + /* Use this machine-specific macro to perform the actual relocation.  */
> + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
> + }
> + }
> +#endif
> +    }
>      _dl_load_base = load_addr;
> -}
> +}
> \ No newline at end of file
> diff --git a/libc/sysdeps/linux/mips/crt1.S 
> b/libc/sysdeps/linux/mips/crt1.S
> index 083615515..7c4db447c 100644
> --- a/libc/sysdeps/linux/mips/crt1.S
> +++ b/libc/sysdeps/linux/mips/crt1.S
> @@ -77,6 +77,10 @@
>  #ifndef __UCLIBC_CTOR_DTOR__
>   .weak _init
>   .weak _fini
> +#endif
> +#ifdef L_rcrt1
> + .type reloc_static_pie,@function
> + .hidden .L0
>  #endif
>   .type    main,@function
>   .type    __uClibc_main,@function
> @@ -89,6 +93,25 @@ __start:
>  #else
>   PTR_LA $28, _gp             /* Setup GP correctly if we're non-PIC.  */
>   move $31, $0
> +#endif
> +#ifdef L_rcrt1
> + PTR_LA $4, _DYNAMIC           /* Place _DYNAMIC into the GOT */
> + REG_S $4, -0x7ff0($28)        /* offset to GOT stolen from dl-startup */
> + jal .L0                       /* Get the current $pc address */
> +.L0:
> + PTR_SUBU $4, $31, $25         /* Calculate load addr */
> + move $31, $0                  /* Clear ra */
> + and $29, -2 * SZREG           /* Ensure stack is aligned */
> + PTR_ADDIU $29, (-2 * SZREG)   /* Allocate 2 register spaces on stack */
> + REG_S $2, SZREG($29)          /* Store atexit in case it exists */
> + PTR_LA $5, reloc_static_pie   /* function calls before relocation
> +                                 don't work unless we set $t9 manually */
> + PTR_ADDU $25, $4, $5          /* store reloc_static_pie in $t9 */
> + jalr $25                      /* call reloc_static_pie */
> + nop  /* delay slot, just in case */
> + REG_L $2, SZREG($29)          /* cleanup stack */
> + PTR_ADDIU $29, $29, (2 * SZREG)
> +
>  #endif
>
>   PTR_LA $4, main /* main */
> -- 
> 2.34.1
>
>
>
> _______________________________________________
> devel mailing list --devel@uclibc-ng.org
> To unsubscribe send an email todevel-leave@uclibc-ng.org
Waldemar Brodkorb Sept. 7, 2022, 7:40 a.m. UTC | #2
Hi,

applied and pushed,

best regards
 Waldemar

linted wrote,

> Hello,
> This is a slight update to the v2 patch. I realized that I left some extraneous
> comments in crt1.S. This patch removes those comments.
> 
> --------
> From f5a4f77a396631bfceea2967b6a9100b09802f6c Mon Sep 17 00:00:00 2001
> From: linted <linted@users.noreply.github.com>
> Date: Sat, 20 Aug 2022 16:41:38 -0400
> Subject: [PATCH] Added support for creation of Static Position-Independent
>  Executables (PIE) on mips
> 
> Updated config to allow compilation of rcrt1.o for mips and modified it's
> crt1.S to perform relocates in __start.
> 
> The mips architecture performs relocations differently then most other
> architectures. reloc_static_pie was rewritten, taking code from dl-startup.c,
> in order to perfrom the additional relocations. Modifications were made to
> mips' dl-startup.h to allow for the use of contained macros without including
> _start definition.
> 
> Signed-off-by: linted <linted@users.noreply.github.com>
> ---
>  extra/Configs/Config.in                |  2 +-
>  ldso/ldso/mips/dl-startup.h            |  3 +-
>  libc/misc/internals/Makefile.in        |  2 +-
>  libc/misc/internals/reloc_static_pie.c | 93 +++++++++++++++++++++-----
>  libc/sysdeps/linux/mips/crt1.S         | 23 +++++++
>  5 files changed, 105 insertions(+), 18 deletions(-)
> 
> diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> index e0905e956..43c04fd0a 100644
> --- a/extra/Configs/Config.in
> +++ b/extra/Configs/Config.in
> @@ -324,7 +324,7 @@ config DOPIC
>  config STATIC_PIE
>   bool "Add support for Static Position Independent Executables (PIE)"
>   default n
> - depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 ||
> TARGET_x86_64 || TARGET_aarch64)
> + depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 ||
> TARGET_x86_64 || TARGET_aarch64 || TARGET_mips)
>  
>  config ARCH_HAS_NO_SHARED
>   bool
> diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
> index 8026f1702..c2168d774 100644
> --- a/ldso/ldso/mips/dl-startup.h
> +++ b/ldso/ldso/mips/dl-startup.h
> @@ -7,6 +7,7 @@
>  
>  
>  #include <sgidefs.h>
> +#ifndef L_rcrt1
>  __asm__(""
>      " .text\n"
>      " .globl _start\n"
> @@ -114,6 +115,7 @@ __asm__(""
>      "\n\n"
>      ".previous\n"
>  );
> +#endif
>  
>  /*
>   * Get a pointer to the argv array.  On many platforms this can be just
> @@ -191,6 +193,5 @@ do { \
>   case R_MIPS_NONE: \
>   break; \
>   default: \
> - SEND_STDERR("Aiieeee!"); \
>   _dl_exit(1); \
>   }
> diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in
> index 69af8b76e..908b18321 100644
> --- a/libc/misc/internals/Makefile.in
> +++ b/libc/misc/internals/Makefile.in
> @@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/
> %.c,$(CSRC-y))
>  MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y))
>  
>  CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS)
> -CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS)
> +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1
>  
>  libc-y += $(MISC_INTERNALS_OBJ)
>  ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y)
> diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/
> reloc_static_pie.c
> index 578202d23..c0027de6f 100644
> --- a/libc/misc/internals/reloc_static_pie.c
> +++ b/libc/misc/internals/reloc_static_pie.c
> @@ -15,33 +15,96 @@
>     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 IS_IN_rtld      // force inline function calls
>  #include <link.h>
>  #include <elf.h>
>  #include <dl-elf.h>
>  
> +#include <ldso.h>
> +#ifdef __mips__
> +#include <dl-startup.h>
> +#endif
> +
>  ElfW(Addr) _dl_load_base = NULL;
>  
>  void
>  reloc_static_pie (ElfW(Addr) load_addr);
>  
>  void
> -reloc_static_pie (ElfW(Addr) load_addr)
> +reloc_static_pie(ElfW(Addr) load_addr)
>  {
> -    ElfW(Word) relative_count = 0;
> -    ElfW(Addr) rel_addr = 0;
> -    ElfW(Dyn) * dyn_addr = NULL;
> -    unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
> +    int indx;
> +    ElfW(Addr) got;
> +    ElfW(Dyn) *dpnt;
> +    struct elf_resolve tpnt_tmp;
> + struct elf_resolve *tpnt = &tpnt_tmp;
> +
> +    DL_BOOT_COMPUTE_GOT(got);
> +    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);
> +
> +    _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
> +    tpnt->loadaddr = load_addr;
> +    tpnt->dynamic_addr = dpnt;
> +
> +    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
> +
> +#if defined(PERFORM_BOOTSTRAP_GOT)
> + /* some arches (like MIPS) we have to tweak the GOT before relocations */
> + PERFORM_BOOTSTRAP_GOT(tpnt);
> +#endif
> +
> +
> +#if defined(ELF_MACHINE_PLTREL_OVERLAP)
> +# define INDX_MAX 1
> +#else
> +# define INDX_MAX 2
> +#endif
> +
> +    for (indx = 0; indx < INDX_MAX; indx++) {
> +        unsigned long rel_addr, rel_size;
> +        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
> +
> +        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
> +                           tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
> +        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
> +               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
> +
> +        if (!rel_addr)
> +            continue;
>  
> -    /* Read our own dynamic section and fill in the info array.  */
> -    dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
> +        if((0 == indx) && relative_count) {
> + rel_size -= relative_count * sizeof(ELF_RELOC);
> +            elf_machine_relative(load_addr, rel_addr, relative_count);
> + rel_addr += relative_count * sizeof(ELF_RELOC);
> +        }
>  
> -    /* Use the underlying function to avoid TLS access before initialization *
> /
> -    __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
> +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
> + {
> + ELF_RELOC *rpnt;
> + unsigned int i;
> + ElfW(Sym) *sym;
> + unsigned long symbol_addr;
> + int symtab_index;
> + unsigned long *reloc_addr;
>  
> -    /* Perform relocations */
> -    relative_count = dynamic_info[DT_RELCONT_IDX];
> -    rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
> -    elf_machine_relative(load_addr, rel_addr, relative_count);
> + /* Now parse the relocation information */
> + rpnt = (ELF_RELOC *) rel_addr;
> + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
> + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->
> r_offset);
> + symtab_index = ELF_R_SYM(rpnt->r_info);
> + symbol_addr = 0;
> + sym = NULL;
> + if (symtab_index) {
> + ElfW(Sym) *symtab;
> + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
> + sym = &symtab[symtab_index];
> + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);
> + }
> + /* Use this machine-specific macro to perform the actual relocation.  */
> + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
> + }
> + }
> +#endif
> +    }
>      _dl_load_base = load_addr;
> -}
> +}
> \ No newline at end of file
> diff --git a/libc/sysdeps/linux/mips/crt1.S b/libc/sysdeps/linux/mips/crt1.S
> index 083615515..7c4db447c 100644
> --- a/libc/sysdeps/linux/mips/crt1.S
> +++ b/libc/sysdeps/linux/mips/crt1.S
> @@ -77,6 +77,10 @@
>  #ifndef __UCLIBC_CTOR_DTOR__
>   .weak _init
>   .weak _fini
> +#endif
> +#ifdef L_rcrt1
> + .type reloc_static_pie,@function
> + .hidden .L0
>  #endif
>   .type    main,@function
>   .type    __uClibc_main,@function
> @@ -89,6 +93,25 @@ __start:
>  #else
>   PTR_LA $28, _gp             /* Setup GP correctly if we're non-PIC.  */
>   move $31, $0
> +#endif
> +#ifdef L_rcrt1
> + PTR_LA $4, _DYNAMIC           /* Place _DYNAMIC into the GOT */
> + REG_S $4, -0x7ff0($28)        /* offset to GOT stolen from dl-startup */
> + jal .L0                       /* Get the current $pc address */
> +.L0:
> + PTR_SUBU $4, $31, $25         /* Calculate load addr */
> + move $31, $0                  /* Clear ra */
> + and $29, -2 * SZREG           /* Ensure stack is aligned */
> + PTR_ADDIU $29, (-2 * SZREG)   /* Allocate 2 register spaces on stack */
> + REG_S $2, SZREG($29)          /* Store atexit in case it exists */
> + PTR_LA $5, reloc_static_pie   /* function calls before relocation
> +                                 don't work unless we set $t9 manually */
> + PTR_ADDU $25, $4, $5          /* store reloc_static_pie in $t9 */
> + jalr $25                      /* call reloc_static_pie */
> + nop  /* delay slot, just in case */
> + REG_L $2, SZREG($29)          /* cleanup stack */
> + PTR_ADDIU $29, $29, (2 * SZREG)
> +
>  #endif
>  
>   PTR_LA $4, main /* main */
> --
> 2.34.1
> 
> 

> From f5a4f77a396631bfceea2967b6a9100b09802f6c Mon Sep 17 00:00:00 2001
> From: linted <linted@users.noreply.github.com>
> Date: Sat, 20 Aug 2022 16:41:38 -0400
> Subject: [PATCH] Added support for creation of Static Position-Independent
>  Executables (PIE) on mips
> 
> Updated config to allow compilation of rcrt1.o for mips and modified it's crt1.S to perform relocates in __start.
> 
> The mips architecture performs relocations differently then most other architectures. reloc_static_pie was rewritten, taking code from dl-startup.c, in order to perfrom the additional relocations. Modifications were made to mips' dl-startup.h to allow for the use of contained macros without including _start definition.
> 
> Signed-off-by: linted <linted@users.noreply.github.com>
> ---
>  extra/Configs/Config.in                |  2 +-
>  ldso/ldso/mips/dl-startup.h            |  3 +-
>  libc/misc/internals/Makefile.in        |  2 +-
>  libc/misc/internals/reloc_static_pie.c | 93 +++++++++++++++++++++-----
>  libc/sysdeps/linux/mips/crt1.S         | 23 +++++++
>  5 files changed, 105 insertions(+), 18 deletions(-)
> 
> diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> index e0905e956..43c04fd0a 100644
> --- a/extra/Configs/Config.in
> +++ b/extra/Configs/Config.in
> @@ -324,7 +324,7 @@ config DOPIC
>  config STATIC_PIE
>  	bool "Add support for Static Position Independent Executables (PIE)"
>  	default n
> -	depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64)
> +	depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips)
>  
>  config ARCH_HAS_NO_SHARED
>  	bool
> diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
> index 8026f1702..c2168d774 100644
> --- a/ldso/ldso/mips/dl-startup.h
> +++ b/ldso/ldso/mips/dl-startup.h
> @@ -7,6 +7,7 @@
>  
>  
>  #include <sgidefs.h>
> +#ifndef L_rcrt1
>  __asm__(""
>      "	.text\n"
>      "	.globl	_start\n"
> @@ -114,6 +115,7 @@ __asm__(""
>      "\n\n"
>      ".previous\n"
>  );
> +#endif
>  
>  /*
>   * Get a pointer to the argv array.  On many platforms this can be just
> @@ -191,6 +193,5 @@ do {										\
>  	case R_MIPS_NONE:							\
>  		break;								\
>  	default:								\
> -		SEND_STDERR("Aiieeee!");					\
>  		_dl_exit(1);							\
>  	}
> diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in
> index 69af8b76e..908b18321 100644
> --- a/libc/misc/internals/Makefile.in
> +++ b/libc/misc/internals/Makefile.in
> @@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y))
>  MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y))
>  
>  CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS)
> -CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS)
> +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1
>  
>  libc-y += $(MISC_INTERNALS_OBJ)
>  ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y)
> diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c
> index 578202d23..c0027de6f 100644
> --- a/libc/misc/internals/reloc_static_pie.c
> +++ b/libc/misc/internals/reloc_static_pie.c
> @@ -15,33 +15,96 @@
>     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 IS_IN_rtld      // force inline function calls
>  #include <link.h>
>  #include <elf.h>
>  #include <dl-elf.h>
>  
> +#include <ldso.h>
> +#ifdef __mips__
> +#include <dl-startup.h>
> +#endif
> +
>  ElfW(Addr) _dl_load_base = NULL;
>  
>  void
>  reloc_static_pie (ElfW(Addr) load_addr);
>  
>  void
> -reloc_static_pie (ElfW(Addr) load_addr)
> +reloc_static_pie(ElfW(Addr) load_addr)
>  {
> -    ElfW(Word) relative_count = 0;
> -    ElfW(Addr) rel_addr = 0;
> -    ElfW(Dyn) * dyn_addr = NULL;
> -    unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
> +    int indx;
> +    ElfW(Addr) got;
> +    ElfW(Dyn) *dpnt;
> +    struct elf_resolve tpnt_tmp;
> +	struct elf_resolve *tpnt = &tpnt_tmp;
> +
> +    DL_BOOT_COMPUTE_GOT(got);
> +    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);
> +
> +    _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
> +    tpnt->loadaddr = load_addr;
> +    tpnt->dynamic_addr = dpnt;
> +
> +    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
> +
> +#if defined(PERFORM_BOOTSTRAP_GOT)
> +	/* some arches (like MIPS) we have to tweak the GOT before relocations */
> +	PERFORM_BOOTSTRAP_GOT(tpnt);
> +#endif
> +
> +
> +#if defined(ELF_MACHINE_PLTREL_OVERLAP)
> +# define INDX_MAX 1
> +#else
> +# define INDX_MAX 2
> +#endif
> +
> +    for (indx = 0; indx < INDX_MAX; indx++) {
> +        unsigned long rel_addr, rel_size;
> +        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
> +
> +        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
> +                           tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
> +        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
> +			               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
> +
> +        if (!rel_addr)
> +            continue;
>  
> -    /* Read our own dynamic section and fill in the info array.  */
> -    dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
> +        if((0 == indx) && relative_count) {
> +			rel_size -= relative_count * sizeof(ELF_RELOC);
> +            elf_machine_relative(load_addr, rel_addr, relative_count);
> +			rel_addr += relative_count * sizeof(ELF_RELOC);
> +        }
>  
> -    /* Use the underlying function to avoid TLS access before initialization */
> -    __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
> +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
> +			{
> +				ELF_RELOC *rpnt;
> +				unsigned int i;
> +				ElfW(Sym) *sym;
> +				unsigned long symbol_addr;
> +				int symtab_index;
> +				unsigned long *reloc_addr;
>  
> -    /* Perform relocations */
> -    relative_count = dynamic_info[DT_RELCONT_IDX];
> -    rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
> -    elf_machine_relative(load_addr, rel_addr, relative_count);
> +				/* Now parse the relocation information */
> +				rpnt = (ELF_RELOC *) rel_addr;
> +				for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
> +					reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset);
> +					symtab_index = ELF_R_SYM(rpnt->r_info);
> +					symbol_addr = 0;
> +					sym = NULL;
> +					if (symtab_index) {
> +						ElfW(Sym) *symtab;
> +						symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
> +						sym = &symtab[symtab_index];
> +						symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);
> +					}
> +					/* Use this machine-specific macro to perform the actual relocation.  */
> +					PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
> +				}
> +			}
> +#endif
> +    }
>      _dl_load_base = load_addr;
> -}
> +}
> \ No newline at end of file
> diff --git a/libc/sysdeps/linux/mips/crt1.S b/libc/sysdeps/linux/mips/crt1.S
> index 083615515..7c4db447c 100644
> --- a/libc/sysdeps/linux/mips/crt1.S
> +++ b/libc/sysdeps/linux/mips/crt1.S
> @@ -77,6 +77,10 @@
>  #ifndef __UCLIBC_CTOR_DTOR__
>  	.weak	_init
>  	.weak	_fini
> +#endif
> +#ifdef L_rcrt1
> +	.type	reloc_static_pie,@function
> +	.hidden	.L0
>  #endif
>  	.type	    main,@function
>  	.type	    __uClibc_main,@function
> @@ -89,6 +93,25 @@ __start:
>  #else
>  	PTR_LA $28, _gp             /* Setup GP correctly if we're non-PIC.  */
>  	move $31, $0
> +#endif
> +#ifdef L_rcrt1
> +	PTR_LA $4, _DYNAMIC           /* Place _DYNAMIC into the GOT */
> +	REG_S $4, -0x7ff0($28)        /* offset to GOT stolen from dl-startup */
> +	jal .L0                       /* Get the current $pc address */
> +.L0:
> +	PTR_SUBU $4, $31, $25         /* Calculate load addr */
> +	move $31, $0                  /* Clear ra */
> +	and $29, -2 * SZREG           /* Ensure stack is aligned */
> +	PTR_ADDIU $29, (-2 * SZREG)   /* Allocate 2 register spaces on stack */
> +	REG_S $2, SZREG($29)          /* Store atexit in case it exists */
> +	PTR_LA $5, reloc_static_pie   /* function calls before relocation
> +	                                 don't work unless we set $t9 manually */
> +	PTR_ADDU $25, $4, $5          /* store reloc_static_pie in $t9 */
> +	jalr $25                      /* call reloc_static_pie */
> +	nop							  /* delay slot, just in case */
> +	REG_L $2, SZREG($29)          /* cleanup stack */
> +	PTR_ADDIU $29, $29, (2 * SZREG)
> +
>  #endif
>  
>  	PTR_LA $4, main		/* main */
> -- 
> 2.34.1
> 

> _______________________________________________
> devel mailing list -- devel@uclibc-ng.org
> To unsubscribe send an email to devel-leave@uclibc-ng.org
diff mbox series

Patch

From f5a4f77a396631bfceea2967b6a9100b09802f6c Mon Sep 17 00:00:00 2001
From: linted <linted@users.noreply.github.com>
Date: Sat, 20 Aug 2022 16:41:38 -0400
Subject: [PATCH] Added support for creation of Static Position-Independent
 Executables (PIE) on mips

Updated config to allow compilation of rcrt1.o for mips and modified it's crt1.S to perform relocates in __start.

The mips architecture performs relocations differently then most other architectures. reloc_static_pie was rewritten, taking code from dl-startup.c, in order to perfrom the additional relocations. Modifications were made to mips' dl-startup.h to allow for the use of contained macros without including _start definition.

Signed-off-by: linted <linted@users.noreply.github.com>
---
 extra/Configs/Config.in                |  2 +-
 ldso/ldso/mips/dl-startup.h            |  3 +-
 libc/misc/internals/Makefile.in        |  2 +-
 libc/misc/internals/reloc_static_pie.c | 93 +++++++++++++++++++++-----
 libc/sysdeps/linux/mips/crt1.S         | 23 +++++++
 5 files changed, 105 insertions(+), 18 deletions(-)

diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index e0905e956..43c04fd0a 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -324,7 +324,7 @@  config DOPIC
 config STATIC_PIE
 	bool "Add support for Static Position Independent Executables (PIE)"
 	default n
-	depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64)
+	depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm || TARGET_i386 || TARGET_x86_64 || TARGET_aarch64 || TARGET_mips)
 
 config ARCH_HAS_NO_SHARED
 	bool
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index 8026f1702..c2168d774 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -7,6 +7,7 @@ 
 
 
 #include <sgidefs.h>
+#ifndef L_rcrt1
 __asm__(""
     "	.text\n"
     "	.globl	_start\n"
@@ -114,6 +115,7 @@  __asm__(""
     "\n\n"
     ".previous\n"
 );
+#endif
 
 /*
  * Get a pointer to the argv array.  On many platforms this can be just
@@ -191,6 +193,5 @@  do {										\
 	case R_MIPS_NONE:							\
 		break;								\
 	default:								\
-		SEND_STDERR("Aiieeee!");					\
 		_dl_exit(1);							\
 	}
diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in
index 69af8b76e..908b18321 100644
--- a/libc/misc/internals/Makefile.in
+++ b/libc/misc/internals/Makefile.in
@@ -17,7 +17,7 @@  MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y))
 MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y))
 
 CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS)
-CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS)
+CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1
 
 libc-y += $(MISC_INTERNALS_OBJ)
 ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y)
diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c
index 578202d23..c0027de6f 100644
--- a/libc/misc/internals/reloc_static_pie.c
+++ b/libc/misc/internals/reloc_static_pie.c
@@ -15,33 +15,96 @@ 
    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 IS_IN_rtld      // force inline function calls
 #include <link.h>
 #include <elf.h>
 #include <dl-elf.h>
 
+#include <ldso.h>
+#ifdef __mips__
+#include <dl-startup.h>
+#endif
+
 ElfW(Addr) _dl_load_base = NULL;
 
 void
 reloc_static_pie (ElfW(Addr) load_addr);
 
 void
-reloc_static_pie (ElfW(Addr) load_addr)
+reloc_static_pie(ElfW(Addr) load_addr)
 {
-    ElfW(Word) relative_count = 0;
-    ElfW(Addr) rel_addr = 0;
-    ElfW(Dyn) * dyn_addr = NULL;
-    unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
+    int indx;
+    ElfW(Addr) got;
+    ElfW(Dyn) *dpnt;
+    struct elf_resolve tpnt_tmp;
+	struct elf_resolve *tpnt = &tpnt_tmp;
+
+    DL_BOOT_COMPUTE_GOT(got);
+    DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr);
+
+    _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
+    tpnt->loadaddr = load_addr;
+    tpnt->dynamic_addr = dpnt;
+
+    __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr);
+
+#if defined(PERFORM_BOOTSTRAP_GOT)
+	/* some arches (like MIPS) we have to tweak the GOT before relocations */
+	PERFORM_BOOTSTRAP_GOT(tpnt);
+#endif
+
+
+#if defined(ELF_MACHINE_PLTREL_OVERLAP)
+# define INDX_MAX 1
+#else
+# define INDX_MAX 2
+#endif
+
+    for (indx = 0; indx < INDX_MAX; indx++) {
+        unsigned long rel_addr, rel_size;
+        ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
+
+        rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] :
+                           tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]);
+        rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] :
+			               tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]);
+
+        if (!rel_addr)
+            continue;
 
-    /* Read our own dynamic section and fill in the info array.  */
-    dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
+        if((0 == indx) && relative_count) {
+			rel_size -= relative_count * sizeof(ELF_RELOC);
+            elf_machine_relative(load_addr, rel_addr, relative_count);
+			rel_addr += relative_count * sizeof(ELF_RELOC);
+        }
 
-    /* Use the underlying function to avoid TLS access before initialization */
-    __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
+#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS
+			{
+				ELF_RELOC *rpnt;
+				unsigned int i;
+				ElfW(Sym) *sym;
+				unsigned long symbol_addr;
+				int symtab_index;
+				unsigned long *reloc_addr;
 
-    /* Perform relocations */
-    relative_count = dynamic_info[DT_RELCONT_IDX];
-    rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
-    elf_machine_relative(load_addr, rel_addr, relative_count);
+				/* Now parse the relocation information */
+				rpnt = (ELF_RELOC *) rel_addr;
+				for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+					reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset);
+					symtab_index = ELF_R_SYM(rpnt->r_info);
+					symbol_addr = 0;
+					sym = NULL;
+					if (symtab_index) {
+						ElfW(Sym) *symtab;
+						symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+						sym = &symtab[symtab_index];
+						symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value);
+					}
+					/* Use this machine-specific macro to perform the actual relocation.  */
+					PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym);
+				}
+			}
+#endif
+    }
     _dl_load_base = load_addr;
-}
+}
\ No newline at end of file
diff --git a/libc/sysdeps/linux/mips/crt1.S b/libc/sysdeps/linux/mips/crt1.S
index 083615515..7c4db447c 100644
--- a/libc/sysdeps/linux/mips/crt1.S
+++ b/libc/sysdeps/linux/mips/crt1.S
@@ -77,6 +77,10 @@ 
 #ifndef __UCLIBC_CTOR_DTOR__
 	.weak	_init
 	.weak	_fini
+#endif
+#ifdef L_rcrt1
+	.type	reloc_static_pie,@function
+	.hidden	.L0
 #endif
 	.type	    main,@function
 	.type	    __uClibc_main,@function
@@ -89,6 +93,25 @@  __start:
 #else
 	PTR_LA $28, _gp             /* Setup GP correctly if we're non-PIC.  */
 	move $31, $0
+#endif
+#ifdef L_rcrt1
+	PTR_LA $4, _DYNAMIC           /* Place _DYNAMIC into the GOT */
+	REG_S $4, -0x7ff0($28)        /* offset to GOT stolen from dl-startup */
+	jal .L0                       /* Get the current $pc address */
+.L0:
+	PTR_SUBU $4, $31, $25         /* Calculate load addr */
+	move $31, $0                  /* Clear ra */
+	and $29, -2 * SZREG           /* Ensure stack is aligned */
+	PTR_ADDIU $29, (-2 * SZREG)   /* Allocate 2 register spaces on stack */
+	REG_S $2, SZREG($29)          /* Store atexit in case it exists */
+	PTR_LA $5, reloc_static_pie   /* function calls before relocation
+	                                 don't work unless we set $t9 manually */
+	PTR_ADDU $25, $4, $5          /* store reloc_static_pie in $t9 */
+	jalr $25                      /* call reloc_static_pie */
+	nop							  /* delay slot, just in case */
+	REG_L $2, SZREG($29)          /* cleanup stack */
+	PTR_ADDIU $29, $29, (2 * SZREG)
+
 #endif
 
 	PTR_LA $4, main		/* main */
-- 
2.34.1