Hello Waldemar, currently i haven't any ideas but i will check this ASAP and fix the issue.
Hi Dmitry,
thanks for the patch.
Unfortunately it breaks ARM FDPIC toolchain building:
ldso/ldso/dl-startup.c: In function '_dl_start':
ldso/ldso/dl-startup.c:268:9: error: aggregate value used where an
integer was expected
268 | DL_RELOCATE_RELR(tpnt);
| ^~~~~~~~~~~~~~~~
You could use OpenADK to produce such a toolchain.
Any idea what is wrong?
best regards
Waldemar
Dmitry Chestnykh wrote,
> Nowadays modern libcs like Glibc and musl currently
> support processing of RELATIVE relocations compressed
> with DT_RELR format. However I have noticed that uClibc-ng
> doesn't support this feature and if the source will be linked with
> `-Wl,-z,pack-relative-relos` (bfd) or `-Wl,--pack-dyn-relocs=relr`
> (lld) then ld.so cannot properly load the produced DSO.
> This patch is intended to fix this issue and adds applying
> of DT_RELR relative relocation.
>
> Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
> ---
> include/elf.h | 8 +++++-
> ldso/include/dl-elf.h | 38 ++++++++++++++++++++++++++
> ldso/ldso/dl-elf.c | 3 ++
> ldso/ldso/dl-startup.c | 3 ++
> libc/misc/internals/reloc_static_pie.c | 1 +
> 5 files changed, 52 insertions(+), 1 deletion(-)
>
> diff --git a/include/elf.h b/include/elf.h
> index b7edbade2..c2efa9978 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -60,6 +60,9 @@ typedef uint16_t Elf64_Section;
> typedef Elf32_Half Elf32_Versym;
> typedef Elf64_Half Elf64_Versym;
>
> +/* Type for relative relocations in DT_RELR format */
> +typedef Elf32_Word Elf32_Relr;
> +typedef Elf64_Xword Elf64_Relr;
>
> /* The ELF file header. This appears at the start of every ELF file. */
>
> @@ -818,7 +821,10 @@ typedef struct
> #define DT_ENCODING 32 /* Start of encoded range */
> #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
> #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
> -#define DT_NUM 34 /* Number used */
> +#define DT_RELRSZ 35 /* Size in bytes, of DT_RELR table */
> +#define DT_RELR 36 /* Address of Relr relocs */
> +#define DT_RELRENT 37 /* Size in bytes of one DT_RELR entry */
> +#define DT_NUM 38 /* Number used */
> #define DT_LOOS 0x6000000d /* Start of OS-specific */
> #define DT_HIOS 0x6ffff000 /* End of OS-specific */
> #define DT_LOPROC 0x70000000 /* Start of processor-specific */
> diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
> index 2b99958d9..10b895733 100644
> --- a/ldso/include/dl-elf.h
> +++ b/ldso/include/dl-elf.h
> @@ -250,5 +250,43 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
> (((X) & PF_W) ? PROT_WRITE : 0) | \
> (((X) & PF_X) ? PROT_EXEC : 0))
>
> +/* Apply relocations in DT_RELR format */
> +#define DL_DO_RELOCATE_RELR(load_addr, relr_start, relr_end) \
> + do { \
> + const ElfW(Relr) *relr = 0; \
> + ElfW(Addr) *reloc_addr = 0; \
> + for (relr = relr_start; relr < relr_end; relr++) { \
> + ElfW(Relr) relr_entry = *relr; \
> + if (!(relr_entry & 1)) \
> + { \
> + reloc_addr = (ElfW(Addr) *)DL_RELOC_ADDR(load_addr, relr_entry); \
> + *reloc_addr = (ElfW(Addr))DL_RELOC_ADDR(load_addr, reloc_addr); \
> + reloc_addr++; \
> + } \
> + else \
> + { \
> + for (long int i = 0; (relr_entry >>= 1) != 0; ++i) { \
> + if ((relr_entry & 1) != 0) \
> + reloc_addr[i] = (ElfW(Addr))DL_RELOC_ADDR(load_addr, reloc_addr[i]); \
> + } \
> + reloc_addr += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \
> + } \
> + } \
> + } while (0);
> +
> +/* The macro to prepare data for the above DL_DO_RELOCATE_RELR */
> +#define DL_RELOCATE_RELR(dyn) \
> + do { \
> + if (dyn->dynamic_info[DT_RELRENT]) \
> + _dl_assert(dyn->dynamic_info[DT_RELRENT] == sizeof(ElfW(Relr))); \
> + if (dyn->dynamic_info[DT_RELR] && \
> + dyn->dynamic_info[DT_RELRSZ]) { \
> + ElfW(Relr) *relr_start = (ElfW(Relr) *)((ElfW(Addr))dyn->loadaddr + (ElfW(Addr))dyn->dynamic_info[DT_RELR]); \
> + ElfW(Relr) *relr_end = (ElfW(Relr) *)((const char *)relr_start + dyn->dynamic_info[DT_RELRSZ]); \
> + _dl_if_debug_dprint("Relocating DT_RELR in %s: start:%p, end:%p\n", \
> + dyn->libname, (void *)relr_start, (void *)relr_end); \
> + DL_DO_RELOCATE_RELR(dyn->loadaddr, relr_start, relr_end); \
> + } \
> + } while (0);
>
> #endif /* _DL_ELF_H */
> diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
> index 8210a012e..cc42b904f 100644
> --- a/ldso/ldso/dl-elf.c
> +++ b/ldso/ldso/dl-elf.c
> @@ -1027,6 +1027,9 @@ int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)
> return goof;
> }
>
> + /* Process DT_RELR relative relocations */
> + DL_RELOCATE_RELR(tpnt);
> +
> reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE];
> /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its
> range. Note that according to the ELF spec, this is completely legal! */
> diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
> index 989711fcc..674c4b7b9 100644
> --- a/ldso/ldso/dl-startup.c
> +++ b/ldso/ldso/dl-startup.c
> @@ -264,6 +264,9 @@ DL_START(unsigned long args)
> that once we are done, we have considerably more flexibility. */
> SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n");
>
> + /* Process DT_RELR relative relocations */
> + DL_RELOCATE_RELR(tpnt);
> +
> {
> int indx;
> #if defined(ELF_MACHINE_PLTREL_OVERLAP)
> diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c
> index ab1923024..7ad80f97b 100644
> --- a/libc/misc/internals/reloc_static_pie.c
> +++ b/libc/misc/internals/reloc_static_pie.c
> @@ -53,6 +53,7 @@ reloc_static_pie(ElfW(Addr) load_addr)
> PERFORM_BOOTSTRAP_GOT(tpnt);
> #endif
>
> + DL_RELOCATE_RELR(tpnt);
>
> #if defined(ELF_MACHINE_PLTREL_OVERLAP)
> # define INDX_MAX 1
> --
> 2.43.0
>
> _______________________________________________
> devel mailing list -- devel@uclibc-ng.org
> To unsubscribe send an email to devel-leave@uclibc-ng.org
>