I’m attempting to instrument virtual function calls in my code. After each virtual call I’m calling my own registerMethod function, with an integer marking the location of the call and a pointer to the function that was called.
However, and this is where I get confused, the function pointer doesn’t match any of the functions in my module. I’d hoped to call ExecutionEngine::getGlobalValueAtAddress to get a Function* for the virtual function, but ExecutionEngine::getGlobalValueAtAddress returns null.
If I look up the virtual function that is getting called (with ExeuctionEngine::getPointerToFunction) it doesn’t match the arguments being passed to my instrumentation. What’s a little strange is that the pointers are somewhat close: getPointerToFunction returns 0x47829a0, but my instrumentation gets 0x477fc10.
What am I missing?
Lines starting with “!” are the instrumented lines.
define double @Return() {
entry:
%this = load %“struct.Q::BinaryOperation<bool,bool,bool,Q::AddOperator>”** @q_constant2 ; <%“struct.Q::BinaryOperation<bool,bool,bool,Q::AddOperator>”> [#uses=2]
%tmp9.i = getelementptr %“struct.Q::BinaryOperation<bool,bool,bool,Q::AddOperator>” %this, i32 0, i32 2, i32 0 ; <%“struct.Q::Function”> [#uses=1]
%tmp10.i = load %“struct.Q::Function” %tmp9.i, align 4 ; <%“struct.Q::Function”> [#uses=2]
%tmp17.i = getelementptr %“struct.Q::BinaryOperation<bool,bool,bool,Q::AddOperator>” %this, i32 0, i32 1, i32 0 ; <%“struct.Q::Function”> [#uses=1]
%tmp18.i = load %“struct.Q::Function” %tmp17.i, align 4 ; <%“struct.Q::Function”> [#uses=2]
%tmp33.i = getelementptr %“struct.Q::Function” %tmp18.i, i32 0, i32 0, i32 0, i32 0, i32 0 ; <i32 (…)> [#uses=1]
%tmp34.i = load i32 (…) %tmp33.i, align 4 ; <i32 (…)> [#uses=1]
%tmp35.i = getelementptr i32 (…) %tmp34.i, i32 9 ; <i32 (…)> [#uses=1]
%tmp36.i = load i32 (…) %tmp35.i, align 4 ; <i32 (…)> [#uses=1]
%tmp3637.i = bitcast i32 (…) %tmp36.i to double (%“struct.Q::Function”) ; <double (%“struct.Q::Function”)> [#uses=2]
%tmp39.i = call double %tmp3637.i( %“struct.Q::Function”* %tmp18.i ) ; [#uses=1]
! bitcast double (%“struct.Q::Function”) %tmp3637.i to i8* ; <i8*>:0 [#uses=1]
! call void @registerMethod( i64 73846672, i8* %0 )
%tmp49.i = getelementptr %“struct.Q::Function”* %tmp10.i, i32 0, i32 0, i32 0, i32 0, i32 0 ; <i32 (…)> [#uses=1]
%tmp50.i = load i32 (…) %tmp49.i, align 4 ; <i32 (…)> [#uses=1]
%tmp51.i = getelementptr i32 (…) %tmp50.i, i32 9 ; <i32 (…)> [#uses=1]
%tmp52.i = load i32 (…) %tmp51.i, align 4 ; <i32 (…)> [#uses=1]
%tmp5253.i = bitcast i32 (…) %tmp52.i to i32 (%“struct.Q::Function”) ; <i32 (%“struct.Q::Function”)> [#uses=2]
%tmp55.i = call i32 %tmp5253.i( %“struct.Q::Function”* %tmp10.i ) ; [#uses=1]
! bitcast i32 (%“struct.Q::Function”) %tmp5253.i to i8* ; <i8*>:1 [#uses=1]
! call void @registerMethod( i64 73865808, i8* %1 )
%tmp5859.i = sitofp i32 %tmp55.i to double ; [#uses=1]
%tmp61.i = add double %tmp39.i, %tmp5859.i ; [#uses=1]
ret double %tmp61.i
}
Robert