Skip to content

Commit

Permalink
ldso: support DT_RELR relative relocation format
Browse files Browse the repository at this point in the history
this resolves DT_RELR relocations in non-ldso, dynamic-linked objects.
  • Loading branch information
MaskRay authored and richfelker committed Aug 2, 2022
1 parent 2404d9d commit d32dadd
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
8 changes: 6 additions & 2 deletions include/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ typedef struct {
#define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18
#define SHT_NUM 19
#define SHT_RELR 19
#define SHT_NUM 20
#define SHT_LOOS 0x60000000
#define SHT_GNU_ATTRIBUTES 0x6ffffff5
#define SHT_GNU_HASH 0x6ffffff6
Expand Down Expand Up @@ -754,7 +755,10 @@ typedef struct {
#define DT_PREINIT_ARRAY 32
#define DT_PREINIT_ARRAYSZ 33
#define DT_SYMTAB_SHNDX 34
#define DT_NUM 35
#define DT_RELRSZ 35
#define DT_RELR 36
#define DT_RELRENT 37
#define DT_NUM 38
#define DT_LOOS 0x6000000d
#define DT_HIOS 0x6ffff000
#define DT_LOPROC 0x70000000
Expand Down
21 changes: 20 additions & 1 deletion ldso/dynlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt)
size_t i;
for (i=0; i<cnt; i++) a[i] = 0;
for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
a[0] |= 1UL<<v[0];
if (v[0] < 8*sizeof(long))
a[0] |= 1UL<<v[0];
a[v[0]] = v[1];
}
}
Expand Down Expand Up @@ -515,6 +516,23 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
}
}

static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size)
{
unsigned char *base = dso->base;
size_t *reloc_addr;
for (; relr_size; relr++, relr_size-=sizeof(size_t))
if ((relr[0]&1) == 0) {
reloc_addr = laddr(dso, relr[0]);
*reloc_addr++ += (size_t)base;
} else {
int i = 0;
for (size_t bitmap=relr[0]; (bitmap>>=1); i++)
if (bitmap&1)
reloc_addr[i] += (size_t)base;
reloc_addr += 8*sizeof(size_t)-1;
}
}

static void redo_lazy_relocs()
{
struct dso *p = lazy_head, *next;
Expand Down Expand Up @@ -1357,6 +1375,7 @@ static void reloc_all(struct dso *p)
2+(dyn[DT_PLTREL]==DT_RELA));
do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);

if (head != &ldso && p->relro_start != p->relro_end) {
long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
Expand Down
2 changes: 1 addition & 1 deletion src/internal/dynlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct fdpic_dummy_loadmap {
#endif

#define AUX_CNT 32
#define DYN_CNT 32
#define DYN_CNT 37

typedef void (*stage2_func)(unsigned char *, size_t *);

Expand Down

0 comments on commit d32dadd

Please sign in to comment.