SVF
SVF copied to clipboard
Incorrect bitcast processing
Hi. I was compiling Linux kernel with LLVM 14 to keep pointer types and found an issue with bitcasts.
For some reason compiler didn't use existing type for a global variable, but used an inplace type. This led to a bitcast instruction appearance. With it indirect call was not resolved.
Here is a minimal sample:
%struct.fs_ctx = type { %struct.fs_ops*, i32 }
%struct.fs_ops = type { void (i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)* }
@my_ops_obj = internal global { void (i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)* } { void (i8*)* @f1, i32 (i8*, i8*)* @f2, i32 (i8*, i8*)* null, i32 (i8*, i8*)* @f3 }, align 8
; Function Attrs: nounwind uwtable
define dso_local void @register_fs(%struct.fs_ctx* noundef %0) local_unnamed_addr #0 {
%2 = getelementptr inbounds %struct.fs_ctx, %struct.fs_ctx* %0, i64 0, i32 0
store volatile %struct.fs_ops* bitcast ({ void (i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)*, i32 (i8*, i8*)* }* @my_ops_obj to %struct.fs_ops*), %struct.fs_ops** %2, align 8
%3 = load volatile %struct.fs_ops*, %struct.fs_ops** %2, align 8
%4 = getelementptr inbounds %struct.fs_ops, %struct.fs_ops* %3, i64 0, i32 1
%5 = load i32 (i8*, i8*)*, i32 (i8*, i8*)** %4, align 8
%6 = tail call i32 %5(i8* noundef null, i8* noundef null) #3
ret void
}
declare dso_local void @f1(i8* noundef) #1
declare dso_local i32 @f2(i8* noundef, i8* noundef) #1
declare dso_local i32 @f3(i8* noundef, i8* noundef) #1
This also happens when llvm decides to create several equal types with different names. volatile was used for inline prevention, it doesn't matter.
I believe in this case call register_fs -> f2 should be resolved, but it is not.