-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Accessing pointers broken on LLVM <12 #1305
Comments
It's strange. When I try
then it seems to work.
but surely
does not. |
Apparently generated code is wrong.
The program store zero
all generated code
|
IR:
llvm10
llvm7
Looking at the IR lifetime seem to be ok. Not sure what else could trigger this, I'm looking into it. |
Using:
On llvm7:
llvm9
and the diff: --- llvm7 2020-09-14 18:33:17.000000000 +0200
+++ llvm9 2020-09-14 18:33:09.000000000 +0200
@@ -7,14 +7,14 @@
JAL 4, implicit-def $r0, implicit-def dead $r1, implicit-def dead $r2, implicit-def dead $r3, implicit-def dead $r4, implicit-def dead $r5, implicit $r11, implicit $r1, implicit $r2, implicit $r3
ADJCALLSTACKUP 0, 0, implicit-def dead $r11, implicit $r11
%19:gpr = COPY $r0
- %20:gpr = LDD %stack.2.struct cgroup.kn, 0 :: (dereferenceable load 8 from %ir."struct cgroup.kn")
+ %20:gpr = MOV_ri 0
+ STD %20:gpr, %stack.1.printf_args, 0 :: (store 8 into %ir.19)
+ %21:gpr = LDD %stack.2.struct cgroup.kn, 0 :: (dereferenceable load 8 from %ir."struct cgroup.kn")
LIFETIME_END %stack.2.struct cgroup.kn
LIFETIME_START %stack.1.printf_args
- %21:gpr = MOV_ri 0
- STD %21:gpr, %stack.1.printf_args, 0 :: (store 8 into %ir.19)
LIFETIME_START %stack.0.struct kernfs_node.parent
ADJCALLSTACKDOWN 0, 0, implicit-def dead $r11, implicit $r11
- %22:gpr = ADD_ri %20:gpr, 8
+ %22:gpr = ADD_ri %21:gpr(tied-def 0), 8
%23:gpr = MOV_rr %stack.0.struct kernfs_node.parent
$r1 = COPY %23:gpr
$r2 = COPY %4:gpr
@@ -23,5 +23,6 @@
ADJCALLSTACKUP 0, 0, implicit-def dead $r11, implicit $r11
%24:gpr = COPY $r0
%25:gpr = LDD %stack.0.struct kernfs_node.parent, 0 :: (dereferenceable load 8 from %ir."struct kernfs_node.parent")
+ STD killed %25:gpr, %stack.1.printf_args, 8 :: (store 8 into %ir.21)
LIFETIME_END %stack.0.struct kernfs_node.parent The IR after the last pass (IR Dump After Module Verifier) is identical between 7 and 9, so it looks like its in the |
Removing the lifetime end fixes it:
But that doesn't explain why it reorders the load/store this way. |
From https://llvm.org/docs/LangRef.html, llvm.lifetime.{start,end} encloses a region of lifetime of a memory object.
After Need to do a little bit study on why llvm did the above reordering. I guess this might be a llvm bug. One comment mentioned it is after BPF DAG->DAG Pattern Instruction Selection. Let me take a further check and then will comment back. |
I tried to build bpftrace from source. I then hit the following error
Any particular tip on how to resolve this? |
Is llvm built with rtti? |
with rtti on for llvm build, the bpftrace build issue is gone. Thanks! |
I filed a bug against llvm upstream: https://bugs.llvm.org/show_bug.cgi?id=47591 |
Thanks @yonghong-song As nobody has found IR issues this looks like an LLVM bug, how can we best move that forward? I'd like to dig into it but it might take a while. |
@fbs This is a BPF backend fix. https://reviews.llvm.org/D88525 I need to resolve bpf selftest failures before merging. Also, I am wondering whether there is an issue selection dag optimization process. Please feel free to try the patch and also suggest whether there is a better approach. Thanks! |
Ah nice 👍, I'l see if I can get that LLVM version built and tested. Any idea how we can implement a w/a for this? Ditching all lifetime ends seems to work, but that might blow the stack quickly. Or maybe we can avoid the last lifetime end and hope thats enough. I'll try to experiment a bit |
That is a problem. Selection dag seems assuming different stack alloc won't collide with each other in memory access. I guess bpftrace could generate different IR. For example, do an analysis to find maximum stack requirement considering the access chain and just do one alloc so you will only have one lifetime. |
The bug is fixed in llvm12. This LLVM patch https://reviews.llvm.org/D91833 fixed the problem and I added a test case (derived from this issue) in BPF https://reviews.llvm.org/D92451. |
Going to close this out b/c we released support for llvm 12. Going to pin this issue so users are aware of implications of using llvm <12. |
bpftrace --info
What reproduces the bug?
This works:
with output like this:
But this script does not work:
with output like:
There are no non-nils.
I think there might have been some change w/ handling pointers already on the stack. Maybe it's eliding a bpf_probe_read()? Could make sense cuz then kernel will fail the dereference and give you 0x0.
cc @mmisono
The text was updated successfully, but these errors were encountered: