The kernel test robot reported an objtool warning with this configuration, which it pointed the finger at commit ab4e4380d4e1 ("Bluetooth: Add vhci devcoredump support") a while ago. Depending on the clang version, you will see one of two warnings:
drivers/bluetooth/hci_vhci.o: warning: objtool: .text: unexpected end of section
drivers/bluetooth/hci_vhci.o: warning: objtool: vhci_coredump_hdr() falls through to next function __cfi_vhci_open_timeout()
The body of vhci_coredump_hdr():
static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
{
char buf[80];
snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n");
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n");
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Driver: vhci_drv\n");
skb_put_data(skb, buf, strlen(buf));
snprintf(buf, sizeof(buf), "Vendor: vhci\n");
skb_put_data(skb, buf, strlen(buf));
}
I bisected the original introduction of this warning to llvm/llvm-project@1f88d80, which looks like a reasonable commit to blame.
My cvise attempt ended up not producing much, it was long and had overtly undefined behavior.
The diff of the IR from the parent of the problematic change shows that it completely eliminates the body of vhci_coredump_hdr(), transforming it simply into unreachable.
@@ -1103,107 +1096,8 @@ entry:
; Function Attrs: noredzone nounwind null_pointer_is_valid ssp
define internal void @vhci_coredump_hdr(ptr nocapture readnone %hdev, ptr noundef %skb) #2 align 16 {
-if.end15.i.i:
- %buf = alloca [80 x i8], align 16
- call void @llvm.lifetime.start.p0(i64 80, ptr nonnull %buf) #15
- call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(28) %buf, ptr noundef nonnull align 1 dereferenceable(28) @.str.11, i64 28, i1 false)
- %call18.i.i = call i64 @strnlen(ptr noundef nonnull %buf, i64 noundef 80) #14
- %.not.i = icmp ugt i64 %call18.i.i, 80
- br i1 %.not.i, label %do.end36.i.i, label %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i
-
-do.end36.i.i: ; preds = %if.end15.i.i
- %add.i.i = add i64 %call18.i.i, 1
- tail call void @__fortify_panic(i8 noundef zeroext 2, i64 noundef 80, i64 noundef %add.i.i) #18
- unreachable
-
-_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i: ; preds = %if.end15.i.i
- %cmp2.not.i.not = icmp eq i64 %call18.i.i, 80
- br i1 %cmp2.not.i.not, label %do.end15.i, label %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit
-
-do.end15.i: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i
- %add.i = add nuw nsw i64 %call18.i.i, 1
- tail call void @__fortify_panic(i8 noundef zeroext 4, i64 noundef 80, i64 noundef %add.i) #18
- unreachable
-
-_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i
- %conv = trunc i64 %call18.i.i to i32
- %call.i = tail call ptr @skb_put(ptr noundef %skb, i32 noundef %conv) #14
- %0 = tail call i64 asm "", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %call18.i.i) #17, !srcloc !17
- call void @llvm.memcpy.p0.p0.i64(ptr align 1 %call.i, ptr nonnull align 16 %buf, i64 %0, i1 false) #15
- call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(27) %buf, ptr noundef nonnull align 1 dereferenceable(27) @.str.12, i64 27, i1 false)
- %call18.i.i38 = call i64 @strnlen(ptr noundef nonnull %buf, i64 noundef 80) #14
- %.not.i39 = icmp ugt i64 %call18.i.i38, 80
- br i1 %.not.i39, label %do.end36.i.i42, label %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i45
-
-do.end36.i.i42: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit
- %add.i.i41 = add i64 %call18.i.i38, 1
- tail call void @__fortify_panic(i8 noundef zeroext 2, i64 noundef 80, i64 noundef %add.i.i41) #18
- unreachable
-
-_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i45: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit
- %cmp2.not.i44.not = icmp eq i64 %call18.i.i38, 80
- br i1 %cmp2.not.i44.not, label %do.end15.i47, label %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit48
-
-do.end15.i47: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i45
- %add.i46 = add nuw nsw i64 %call18.i.i38, 1
- tail call void @__fortify_panic(i8 noundef zeroext 4, i64 noundef 80, i64 noundef %add.i46) #18
- unreachable
-
-_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit48: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i45
- %conv10 = trunc i64 %call18.i.i38 to i32
- %call.i90 = tail call ptr @skb_put(ptr noundef %skb, i32 noundef %conv10) #14
- %1 = tail call i64 asm "", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %call18.i.i38) #17, !srcloc !17
- call void @llvm.memcpy.p0.p0.i64(ptr align 1 %call.i90, ptr nonnull align 16 %buf, i64 %1, i1 false) #15
- call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(18) %buf, ptr noundef nonnull align 1 dereferenceable(18) @.str.13, i64 18, i1 false)
- %call18.i.i58 = call i64 @strnlen(ptr noundef nonnull %buf, i64 noundef 80) #14
- %.not.i59 = icmp ugt i64 %call18.i.i58, 80
- br i1 %.not.i59, label %do.end36.i.i62, label %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i65
-
-do.end36.i.i62: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit48
- %add.i.i61 = add i64 %call18.i.i58, 1
- tail call void @__fortify_panic(i8 noundef zeroext 2, i64 noundef 80, i64 noundef %add.i.i61) #18
+do.end36.i.i:
unreachable
-
-_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i65: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit48
- %cmp2.not.i64.not = icmp eq i64 %call18.i.i58, 80
- br i1 %cmp2.not.i64.not, label %do.end15.i67, label %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit68
-
-do.end15.i67: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i65
- %add.i66 = add nuw nsw i64 %call18.i.i58, 1
- tail call void @__fortify_panic(i8 noundef zeroext 4, i64 noundef 80, i64 noundef %add.i66) #18
- unreachable
-
-_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit68: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i65
- %conv17 = trunc i64 %call18.i.i58 to i32
- %call.i111 = tail call ptr @skb_put(ptr noundef %skb, i32 noundef %conv17) #14
- %2 = tail call i64 asm "", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %call18.i.i58) #17, !srcloc !17
- call void @llvm.memcpy.p0.p0.i64(ptr align 1 %call.i111, ptr nonnull align 16 %buf, i64 %2, i1 false) #15
- call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(14) %buf, ptr noundef nonnull align 1 dereferenceable(14) @.str.14, i64 14, i1 false)
- %call18.i.i78 = call i64 @strnlen(ptr noundef nonnull %buf, i64 noundef 80) #14
- %.not.i79 = icmp ugt i64 %call18.i.i78, 80
- br i1 %.not.i79, label %do.end36.i.i82, label %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i85
-
-do.end36.i.i82: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit68
- %add.i.i81 = add i64 %call18.i.i78, 1
- tail call void @__fortify_panic(i8 noundef zeroext 2, i64 noundef 80, i64 noundef %add.i.i81) #18
- unreachable
-
-_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i85: ; preds = %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit68
- %cmp2.not.i84.not = icmp eq i64 %call18.i.i78, 80
- br i1 %cmp2.not.i84.not, label %do.end15.i87, label %_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit88
-
-do.end15.i87: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i85
- %add.i86 = add nuw nsw i64 %call18.i.i78, 1
- tail call void @__fortify_panic(i8 noundef zeroext 4, i64 noundef 80, i64 noundef %add.i86) #18
- unreachable
-
-_Z16__fortify_strlenPKcU25pass_dynamic_object_size1.exit88: ; preds = %_Z7strnlenPKcU25pass_dynamic_object_size1m.exit.i85
- %conv24 = trunc i64 %call18.i.i78 to i32
- %call.i132 = tail call ptr @skb_put(ptr noundef %skb, i32 noundef %conv24) #14
- %3 = tail call i64 asm "", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %call18.i.i78) #17, !srcloc !17
- call void @llvm.memcpy.p0.p0.i64(ptr align 1 %call.i132, ptr nonnull align 16 %buf, i64 %3, i1 false) #15
- call void @llvm.lifetime.end.p0(i64 80, ptr nonnull %buf) #15
- ret void
}
; Function Attrs: noredzone null_pointer_is_valid
@@ -1221,9 +1115,6 @@ declare dso_local i32 @hci_devcd_abort(ptr noundef) local_unnamed_addr #1
; Function Attrs: noredzone null_pointer_is_valid
declare dso_local i64 @_copy_from_user(ptr noundef, ptr noundef, i64 noundef) local_unnamed_addr #1
-; Function Attrs: argmemonly mustprogress nofree noredzone nounwind null_pointer_is_valid readonly willreturn
-declare dso_local i64 @strnlen(ptr nocapture noundef, i64 noundef) local_unnamed_addr #11
-
; Function Attrs: noredzone null_pointer_is_valid
declare dso_local i64 @__msecs_to_jiffies(i32 noundef) local_unnamed_addr #1
This appears related to the fact that __fortify_panic() is __noreturn (which introduces the unreachable instruction implicitly), as I can kill this warning by replacing strlen() with __builtin_strlen() in vhci_coredump_hdr() and it remains present by explicitly calling __fortify_panic(). It also appears related to this configuration having CONFIG_INIT_STACK_NONE, as the warning is not present with CONFIG_INIT_STACK_ALL_ZERO (the default); char buf[80] is technically uninitialized but there are other functions in drivers/bluetooth that have the exact same form but no issues. I will see if I can tease out a reproducer on top of defconfig to see if there are any other obvious factors here.
The kernel test robot reported an
objtoolwarning with this configuration, which it pointed the finger at commit ab4e4380d4e1 ("Bluetooth: Add vhci devcoredump support") a while ago. Depending on the clang version, you will see one of two warnings:The body of
vhci_coredump_hdr():I bisected the original introduction of this warning to llvm/llvm-project@1f88d80, which looks like a reasonable commit to blame.
My
cviseattempt ended up not producing much, it was long and had overtly undefined behavior.The diff of the IR from the parent of the problematic change shows that it completely eliminates the body of
vhci_coredump_hdr(), transforming it simply intounreachable.This appears related to the fact that
__fortify_panic()is__noreturn(which introduces theunreachableinstruction implicitly), as I can kill this warning by replacingstrlen()with__builtin_strlen()invhci_coredump_hdr()and it remains present by explicitly calling__fortify_panic(). It also appears related to this configuration havingCONFIG_INIT_STACK_NONE, as the warning is not present withCONFIG_INIT_STACK_ALL_ZERO(the default);char buf[80]is technically uninitialized but there are other functions indrivers/bluetooththat have the exact same form but no issues. I will see if I can tease out a reproducer on top ofdefconfigto see if there are any other obvious factors here.