Reputation: 1223
I have a file print.c, which has two functions:
void printLoad(...) {
// print address and value of memory location from which value
printf("address=... value=...", ...);
}
void printStore(...) {
// print address and value of memory location from which value
}
I have an LLVM pass which iterates over the instructions and adds CallInst instruction either printLoad or printStore (depending on the instruction type) after the current one (load/store inst).
In order to call this printStore or printLoad I need to add appropriate arguments to CallInst::Create function, which are the address and the value of the memory location.
This is an example of what I want to achieve:
define void @mains() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 5, i32* %1, align 4
store i32 2, i32* %2, align 4
store i32 4, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = add nsw i32 %3, 5
store i32 %4, i32* %1, align 4
ret void
}
The output should be:
store instruction:
address=... // address of %1
value=0
...
...
...
load instruction:
address=... // address of %2
value=4
store instruction:
address=... // address of %1
value=9
Progress so far:
I am able to get the addresses of the operands using getPointerOperand() on LoadInst/StoreInst.
I can also get the value of StoreInst in the first 4 store instructions by casting the operand to ConstantInt, but I don't know how to extract the value in the last StoreInst. Is it even possible?
EDITED:
Using
void printLoad(int32_t p)
and
Constant *hookLoadFunc = M.getOrInsertFunction("printLoad", Type::getVoidTy(M.getContext()), Type::getInt32Ty(M.getContext()));
.
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
store i32 0, i32* %1, align 4
call void @printStore(i32 0)
store i32 0, i32* %2, align 4
call void @printStore(i32 0)
store i32 5, i32* %2, align 4
call void @printStore(i32 5)
store i32 2, i32* %3, align 4
call void @printStore(i32 2)
store i32 4, i32* %3, align 4
call void @printStore(i32 4)
%4 = load i32, i32* %3, align 4
%5 = add nsw i32 %4, 5
store i32 %5, i32* %2, align 4
call void @printStore(i32 %5)
ret i32 0
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
call void @printStore(i32 %0)
%3 = load i32, i32* %2, align 4
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str, i32 0, i32 0), i32 %3)
ret void
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
call void @printStore(i32 %0)
%3 = load i32, i32* %2, align 4
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.1, i32 0, i32 0), i32 %3)
ret void
This causes Segmentation fault: 11 when run.
SOLVED:
Figured out that I had infinity loop (due to recursion). printStore actually uses load/store instructions, thus creating another call to printStore and so on.
Upvotes: 3
Views: 5300
Reputation: 11181
Assuming that you have an llvm::Function
that represents printLoad()
and printStore()
:
llvm::Function * print_load = ....
llvm::Function * print_store = ...
You can emit a CallInst
for each LoadInst
and StoreInst
.
For LoadInst
:
LoadInst * some_load = ...
Value * address_of_load = some_load->getOperand(0);
Value * print_load_arguments[] = { address_of_load, some_load };
// Insert a CallInst just after the load.
CallInst::Create(print_load, print_load_arguments )->insertAfter( some_load );
Remember that in llvm the value loaded by the LoadInst
is the same thing as the LoadInst
itself.
For StoreInst
:
StoreInst * some_store = ...
Value * value_to_store = some_store->getOperand(0);
Value * address_of_store = some_store->getOperand(1);
Value * print_store_arguments[] = { address_of_store, value_to_store };
// Insert a CallInst just after the store.
CallInst::Create(print_store, print_store_arguments)->insertAfter(some_store);
This will work if all the types match. Otherwise, you have to insert BitCast
instructions just before calling printStore()
or printLoad()
.
Upvotes: 6