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

Support PLT entries in cranelift-jit crate on aarch64 #2735

Open
benmkw opened this issue Mar 17, 2021 · 9 comments
Open

Support PLT entries in cranelift-jit crate on aarch64 #2735

benmkw opened this issue Mar 17, 2021 · 9 comments
Labels
cranelift:area:aarch64 Issues related to AArch64 backend. cranelift Issues related to the Cranelift code generator

Comments

@benmkw
Copy link

benmkw commented Mar 17, 2021

Feature

JIT for arm64

Benefit

x86 works and it would be nice to be able to use it on M1 mac as well

Implementation

it currently panics here:

unsafe fn write_plt_entry_bytes(plt_ptr: *mut [u8; 16], got_ptr: *mut *const u8) {
assert!(
cfg!(target_arch = "x86_64"),
"PLT is currently only supported on x86_64"
);
// jmp *got_ptr; ud2; ud2; ud2; ud2; ud2
let mut plt_val = [
0xff, 0x25, 0, 0, 0, 0, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b, 0x0f, 0x0b,
];
let what = got_ptr as isize - 4;
let at = plt_ptr as isize + 2;
plt_val[2..6].copy_from_slice(&i32::to_ne_bytes(i32::try_from(what - at).unwrap()));
std::ptr::write(plt_ptr, plt_val);
I'm unsure what needs to change/ whats blocking it

Alternatives

only make JIT available on x86

@cfallin cfallin changed the title JIT for arm Support PLT entries in cranelift-jit crate on aarch64 Mar 17, 2021
@cfallin
Copy link
Member

cfallin commented Mar 17, 2021

@bnjbvr any thoughts on this? I'm not sure how PLTs ordinarily work on macOS/aarch64 but perhaps it's a simple addition?

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 17, 2021

As workaround you could disable the is_pic flag when creating the TargetIsa.

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 17, 2021

This is one of the plt entries of an executable I compiled on my phone:

90 01 00 B0    adrp x16, #0x31000
11 F2 46 F9    ldr  x17, [x16, #0xde0]
10 82 37 91    add  x16, x16, #0xde0
20 02 1F D6    br   x17

@benmkw
Copy link
Author

benmkw commented Mar 17, 2021

As workaround you could disable the is_pic flag when creating the TargetIsa.

Tried with https://github.com/bytecodealliance/cranelift-jit-demo

diff --git a/Cargo.toml b/Cargo.toml
index 756983f..f6dd93f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,8 @@ description = "Toy language implemented using cranelift-jit"
 edition = "2018"
 
 [dependencies]
-cranelift = "0.69.0"
-cranelift-module = "0.69.0"
-cranelift-jit = "0.69.0"
+cranelift = "0.72.0"
+cranelift-module = "0.72.0"
+cranelift-jit = "0.72.0"
+cranelift-native = "0.72.0"
 peg = "0.6"
diff --git a/src/jit.rs b/src/jit.rs
index 160ac36..ffcff04 100644
--- a/src/jit.rs
+++ b/src/jit.rs
@@ -26,7 +26,17 @@ pub struct JIT {
 
 impl Default for JIT {
     fn default() -> Self {
-        let builder = JITBuilder::new(cranelift_module::default_libcall_names());
+        let mut flag_builder = settings::builder();
+        // On at least AArch64, "colocated" calls use shorter-range relocations,
+        // which might not reach all definitions; we can't handle that here, so
+        // we require long-range relocation types.
+        flag_builder.set("use_colocated_libcalls", "false").unwrap();
+        flag_builder.set("is_pic", "false").unwrap();
+        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
+            panic!("host machine is not supported: {}", msg);
+        });
+        let isa = isa_builder.finish(settings::Flags::new(flag_builder));
+        let builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
         let module = JITModule::new(builder);
         Self {
             builder_context: FunctionBuilderContext::new(),
λ  (main|✚ 2) cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/toy`
the answer is: 42
recursive_fib(10) = 55
iterative_fib(10) = 55
hello world!

I could maybe PR that because I don't see how PIC is really relevant to the demo and it would make it work on more platforms

@bnjbvr
Copy link
Member

bnjbvr commented Mar 22, 2021

I don't know how PLT tables work in MacOS/aarch64 either. It's easy to make it work for our use case (load from pointer into reg + branch into it), but if the linker expects a precise sequence like the one from @bjorn3's comment, we'd need to find what is precisely expected. I don't plan to work on this immediately, yet I'd be happy to try patches if that can help!

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 22, 2021

In case of cranelift-jit no linker is involved. Or rather cranelift-jit is kind of the linker itself. It is not necessary to copy the exact same sequence. (Even on x86_64 I didn't use the exact same sequence) I merely posted it to show what it would roughly need to look like. Basically all the PLT entry needs to do in the case of cranelift-jit on any platform is load the corresponding GOT entry and jump to the loaded address. This is independent of the OS, but once Rust supports pointer authentication on the M1, the PLT entry code will need to be adapted to support pointer authentication.

@evaporei
Copy link

evaporei commented Apr 2, 2021

Is this related to: bytecodealliance/wasmtime-go#53?

@cfallin
Copy link
Member

cfallin commented Apr 2, 2021

@octaviopace no, this issue doesn't need to be solved in order to run Wasmtime on macOS/aarch64 (M1) -- the cranelift-jit crate isn't used by Wasmtime.

@akirilov-arm akirilov-arm added cranelift Issues related to the Cranelift code generator cranelift:area:aarch64 Issues related to AArch64 backend. labels Oct 1, 2021
@akirilov-arm
Copy link
Contributor

Issue #2907 is related to this.

sampsyo added a commit to sampsyo/bril that referenced this issue May 28, 2022
This involves a workaround for incomplete PIC support in `cranelift_jit`
on ARM:
bytecodealliance/wasmtime#2735

The workaround is just to disable PIC on that platform, but it
unfortunately requires duplicating a little code from the library
because the `JITBuilder::new` is hard-coded to use PIC.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:aarch64 Issues related to AArch64 backend. cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

No branches or pull requests

6 participants