diff options
| author | Fangrui Song <i@maskray.me> | 2022-08-02 17:24:47 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2022-08-02 17:27:45 -0400 | 
| commit | d32dadd60efb9d3b255351a3b532f8e4c3dd0db1 (patch) | |
| tree | 138a5a8889ec07ec020f12ecea4a7341611319b0 | |
| parent | 2404d9d643763e6eceafa9a1918925d80a84ad44 (diff) | |
| download | musl-d32dadd60efb9d3b255351a3b532f8e4c3dd0db1.tar.gz | |
ldso: support DT_RELR relative relocation format
this resolves DT_RELR relocations in non-ldso, dynamic-linked objects.
| -rw-r--r-- | include/elf.h | 8 | ||||
| -rw-r--r-- | ldso/dynlink.c | 21 | ||||
| -rw-r--r-- | src/internal/dynlink.h | 2 | 
3 files changed, 27 insertions, 4 deletions
diff --git a/include/elf.h b/include/elf.h index 86e2f0bb..9e980a29 100644 --- a/include/elf.h +++ b/include/elf.h @@ -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 @@ -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 diff --git a/ldso/dynlink.c b/ldso/dynlink.c index cc677952..e92f03cb 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -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];  	}  } @@ -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; @@ -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), diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 51c0639f..830354eb 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -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 *);  | 
