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 ERROR: Cannot select: intrinsic %llvm.ptrauth.auth #57735

Open
ChoKyuWon opened this issue Sep 14, 2022 · 2 comments
Open

LLVM ERROR: Cannot select: intrinsic %llvm.ptrauth.auth #57735

ChoKyuWon opened this issue Sep 14, 2022 · 2 comments
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] llvm:codegen

Comments

@ChoKyuWon
Copy link
Contributor

ChoKyuWon commented Sep 14, 2022

I try to write new pass using llvm.ptrauth.auth and it seems work well in opt, but when I try to cross compile the result IR with LLC, it generates the crash.

Here is the compile command: llc-14 --march=aarch64 output/main.opt.bc and here is callstack:

Stack dump:
0.      Program arguments: llc-14 --march=aarch64 output/main.opt.bc
1.      Running pass 'Function Pass Manager' on module 'output/main.opt.bc'.
2.      Running pass 'AArch64 Instruction Selection' on function '@foobar'
 #0 0x00007f5131519311 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4b311)
 #1 0x00007f513151705e llvm::sys::RunSignalHandlers() (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4905e)
 #2 0x00007f513151984b (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xe4b84b)
 #3 0x00007f51306bf420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f51301b000b raise /build/glibc-SzIz7B/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007f513018f859 abort /build/glibc-SzIz7B/glibc-2.31/stdlib/abort.c:81:7
 #6 0x00007f51314542f8 (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xd862f8)
 #7 0x00007f5131d31f01 (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x1663f01)
 #8 0x00007f5131d313a8 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x16633a8)
 #9 0x00007f513301f731 (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x2951731)
#10 0x00007f5131d29fff llvm::SelectionDAGISel::DoInstructionSelection() (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x165bfff)
#11 0x00007f5131d296c4 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x165b6c4)
#12 0x00007f5131d28815 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x165a815)
#13 0x00007f5131d26669 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x1658669)
#14 0x00007f513189b42e llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0x11cd42e)
#15 0x00007f5131653350 llvm::FPPassManager::runOnFunction(llvm::Function&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xf85350)
#16 0x00007f513165a943 llvm::FPPassManager::runOnModule(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xf8c943)
#17 0x00007f5131653ef6 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-14.so.1+0xf85ef6)
#18 0x0000000000410078 main (/usr/lib/llvm-14/bin/llc+0x410078)
#19 0x00007f5130191083 __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:342:3
#20 0x000000000040afde _start (/usr/lib/llvm-14/bin/llc+0x40afde)
[1]    3539452 abort      llc-14 --march=aarch64 output/main.opt.bc

Here is buggy IR:

; ModuleID = 'output/main.bc'
source_filename = "tests/main.c"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64"

@.str = private unnamed_addr constant [3 x i8] c"%p\00", align 1

; Function Attrs: noinline nounwind optnone uwtable
define void @foobar(void (...)* noundef %f) #0 {
  %ptrtoint = ptrtoint void (...)* %f to i64
  %signed_ptr = call i64 @llvm.ptrauth.sign(i64 %ptrtoint, i32 0, i64 0)
  %inttoptr = inttoptr i64 %signed_ptr to void (...)*
  br label %entry

entry:                                            ; preds = %0
  %f.addr = alloca void (...)*, align 8
  %tmp = alloca void (...)*, align 8
  %ptrtoint1 = ptrtoint void (...)* %inttoptr to i64
  %signed_ptr2 = call i64 @llvm.ptrauth.sign(i64 %ptrtoint1, i32 0, i64 0)
  %inttoptr3 = inttoptr i64 %signed_ptr2 to void (...)*
  store void (...)* %inttoptr3, void (...)** %f.addr, align 8
  %1 = load void (...)*, void (...)** %f.addr, align 8
  %callee.knr.cast = bitcast void (...)* %1 to void ()*
  %ptrtoint4 = ptrtoint void ()* %callee.knr.cast to i64
  %signed_ptr5 = call i64 @llvm.ptrauth.auth(i64 %ptrtoint4, i32 0, i64 0)
  %inttoptr6 = inttoptr i64 %signed_ptr5 to void ()*
  call void %inttoptr6()
  %signed_ptr7 = call i64 @llvm.ptrauth.sign(i64 0, i32 0, i64 0)
  %inttoptr8 = inttoptr i64 %signed_ptr7 to void (...)*
  store void (...)* %inttoptr8, void (...)** %tmp, align 8
  %call = call i32 (i8*, ...) @__isoc99_scanf(i8* noundef getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), void (...)** noundef %tmp)
  %2 = load void (...)*, void (...)** %tmp, align 8
  %ptrtoint9 = ptrtoint void (...)* %2 to i64
  %signed_ptr10 = call i64 @llvm.ptrauth.sign(i64 %ptrtoint9, i32 0, i64 0)
  %inttoptr11 = inttoptr i64 %signed_ptr10 to void (...)*
  store void (...)* %inttoptr11, void (...)** %f.addr, align 8
  ret void
}

declare i32 @__isoc99_scanf(i8* noundef, ...) #1

; Function Attrs: nounwind readnone
declare i64 @llvm.ptrauth.sign(i64, i32 immarg, i64) #2

; Function Attrs: nounwind readnone
declare i64 @llvm.ptrauth.auth(i64, i32 immarg, i64) #2

attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+mte,+neon,+pauth,+v8.5a" }
attributes #1 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+mte,+neon,+pauth,+v8.5a" }
attributes #2 = { nounwind readnone }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7}
!llvm.ident = !{!8}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 0}
!2 = !{i32 1, !"sign-return-address", i32 0}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{i32 7, !"uwtable", i32 1}
!7 = !{i32 7, !"frame-pointer", i32 1}
!8 = !{!"clang version 14.0.0"}

Am I doing something wrong on using llvm.ptrauth API? Or is it real LLVM's problem?

@fhahn
Copy link
Contributor

fhahn commented Sep 14, 2022

I think pointer auth support is still in development. Maybe @ahmedbougacha knows more.

@EugeneZelenko EugeneZelenko added llvm:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Sep 14, 2022
@ahmedbougacha
Copy link
Member

Yes, ptrauth support is not fully functional in main (and even less so on llvm-14). However, the full support is already in the apple/llvm-project fork, and I'm maintaining a work-in-progress branch on top of (non-forked llvm-project) main.

If you haven't looked at that yet, I'd suggest you go over the changes there, as well as the llvm-dev RFC linked in the PR above, which goes into the overall design (for instance, instead of call void %inttoptr6(), which drastically weakens the security model, you should use the ptrauth operand bundle)

If you have a longer-term project using ptrauth, feel free to join our monthly LLVM Pointer Authentication syncs or reach out offline.

As for this concrete failure: it will be resolved when https://reviews.llvm.org/D132386 lands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash Prefer [crash-on-valid] or [crash-on-invalid] llvm:codegen
Projects
None yet
Development

No branches or pull requests

4 participants