CensoredUsername / dynasm-rs

A dynasm-like tool for rust.
https://censoredusername.github.io/dynasm-rs/language/index.html
Mozilla Public License 2.0
705 stars 52 forks source link

ImpossibleRelocation error on seemingly valid AArch64 code #79

Closed john-h-k closed 10 months ago

john-h-k commented 1 year ago

Hey, this is my first time using this library, so I apologise if I've made a stupid mistake, but this is really stumping me:

dynasm!(asm
    ; .arch aarch64
    ; ldrb w1, [x0]
    ; cbs w1, =>end
    ; .align 4
    ; =>start
)

(the other part of the generation has ; .align 4; => end. both are dynamic labels)

But when I attempt to run this, I get an ImpossibleRelocation error, and I'm not sure why. As far as I know, provided it is within range (which it definitely is, this code isn't more than a few hundred bytes apart) and aligned to 4 bytes, these labels should be valid?

CensoredUsername commented 1 year ago

(I'm assuming the relevant instruction was cbz, not cbs 😉)

I'm not sure what's happening here unfortunately. cbz's target has to be a signed immediate multiple of 4, and the range is like +/- 1MB. As long as these requirements are met it should be able to work.

The relevant check that supposedly is creating the error would be here: https://github.com/CensoredUsername/dynasm-rs/blob/master/runtime/src/aarch64.rs#L70 . That'd probably be a good point to start debugging. Unfortunately with your example I really cannot really reproduce it easily. Do you may

Are you sure this is the location causing the error? I tried making a simple reproduction case:

    let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
    let start = ops.new_dynamic_label();
    let end = ops.new_dynamic_label();
    dynasm!(ops
        ; .arch aarch64
        ; ldrb w1, [x0]
        ; cbz w1, =>end
        ; .align 4
        ; =>start
        ; .bytes b"abcdef123"
        ; .align 4
        ; => end
    );
    let buf = ops.finalize().unwrap();

but that assembled just fine.

john-h-k commented 1 year ago

Thanks, turns out it was user error, I'd managed to use dynasmrt::x64::Assembler accidentally and it seems that was causing the issue.

That's all resolved, but if I can point out one other issue - it seems mov w0, <immediate> expects a u64 and mov x0, <immediate> expects a u32, which to my understanding is the wrong way round

CensoredUsername commented 1 year ago

Thanks, turns out it was user error, I'd managed to use dynasmrt::x64::Assembler accidentally and it seems that was causing the issue.

A yep, that'd do it. Due to a lack of nice to use associated types on structs in rust the interface between assemblers is somewhat weakly typed unfortunately.

That's all resolved, but if I can point out one other issue - it seems mov w0, expects a u64 and mov x0, expects a u32, which to my understanding is the wrong way round

Looking at the code both seem to actually expect an u64 if encoded at runtime, does that match your observations? That's indeed a bit useless for mov w0, . https://github.com/CensoredUsername/dynasm-rs/blob/master/plugin/src/arch/aarch64/compiler.rs#L609 is the offending line, but fixing that right now is both low priority and a breaking change.

It's probably an artifact from the fact that compile-time encoding of constants always uses u64's internally

john-h-k commented 10 months ago

All resolved thanks