Index: libexec/rtld-elf/rtld.h =================================================================== --- libexec/rtld-elf/rtld.h +++ libexec/rtld-elf/rtld.h @@ -174,6 +174,8 @@ unsigned long relsize; /* Size in bytes of relocation info */ const Elf_Rela *rela; /* Relocation entries with addend */ unsigned long relasize; /* Size in bytes of addend relocation info */ + const Elf_Relr *relr; /* RELR relocation entries */ + unsigned long relrsize; /* Size in bytes of RELR relocations */ const Elf_Rel *pltrel; /* PLT relocation entries */ unsigned long pltrelsize; /* Size in bytes of PLT relocation info */ const Elf_Rela *pltrela; /* PLT relocation entries with addend */ Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c +++ libexec/rtld-elf/rtld.c @@ -1255,6 +1255,14 @@ assert(dynp->d_un.d_val == sizeof(Elf_Rela)); break; + case DT_RELR: + obj->relr = (const Elf_Relr *)(obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_RELRSZ: + obj->relrsize = dynp->d_un.d_val; + break; + case DT_PLTREL: plttype = dynp->d_un.d_val; assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); @@ -3148,6 +3156,29 @@ return (0); } +/* Process RELR relative relocations. */ +static void +reloc_relr(Obj_Entry *obj) +{ + const Elf_Relr *relr, *relrlim; + Elf_Addr *where; + + relrlim = (const Elf_Relr *)((const char *)obj->relr + obj->relrsize); + for (relr = obj->relr; relr < relrlim; relr++) { + Elf_Relr entry = *relr; + if (entry % 2 == 0) { + where = (Elf_Addr *)(obj->relocbase + entry); + *where++ += (Elf_Addr)obj->relocbase; + } else { + long i = 0; + for (; (entry >>= 1) != 0; i++) + if (entry % 2 != 0) + where[i] += (Elf_Addr)obj->relocbase; + where += 8 * sizeof(Elf_Relr) - 1; + } + } +} + /* * Relocate single object. * Returns 0 on success, or -1 on failure. @@ -3174,6 +3205,7 @@ /* Process the non-PLT non-IFUNC relocations. */ if (reloc_non_plt(obj, rtldobj, flags, lockstate)) return (-1); + reloc_relr(obj); /* Re-protected the text segment. */ if (obj->textrel && reloc_textrel_prot(obj, false) != 0) Index: sys/sys/elf32.h =================================================================== --- sys/sys/elf32.h +++ sys/sys/elf32.h @@ -152,6 +152,8 @@ /* Macro for constructing r_info from field values. */ #define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) +typedef Elf32_Word Elf32_Relr; + /* * Note entry header */ Index: sys/sys/elf64.h =================================================================== --- sys/sys/elf64.h +++ sys/sys/elf64.h @@ -166,6 +166,8 @@ #define ELF64_R_TYPE_INFO(data, type) \ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) +typedef Elf64_Xword Elf64_Relr; + /* * Note entry header */ Index: sys/sys/elf_common.h =================================================================== --- sys/sys/elf_common.h +++ sys/sys/elf_common.h @@ -617,6 +617,9 @@ #define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of pre-initialization functions. */ #define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_RELRSZ 35 /* Total size of ElfNN_Relr relocations. */ +#define DT_RELR 36 /* Address of ElfNN_Relr relocations. */ +#define DT_RELRENT 37 /* Size of each ElfNN_Relr relocation. */ #define DT_LOOS 0x6000000d /* First OS-specific */ #define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ #define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ Index: sys/sys/elf_generic.h =================================================================== --- sys/sys/elf_generic.h +++ sys/sys/elf_generic.h @@ -71,6 +71,7 @@ __ElfType(Dyn); __ElfType(Rel); __ElfType(Rela); +__ElfType(Relr); __ElfType(Sym); __ElfType(Verdef); __ElfType(Verdaux);