d32dadd60efb9d3b255351a3b532f8e4c3dd0db1 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. From d32dadd60efb9d3b255351a3b532f8e4c3dd0db1 Mon Sep 17 00:00:00 2001
  2. From: Fangrui Song <i@maskray.me>
  3. Date: Tue, 2 Aug 2022 17:24:47 -0400
  4. Subject: ldso: support DT_RELR relative relocation format
  5. this resolves DT_RELR relocations in non-ldso, dynamic-linked objects.
  6. ---
  7. include/elf.h | 8 ++++++--
  8. ldso/dynlink.c | 21 ++++++++++++++++++++-
  9. src/internal/dynlink.h | 2 +-
  10. 3 files changed, 27 insertions(+), 4 deletions(-)
  11. diff --git a/include/elf.h b/include/elf.h
  12. index 86e2f0bb..9e980a29 100644
  13. --- a/include/elf.h
  14. +++ b/include/elf.h
  15. @@ -385,7 +385,8 @@ typedef struct {
  16. #define SHT_PREINIT_ARRAY 16
  17. #define SHT_GROUP 17
  18. #define SHT_SYMTAB_SHNDX 18
  19. -#define SHT_NUM 19
  20. +#define SHT_RELR 19
  21. +#define SHT_NUM 20
  22. #define SHT_LOOS 0x60000000
  23. #define SHT_GNU_ATTRIBUTES 0x6ffffff5
  24. #define SHT_GNU_HASH 0x6ffffff6
  25. @@ -754,7 +755,10 @@ typedef struct {
  26. #define DT_PREINIT_ARRAY 32
  27. #define DT_PREINIT_ARRAYSZ 33
  28. #define DT_SYMTAB_SHNDX 34
  29. -#define DT_NUM 35
  30. +#define DT_RELRSZ 35
  31. +#define DT_RELR 36
  32. +#define DT_RELRENT 37
  33. +#define DT_NUM 38
  34. #define DT_LOOS 0x6000000d
  35. #define DT_HIOS 0x6ffff000
  36. #define DT_LOPROC 0x70000000
  37. diff --git a/ldso/dynlink.c b/ldso/dynlink.c
  38. index cc677952..e92f03cb 100644
  39. --- a/ldso/dynlink.c
  40. +++ b/ldso/dynlink.c
  41. @@ -210,7 +210,8 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt)
  42. size_t i;
  43. for (i=0; i<cnt; i++) a[i] = 0;
  44. for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
  45. - a[0] |= 1UL<<v[0];
  46. + if (v[0] < 8*sizeof(long))
  47. + a[0] |= 1UL<<v[0];
  48. a[v[0]] = v[1];
  49. }
  50. }
  51. @@ -515,6 +516,23 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
  52. }
  53. }
  54. +static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size)
  55. +{
  56. + unsigned char *base = dso->base;
  57. + size_t *reloc_addr;
  58. + for (; relr_size; relr++, relr_size-=sizeof(size_t))
  59. + if ((relr[0]&1) == 0) {
  60. + reloc_addr = laddr(dso, relr[0]);
  61. + *reloc_addr++ += (size_t)base;
  62. + } else {
  63. + int i = 0;
  64. + for (size_t bitmap=relr[0]; (bitmap>>=1); i++)
  65. + if (bitmap&1)
  66. + reloc_addr[i] += (size_t)base;
  67. + reloc_addr += 8*sizeof(size_t)-1;
  68. + }
  69. +}
  70. +
  71. static void redo_lazy_relocs()
  72. {
  73. struct dso *p = lazy_head, *next;
  74. @@ -1357,6 +1375,7 @@ static void reloc_all(struct dso *p)
  75. 2+(dyn[DT_PLTREL]==DT_RELA));
  76. do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
  77. do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
  78. + do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);
  79. if (head != &ldso && p->relro_start != p->relro_end) {
  80. long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
  81. diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h
  82. index 51c0639f..830354eb 100644
  83. --- a/src/internal/dynlink.h
  84. +++ b/src/internal/dynlink.h
  85. @@ -93,7 +93,7 @@ struct fdpic_dummy_loadmap {
  86. #endif
  87. #define AUX_CNT 32
  88. -#define DYN_CNT 32
  89. +#define DYN_CNT 37
  90. typedef void (*stage2_func)(unsigned char *, size_t *);
  91. --
  92. cgit v1.2.1