llvm-tutor
llvm-tutor copied to clipboard
Is it possible to obtain and print the specified local variable value by llvm pass?
Hello, I just started to learn llvm pass. You must be very professional in llvm pass, so I want to ask a practical question, as the title says. For example, this is a very simple program.
#include <stdlib.h>
int main(){
int a=0;
for(int i=0;i<5;i++){
a++;
}
return 0;
}
Can I dynamically obtain the value of local variable a in llvm pass? My purpose is to observe its value change When it changes. So I have to obtain the value of the local variable a firstly.
If it's a global variable, it should be very simple to obtain its value, but I don't have any ideas about local variables.
I have checked the official documents and don't know whether this can be realized. If so, can you provide some ideas?
Hi @songxpu ,
Thank you for stopping by :) Unfortunately, I'm not aware of an easy ways of achieving this. You will probably have to use the debug info to track any source-level variables. That should be doable, but I've never tried it myself. Let me know how you get on - I'd be curious to see the end result myself!
Best, -Andrzej
Hi @banach-space ,thanks for your reply :)
After two days of study, my thoughts are similar to yours, that is, debug info may be needed to achieve this goal. In fact, when this question was raised 4 days ago, I wanted to know how to get the return value of an instruction. Now my problem is solved, that is, the return value of the instruction is the instruction itself.
So I can insert a custom function and pass the instruction of the target variable as a parameter to this function to get its value. Of course, this is only a small step, there are more things to be solved in the next step.
Hi @songxpu, what do you mean by 'obtain the value of local variable a in llvm pass'? The LLVM pass sees the code before it is executed. So I presume you mean you want to observe the value at runtime, therefore you want your pass to insert code which allows the value to be observed at runtime? For example, would you consider this case satisfied if you had a pass which inserted the equivalent of a 'printf()' whenever the variable a
is modified during execution, or do you mean something else?
how to use debug info to find local variables? Which API should I use?
Hey @Nicholas-wei , thanks for visiting 👋!
In general, I feel that this question is much more suitable for https://discourse.llvm.org/. This way it would get more visibility - that’s where most LLVM experts are :) Also, that’s where others will seek answers for similar questions.
Closing this as is - please post on Discourse instead :)
I came across this question while searching for answers for the same question, here are my quick experiments. My goal is also to be able to generate code to print the value of certain variables during run-time.
With the following code in an LLVM pass:
bool runOnFunction(Function &F) override {
for (Function::iterator itr = F.begin(); itr != F.end(); itr++) {
...
BasicBlock& bb = *itr;
...
for (BasicBlock::iterator itr2 = bb.begin(); itr2 != bb.end(); itr2++) {
Instruction& instr = *itr2;
...
if (isa<CallInst>(instr)) {
CallInst& ci = cast<CallInst>(instr);
for (User::op_iterator itr3 = ci.arg_begin(); itr3 != ci.arg_end(); itr3++) {
Value* value = itr3->get();
...
} else if (isa<MetadataAsValue>(*value)) {
Metadata* md = cast<MetadataAsValue>(*value).getMetadata();
unsigned char mdid = md->getMetadataID();
fprintf(stderr, " MetadataAsValue ID=%u(%s", mdid, GetMetadataKind(md));
if (isa<DILocalVariable>(*md)) {
DILocalVariable& dil = cast<DILocalVariable>(*md);
fprintf(stderr, " \"%s\"", dil.getName().data());
}
...
If you have the following program:
int main() { int a = 1; }
The program when compiled with -g
, will result in a call instruction to "llvm.dbg.declare".
define dso_local i32 @main() #4 !dbg !1563 {
%1 = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %1, metadata !1564, metadata !DIExpression()), !dbg !1565
store i32 1, i32* %1, align 4, !dbg !1565
...
Then, when the pass is run, it will print the name of the local variable, "a".
I think one can keep track of the CXX scope to learn which variables (global, class, extern, etc) are visible and do thing upon them.
Thank you! That perfectly solves my question
Thanks for sharing @quadpixels !
Clearly there’s more people interested in this - have you considered creating an llvm-tutor example out of this? Happy to review one ;-)