#include <cheri_perms.h>
static inline uintptr_t
-morello_relative (uintptr_t base,
- const ElfW(Rela) *reloc,
- void *reloc_addr)
+morello_relative (uint64_t base, uintptr_t cap_rx, uintptr_t cap_rw,
+ const ElfW(Rela) *reloc, void *reloc_addr)
{
uint64_t *__attribute__((may_alias)) u64_reloc_addr = reloc_addr;
unsigned long perm = u64_reloc_addr[1] >> 56;
uintptr_t value;
- value = base + loc;
+ /* Permissions field is encoded as:
+ 4 = executable, 2 = read/write, 1 = read-only. */
+ if (perm == 2)
+ value = __builtin_cheri_address_set (cap_rw, base + loc);
+ else
+ value = __builtin_cheri_address_set (cap_rx, base + loc);
value = __builtin_cheri_bounds_set_exact (value, len);
if (perm == 1)
value = __builtin_cheri_perms_and (value, CAP_PERM_MASK_R);
- if (perm == 2)
- value = __builtin_cheri_perms_and (value, CAP_PERM_MASK_RW);
- if (perm == 4)
- value = __builtin_cheri_perms_and (value, CAP_PERM_MASK_RX);
/* Seal executable capabilities with MORELLO_RB. */
if (perm == 4)
}
static void
-apply_rel (uintptr_t base, uintptr_t start, uintptr_t end)
+apply_rel (uintptr_t cap_rx, uintptr_t cap_rw, uintptr_t start, uintptr_t end)
{
const ElfW(Rela) *r;
for (r = (const ElfW(Rela) *)start; r != (void *)end; r++)
{
- uintptr_t *reloc_addr = base + r->r_offset;
- uintptr_t value = morello_relative (base, r, reloc_addr);
+ uintptr_t *reloc_addr =
+ (uintptr_t *) __builtin_cheri_address_set (cap_rw, r->r_offset);
+ uintptr_t value = morello_relative (0, cap_rx, cap_rw, r, reloc_addr);
*reloc_addr = value;
}
}
uintptr_t start = get_rela_dyn_start ();
uintptr_t end = get_rela_dyn_end ();
uintptr_t base = get_base ();
- apply_rel (base, start, end);
+ apply_rel (base, base, start, end);
rtld_fini = 0;
}
/* Compiler barrier after relocs are processed. */