-
Notifications
You must be signed in to change notification settings - Fork 440
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
An issue with global objects #1650
Comments
What do you mean by "When I change nested_ptr.ptr type to struct interesting, everything works fine.". Could I ask you to do the below so that we can debug and have a look? (1) simplify the example to leave only necessary variables and functions Thanks, |
struct interesting {
int dummy1;
void (*f1)();
void (*f2)();
int dummy2;
};
struct nested_ptr {
int dummy1;
struct interesting ptr;
int dummy2;
};
...
struct nested_ptr n1 = {
.ptr = {
.f1 = f1,
.f2 = f2
}
}; I reduced the code size and left important things only |
Thanks and what is the minimum change to the below code that does not work? Would be good to paste it here too.
|
I pasted the part of the code. To be more clear: I change the second field type in struct interesting {
int dummy1;
void (*f1)();
void (*f2)();
int dummy2;
};
struct nested_ptr {
int dummy1;
struct interesting ptr;
int dummy2;
};
extern struct interesting interesting_stub;
extern struct nested_ptr nested_ptr_stub;
void interesting_1_fstub() {
interesting_stub.f1();
}
void interesting_2_fstub() {
interesting_stub.f2();
}
void exchange_value() {
interesting_stub = nested_ptr_stub.ptr;
nested_ptr_stub.ptr = interesting_stub;
interesting_stub.f1 = interesting_1_fstub;
interesting_stub.f2 = interesting_2_fstub;
}
void f1();
void f2();
struct nested_ptr n1 = {
.ptr = {
.f1 = f1,
.f2 = f2
}
};
void test_ptr() {
nested_ptr_stub = n1;
} Not working one: struct interesting {
int dummy1;
void (*f1)();
void (*f2)();
int dummy2;
};
struct nested_ptr {
int dummy1;
struct interesting* ptr;
int dummy2;
};
extern struct interesting interesting_stub;
extern struct nested_ptr nested_ptr_stub;
void interesting_1_fstub() {
interesting_stub.f1();
}
void interesting_2_fstub() {
interesting_stub.f2();
}
void exchange_value() {
interesting_stub = *nested_ptr_stub.ptr;
nested_ptr_stub.ptr = &interesting_stub;
interesting_stub.f1 = interesting_1_fstub;
interesting_stub.f2 = interesting_2_fstub;
}
void f1();
void f2();
struct interesting i1 = {
.f1 = f1,
.f2 = f2
};
struct nested_ptr n1 = {
.ptr = &i1
};
void test_ptr() {
nested_ptr_stub = n1;
} |
I have further simplified your two programs.
For the first program, SVF works correctly as an LLVM memcpy will be introduced for
For the second program, LLVM IR translates
If you add another field declaration (e.g., A possible solution is to enhance SVF to handle the first field and the entire object in a smarter and automated manner, rather than requiring manual toggling of @jumormt @bjjwwang we may need to look into this first-field-eq-base issue later. The llvm bcs and callgraphs and pags are attached. |
struct interesting {
int dummy;
void (*f1)();
void (*f2)();
};
struct nested_ptr {
int dummy;
struct interesting* ptr;
};
void f1();
void f2();
struct interesting i1 = {
.f1 = f1,
.f2 = f2
};
struct nested_ptr n1 = {
.ptr = &i1
};
void test_ptr() {
struct interesting interesting_stub;
interesting_stub = *n1.ptr;
interesting_stub.f1();
interesting_stub.f2();
} IR is straightforward and uses GEPs: ; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @test_ptr() #1 {
%1 = alloca %struct.interesting, align 8
%2 = load %struct.interesting*, %struct.interesting** getelementptr inbounds (%struct.nested_ptr, %struct.nested_ptr* @n1, i32 0, i32 1), align 8
%3 = bitcast %struct.interesting* %1 to i8*
%4 = bitcast %struct.interesting* %2 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %3, i8* align 8 %4, i64 24, i1 false)
%5 = getelementptr inbounds %struct.interesting, %struct.interesting* %1, i32 0, i32 1
%6 = load void (...)*, void (...)** %5, align 8
call void (...) %6()
%7 = getelementptr inbounds %struct.interesting, %struct.interesting* %1, i32 0, i32 2
%8 = load void (...)*, void (...)** %7, align 8
call void (...) %8()
ret void
} However, neither |
It is good for the trying. It looks to me that the PAG is not fully built when handling SVF/svf-llvm/lib/SVFIRExtAPI.cpp Lines 95 to 96 in d39256e
|
@Frankenween could you try this pull request to see whether it fixes the problem (maybe try to tweak the programs to see any other issues)? |
@Frankenween Xiao made another update and could you try the pull request again? |
@yuleisui It's not crashing now and it resolves more calls, but it is still not working in all cases. Left one more test and LLVM IR in the PR. |
Hi, thanks for this great tool. I'm trying to do some LLVM IR instrumentation and I hit an issue, which looks like a bug. I have this sample code:
I compile with
clang-14 -O0
and runwpa -ander -dump-callgraph -ff-eq-base
(SVF is the latest one).I expect
interesting_stub.f1
to point tointeresting_1_fstub
andf1
, howeverinteresting_1_fstub -> f1
is not present in the call graph.If I understand it correctly,
n1.ptr
points toi1
. Later the pointer is copied, sonested_ptr_stub.ptr
should point toi1
orinteresting_stub
. And we end up withinteresting_stub = *nested_ptr_stub.ptr
, sointeresting_stub
should have the same values asi1
+_fstub
pointers.When I change
nested_ptr.ptr
type tostruct interesting
, everything works fine.If it is an expected behavior, could you please suggest any ways to make it work as I described?
example.zip
The text was updated successfully, but these errors were encountered: