I'm writing LLVM pass which writes value of global variable when opt is called with -var [global_variable_name]. But I'm not able to find out how to write strings defined as char *string = "help"; in .c source code.
I have tried:
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
writeConstant(Out, CE->getAggregateElement(CV));
return;
}
but this resulted in SEGFAULT.
This is part of function for writing global variable of int type:
void writeConstant(raw_ostream &Out, const Constant *CV)
{
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
if (CI->getType()->isIntegerTy(1)) {
Out << (CI->getZExtValue() ? "true" : "false");
return;
}
}
APInt AI = CI->getValue();
if( CI->getBitWidth() == 8) { // if sizeof constant == sizeof char
const uint64_t *letter = AI.getRawData();
if(char letter2 = (char) (*letter)) {
Out << letter2;
return;
}
}
Out << CI->getValue();
return;
}
Excpected result:
In testsource.c is line as follows:
char *testString = "Hello";
Calling in bash:
opt -load pass.so -var testString < testsource.bc > /dev/null
Output of command above:
Hello
Finally found out solution, it was needed to get operand of constant expression which could be represented as global variable and thus it has initializer of constant data array type so it was just needed to call my function over this type of Constant. See code below:
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
Value *firstop = CE->getOperand(0);
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(firstop)) {
Constant *v = GV->getInitializer();
writeConstant(Out, v);
}
return;
}
For more information look up in repo: https://github.com/Petku/GlobalVariablePass/blob/master/globvars/globvars.cpp