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

llvm-objdump emits <unknown> and wrong register names when using "smc" and "TTBR0_EL2" on arm64(aarch64) #53956

Closed
PG-MANA opened this issue Feb 20, 2022 · 9 comments
Labels
backend:AArch64 mc Machine (object) code

Comments

@PG-MANA
Copy link

PG-MANA commented Feb 20, 2022

When I disassembly the aarch64 binary containg "smc 0" and "mrs x0, TTBR0_EL2", I found the result of "llvm-objdump -d " are different between llvm13 and llvm14.
llvm14-objdump emits "smc 0" as "<unknown>", and " mrs x0, TTBR0_EL2" as "mrs x0, S3_4_C2_C0_0".
llvm13-objdump seems printing correctly.

Test Code

//test.c
int main(void) {
        asm volatile ("smc 0");
        asm volatile ("mrs x0, TTBR0_EL2");
        return 0;
}

LLVM Version

I installed llvm 13 and 14 from https://apt.llvm.org/ on ubuntu.

$ llvm-objdump-13 --version
Ubuntu LLVM version 13.0.1

$ llvm-objdump-14 --version
Ubuntu LLVM version 14.0.0

Compile Command

$ clang-14 --target=aarch64-none-elf  -ffreestanding  -c test.c

Result

$ llvm-objdump-13 -d test.o

test.o: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <main>:
       0: 03 00 00 d4   smc     #0
       4: 00 20 3c d5   mrs     x0, TTBR0_EL2
       8: e0 03 1f 2a   mov     w0, wzr
       c: c0 03 5f d6   ret

$ llvm-objdump-14 -d test.o

test.o: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <main>:
       0: 03 00 00 d4   <unknown>
       4: 00 20 3c d5   mrs     x0, S3_4_C2_C0_0
       8: e0 03 1f 2a   mov     w0, wzr
       c: c0 03 5f d6   ret
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 20, 2022

@llvm/issue-subscribers-backend-aarch64

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 20, 2022

@llvm/issue-subscribers-tools-llvm-objdump

@DavidSpickett
Copy link
Collaborator

I believe this started with https://reviews.llvm.org/D110065. I think because these are not present on R profile and llvm-objdump doesn't know to default to A profile?

Adding the v8a feature or selecting a cpu works around it, which supports that idea:

$ ./bin/llvm-objdump -d /tmp/test.o --mcpu=cortex-a53
<...>
       0: 03 00 00 d4   smc     #0
       4: 00 20 3c d5   mrs     x0, TTBR0_EL2
$ ./bin/llvm-objdump -d /tmp/test.o --mattr=+v8a
<...>
       0: 03 00 00 d4   smc     #0
       4: 00 20 3c d5   mrs     x0, TTBR0_EL2
<...>

@labrinea Does that sound right to you?

@PG-MANA
Copy link
Author

PG-MANA commented Feb 23, 2022

Actually, I'm writing a bare-metal program for AArch64 with Rust, it becomes not been able to compile recently.
I inspected when the nightly rust compiler is not able to compile and why.
I found the problem appears since nightly-2022-02-18 containing the commit that switches backend from LLVM13 to LLVM14.

// test.rs
#![no_std]
#[no_mangle]
fn test() {
    use core::arch::asm;
    unsafe {
        asm!("smc 0", clobber_abi("C"));
        asm!("mrs x0, TTBR0_EL2");
    }
}

this code can compile with nightly-2022-02-17, but it cannot with nightly-2022-02-18 and emits errors like below.

$ rustup run nightly-2022-02-18 rustc --target aarch64-unknown-none --crate-type=lib test.rs
error: instruction requires: el3
 --> test.rs:7:15
  |
7 |         asm!("smc 0", clobber_abi("C"));
  |               ^
  |
note: instantiated into assembly here
 --> <inline asm>:1:2
  |
1 |     smc 0
  |     ^

error: expected readable system register
 --> test.rs:8:15
  |
8 |         asm!("mrs x0, TTBR0_EL2");
  |               ^
  |
note: instantiated into assembly here
 --> <inline asm>:1:10
  |
1 |     mrs x0, TTBR0_EL2
  |             ^

error: aborting due to 2 previous errors

The version information of nightly-2022-02-17 and nightly-2022-02-18 show that the LLVM version switched to 14.

$ rustup run nightly-2022-02-17 rustc --version --verbose
rustc 1.60.0-nightly (75d9a0ae2 2022-02-16)
binary: rustc
commit-hash: 75d9a0ae210dcd078b3985e3550b59064e6603bc
commit-date: 2022-02-16
host: x86_64-unknown-linux-gnu
release: 1.60.0-nightly
LLVM version: 13.0.0

$ rustup run nightly-2022-02-18 rustc --version --verbose 
rustc 1.60.0-nightly (30b3f35c4 2022-02-17) 
binary: rustc 
commit-hash: 30b3f35c420694a4f24e5a4df00f06073f4f3a37 
commit-date: 2022-02-17 
host: x86_64-unknown-linux-gnu
release: 1.60.0-nightly 
LLVM version: 14.0.0

Therefore, I suspect the rust's compile error is caused by LLVM 14 and continued to inspect, I finally found this objdump's issue.

Thanks to #53956 (comment), I came up with an idea to add "features: +v8.1a" to target triple configure file and the above source code can compile now.

I think because these are not present on R profile and llvm-objdump doesn't know to default to A profile?

I think it affects not only llvm-objdump but also the build system of rust.

I'm not clear on whether this behavior is a bug or a specification. If it is a spec, I must change my configure files.

Anyway, #53956 (comment) helps me very much.
I really appreciate @DavidSpickett, thank you.

@PG-MANA
Copy link
Author

PG-MANA commented Mar 12, 2022

I believe this started with https://reviews.llvm.org/D110065.

I read the discussion and code review.

To maintain backward compatibility we enable the features that correspond to -march=armv8-a when the architecture is not explicitly specified on the command line.

Based on the above sentence, I think the behavior of "llvm-objdump" should be repaired.
But in the reviewed code, I found that some system registers are deleted from the test.
I think the test should not remove them if maintains backward compatibility, but it was deleted, therefore I consider if I use system registers, I should specify the A-Profile.

I think it may be ok to fix only by reverting line 523 in clang/lib/Basic/Targets/AArch64.cpp,

// ArchKind = llvm::AArch64::ArchKind::INVALID;
ArchKind = llvm::AArch64::ArchKind::ARMV8A;

I will try it, but if anyone has any idea, please add a comment.
Thank you.

@oToToT
Copy link
Member

oToToT commented Apr 23, 2022

A proposed patch for this. Maybe you could have a check.

@PG-MANA
Copy link
Author

PG-MANA commented Apr 24, 2022

I submit a patch for this. Maybe you could have a check.

I compiled llvm 14.0.1 with this patch, and confirmed that llvm-objdump emits SMC and TTBR_EL2 correctly.
I did not test with rust compiler, but I think it will work well.
I will close this branch when the patch is accepted.
It is the really nice patch, thank you very much!

@oToToT
Copy link
Member

oToToT commented Apr 28, 2022

The above patch is now landed in 4a31af8. To fix the problem in the Rust side, I will send a PR to ask them cherry-pick this patch.

@oToToT
Copy link
Member

oToToT commented Jun 27, 2022

Closing as the fix is now merged in rust-lang/rust#98285.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

No branches or pull requests

5 participants