Llvm Get Constant Integer Back from Value*

LLVM get constant integer back from Value*

Given llvm::Value* foo and you know that foo is actually a ConstantInt, I believe that the idiomatic LLVM code approach is to use dyn_cast as follows:

if (llvm::ConstantInt* CI = dyn_cast<llvm::ConstantInt>(foo)) {
// foo indeed is a ConstantInt, we can use CI here
}
else {
// foo was not actually a ConstantInt
}

If you're absolutely sure that foo is a ConstantInt and are ready to be hit with an assertion failure if it isn't, you can use cast instead of dyn_cast.


P.S. Do note that cast and dyn_cast are part of LLVM's own implementation of RTTI. dyn_cast acts somewhat similarly to the standard C++ dynamic_cast, though there are differences in implementation and performance (as can be read here).

How to get the exact integer from a Value

The way you outline is more or less correct - there's also a more complete answer in this related question. But that is of course assuming the value is a ConstantInt.

If you expect some value to be a constant but it isn't, you should make sure you're running one of the constant propagation passes first. If the value is still not a constant there's nothing much you can do, except for maybe writing your own specialized constant propagation pass...

Obfuscating integer constants with an LLVM pass

The problem here is IRBuilder, which performs Constant Folding by default upon creating the new IR instructions.

To solve this issue, I had to create a new volatile (volatile is not obligatory, but I could so I did) variable in IR, perform the "obfuscated" arithmetic operations on it, and replace the operand of the instruction that uses "1337" with the resulting value.

The code is the same as in the question, except for the function obfuscateInt(...), which now looks as follows:

  // replValue = ~(originalInt ^ key) -1
Value *obfuscateInt(BasicBlock &BB, Instruction &Inst, Constant *C) {

srand(time(NULL));
int key = std::rand();
int32_t replacedValue = ~(C->getUniqueInteger().getLimitedValue() ^ key);

Constant *replValue = ConstantInt::get(C->getType(), replacedValue),
*keyValue = ConstantInt::get(C->getType(), key);

IRBuilder<> Builder(&Inst);

// allocate enough space on the stack to store a 32-bit value. Var name = "AA"
AllocaInst *varAlloc = Builder.CreateAlloca(Builder.getInt32Ty(), nullptr, "AA");

// Store the key in AA, set "volatile" to true
Builder.CreateStore(keyValue, varAlloc, true);

// read the variable "AA"
LoadInst *loadVar = Builder.CreateLoad(varAlloc, true, "AA");

// use it
Value *repl = Builder.CreateXor(replValue, loadVar);
Value *finValue = Builder.CreateNeg(repl);

return Builder.CreateSub(finValue, Builder.getInt32(1));
}

The generated IR now looks like:

  %1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store volatile i32 3, i32* %2, align 4
%3 = load volatile i32, i32* %2, align 4
%4 = alloca i32
store volatile i32 525933950, i32* %4
%5 = load volatile i32, i32* %4
%6 = xor i32 -525932616, %5
%7 = sub i32 0, %6
%8 = sub i32 %7, 1
%9 = add nsw i32 %3, %8
store volatile i32 %9, i32* %2, align 4
%10 = load volatile i32, i32* %2, align 4
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str, i32 0, i32 0), i32 %10)
%12 = load volatile i32, i32* %2, align 4
ret i32 %12

And the disassembly shows that 1337 doesn't appear anywhere, yet the behaviour of the program is preserved:

0000000000001140 <main>:
1140: 55 push rbp
1141: 48 89 e5 mov rbp,rsp
1144: 48 83 ec 10 sub rsp,0x10
1148: 31 c0 xor eax,eax
114a: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0
1151: c7 45 f8 03 00 00 00 mov DWORD PTR [rbp-0x8],0x3
1158: 8b 4d f8 mov ecx,DWORD PTR [rbp-0x8]
115b: c7 45 f4 02 77 c4 31 mov DWORD PTR [rbp-0xc],0x31c47702
1162: 8b 55 f4 mov edx,DWORD PTR [rbp-0xc]
1165: 81 f2 c4 8d 3b ce xor edx,0xce3b8dc4
116b: 29 d0 sub eax,edx
116d: 83 e8 01 sub eax,0x1
1170: 01 c1 add ecx,eax
1172: 89 4d f8 mov DWORD PTR [rbp-0x8],ecx
....

How to create a ConstantInt in LLVM?

Most things in LLVM are created through a static method call instead of directly using a constructor. One reason is that an existing object can be returned instead of creating a new instance.

The static members of ConstantInt have a number of creation methods. You're probably most interested in get (Type *Ty, uint64_t V, bool isSigned=false) and, if you don't already have an integer type, IntegerType::get (LLVMContext &C, unsigned NumBits).



Related Topics



Leave a reply



Submit