Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Morello: Stop using caprelocs for static binaries #2286

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from

Conversation

bsdjhb
Copy link
Collaborator

@bsdjhb bsdjhb commented Jan 8, 2025

  • csu: Add support for ELF relocations to init caps for static binaries
  • morello: Support R_MORELLO_RELATIVE relocations in static binaries
  • rtld: Workaround Morello LLVM lld bug with local-caprelocs=elf
  • Enable --local-caprelocs=elf for Morello

@bsdjhb bsdjhb requested a review from jrtc27 January 8, 2025 14:23
@bsdjhb
Copy link
Collaborator Author

bsdjhb commented Jan 8, 2025

I have a request to fix the bug in Morello lld at https://git.morello-project.org/morello/llvm-project/-/merge_requests/307, but it may be a while before we can assume it is fixed. The workaround should let us work with existing lld for now and we can eventually drop it.

#ifdef __CHERI_PURE_CAPABILITY__
#if defined(__aarch64__)
__asm__ (
"adrp %0, __rela_dyn_start\n\t"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this in crt.h as some #define FOO(x) ({ __typeof__(x) *_p; __asm__ ("adrp %0, %c1; add %0, %0, :lo12:%c1" : "=C"(_p) : "i"(&x)); _p; })? Hybrid can define it to just &x.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Or crt1_c.c where CHERI_INIT_RELA lives)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it can also be part of the second commit that adds Morello support specifically

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yeah, that might be fine, and certainly cleaner. PCREL_PTR() maybe?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, seems fine, name doesn't hugely matter, it's internal to csu

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After adding a description in the commit log I ended up going with RODATA_PTR() for the name.

bsdjhb added 3 commits January 8, 2025 12:40
This is to support the --local-caprelocs=elf flag to lld.  When this
is specified, an ELF relocation table is emitted.  The table is
identified by the hidden symbols __rela_dyn_start and __rela_dyn_end.

If an architecture defines CHERI_INIT_RELA, then crt_init_globals()
will look for this table.  For each relocation found, an MD function
provided by the architecture is called to handle the relocation.  The
function's signature is:

    elf_reloc(const Elf_Rela *, void * __capability data_cap,
       const void * __capability code_cap, Elf_Addr relocbase)

In addition, an architecture must define a RODATA_PTR helper macro
which accepts a symbol name as its sole argument and returns a
readable pointer.  For hybrid this can just use the normal address-of
operator, but for purecap this has to avoid depending on an ELF
relocation and instead derive the pointer from an existing capability
such as PCC.
A shared header containing the implementation of elf_reloc is used to
avoid duplicating code between hybrid and purecap.  The
init_cap_from_fragment function is copied directly from rtld (might be
nice to move that function to a shared header).
Morello LLVM's lld always emits PLT-related .dynamic entries when ELF
local caprelocs are used even if the PLT is empty.  This confuses rtld
which tries to treat the start of the binary as a GOT PLT.  In
particular, rtld itself ends up with an empty PLT and so rtld tries to
write to its ELF header which crashes since the page is mapped
read-only.

Workaround this by ignoring DT_JMPREL and DT_PLTGOT entries whose
value is 0.  The PLT GOT and PLT relocation table can never be at the
start of a valid binary.
@bsdjhb bsdjhb force-pushed the morello_static_rela branch from 9bb66ed to ee51273 Compare January 8, 2025 17:43
This is done in bsd.{lib,prog}.mk instead of bsd.cpu.mk as it can't be
turned off for the lib32 build otherwise.
@bsdjhb bsdjhb force-pushed the morello_static_rela branch from ee51273 to c9c2b04 Compare January 9, 2025 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants