Problems in instrumentation

Hi everyone,

I have some trouble in instrumenting load instructions. I want to instrument load instructions as follow: Firstly, I judge whether the loaded pointer(any type is possible) is NULL. If so, I want to explicitly allocate the corresponding address space of its type to the pointer.

For example, in source code level I want to translate the next statement

*p = 1;

into the next statements

if (p == NULL)
*p = malloc(sizeof(*p));
*p = 1;

For simplicity, I want to wrapper the first two statements into function init. And then I can implement as follow:

init((void*)p, sizeof(*p));
*p = 1;

where

void init(void *p, int size) {
if (p == NULL)
p = malloc(size);
}

I am trying to use the next pass for instrumentation:

for (Module::iterator f=M.begin(), fe=M.end(); f!=fe; ++f) {
for (Function::iterator b=f->begin(), be=f->end(); b!=be; ++b) {
for (BasicBlock::iterator i=b->begin(), ie=b->end()l i!=ie; ++i) {
if (i->getOpcode() == Instruction::Load) {

CallInst::create(…); // add a call inst before inst i to invoke function init

}
}
}
}

So my question is How should I create the previous call inst to execute invocation: init((void*)p, sizeof(p)). Because any pointer type is possible, so I let the first parameter of function init as ‘void*’. Furthermore, how should I get the size of *p? I check Type.h, and found class Type only provide function getPrimitiveSizeInBits() to return the size of the primitive types. How can I know the size of other types, eg. the size of a structure type.

Any Suggestions are welcome. Thank you all in advance.

Best Regards!

Just three notes: 1) You may want to ensure that you’re not invalidating the BasicBlock::iterator variable i by inserting the Call instruction. If you are invalidating the iterator, then your code may skip over load instructions or instrument a single load twice. 2) It may be better make your class derive from the InstVisitor class. 3) You may want to instrument atomic operations as well as the Load Instruction. This is because the atomic operations also perform a load (as well as a store). The same applies to some of the intrinsics (e.g., the memcpy/memcmp intrinsics). A “void *” in the LLVM IR is a pointer to an integer of size 1 (i.e., a char *). You can use the DataLayout analysis pass to find the size of various types. You can read the doxygen documentation on it at . Regards, John Criswell

Hi Qiuping,

IIRC, there’s a wrapper API for easy use of all type definitions; however I cannot remember exactly now.
For a void* type, is the size i8? I don’t think you can get the size of *p though since this formal parameter of a function in C is no more than an address.
Another tip: you can try some C++11 features(such as range-based for loops) in order to avoid “ugly code”, or customize some macros yourself.

Hi, John Criswell

Thank you for your detail notes, which give me much invaluable information.

Hi, Hongxu

Thank you for your advice. Now I resolve to the DataLayout (TargetData in lower llvm version) analysis pass to get the size of each type.

Best Regards!
Qiuping