I am trying to understand the getelementptr instruction in llvm IR, but not fully understanding it.
I have a struct like below -
struct Foo {
int32_t* p;
}
I want to do this -
foo.p++;
What would be the right code for this?
%0 = getelementptr %Foo* %fooPtr, i32 0, i32 0
%1 = getelementptr i32* %0, i8 1
store i32* %1, i32* %0
I am wondering if value in %0 needs to be first loaded using "load" before executing 2nd line.
Thanks!
You can see the GEP instruction as an operation that performs arithmetic operations on pointers. In LLVM IR the GEP instruction is your instruction of choice to perform operations on pointers easyly. You don't have to do cumbersome calculate the size of your types and offsets to manually perform such operations.
In your case:
%0 = getelementptr %Foo* %fooPtr, i32 0, i32 0
selects the member inside the structure. It uses the pointer operatand %fooPtr to calculate %0 = ((fooPtr + 0) + 0). GEP does not know about fooPtr just pointing to one element of Foo, this is why two indices are used to select the member.
%1 = getelementptr i32* %0, i8 1
As mentioned above the GEP performs pointer arithmetic and in your case get %1 = (p + 1);
Since you are operating on pointers using GEP you don't need to load the value of p. GEP will do this implicitly for you.
Now you can store the new index back to the position of the p member inside the Foo struct pointed to by fooPtr.
For further reading: The Often Misunderstood GEP Instruction
Related
For example,
If I want to store and save the variables %1, and % 3 in the instruction
%1 = alloca i32, align 4
%3 = load i32, i32* %2, align 4
into " *Value " variable for further use, how can I get them?
It looks like getOperand() can only get the operands, but not the variables being assigned.
It looks like getOperand() can only get the operands, but not the variables being assigned.
I am trying to implement a transformation of CallInst and perform the following:
Change the type of the arguments of function calls
Change the type of the return value
For example, I want to change the following IR:
%call = call double #add(double %0, double %1)
define double #add(double %x, double %y) #0 {
entry:
%x.addr = alloca double, align 8
%y.addr = alloca double, align 8
store double %x, double* %x.addr, align 8
store double %y, double* %y.addr, align 8
%0 = load double, double* %x.addr, align 8
%1 = load double, double* %x.addr, align 8
%add = fadd double %0, %1
ret double %add
}
To IR_New:
%call = call x86_fp80 #new_add(x86_fp80 %0, x86_fp80 %1)
define x86_fp80 #new_add(x86_fp80 %x, x86_fp80 %y) #0 {
entry:
%x.addr = alloca x86_fp80, align 16
%y.addr = alloca x86_fp80, align 16
store x86_fp80 %x, x86_fp80* %x.addr, align 16
store x86_fp80 %y, x86_fp80* %y.addr, align 16
%0 = load x86_fp80, x86_fp80* %x.addr, align 16
%1 = load x86_fp80, x86_fp80* %x.addr, align 16
%add = fadd x86_fp80 %0, %1
ret x86_fp80 %add
}
I have finished changing the type of AllocaInst, StoreInst, LoadInst, BinaryOperator and ReturnInst.
I am now very confused about how to deal with CallInst.
My original idea is when iterating all the instructions, if I find a CallInst,
if (CallInst *call = dyn_cast<CallInst>(it)){
do the following three steps:
Construct the new FunctionType
x86_fp80(x86_fp80, x86_fp80)
using
std::vector<Type*> ParamTys;
ParamTys.push_back(Type::getX86_FP80Ty(context));
ParamTys.push_back(Type::getX86_FP80Ty(context));
FunctionType *new_fun_type = FunctionType::get(Type::getX86_FP80Ty(context), ParamTys, true);
Construct function with new type in Step 1, i.e. construct new_add in the example
Function *fun = call->getCalledFunction();
Function *new_fun = Function::Create(new_fun_type,fun->getLinkage(), "", fun->getParent());
Construct a new CallInst with the new function obtained from step 2.
CallInst *new_call = CallInst::Create(new_fun, *arrayRefOperands, "newCall", call);
new_call->takeName(call);
}
However, in this way, I got the following IR instead of the IR_New I want:
%call = call x86_fp80 (x86_fp80, x86_fp80, ...) #0(x86_fp80 %5, x86_fp80 %7)
declare x86_fp80 #new_add(x86_fp80, x86_fp80, ...)
A new definition of called function is constructed(declare x86_fp80 #new_add(x86_fp80, x86_fp80, ...)), but the body of this new function is empty. I am very confused how to add the body and get the IR_New I want. My naive idea is:
for (Instruction i : called function(add in the example)){
create new_i with type x86_fp80;
insert new_i in the new function constructed(new_add in the example);
}
Is this a good way to achieve my goal?
Any advice will be greatly appreciated :)
you can use llvm::Value::mutateType(llvm::Ty) to change double type value to x86_fp80 if you are no longer using the original function somewhere else.
goto function definition using CallInst->getCalledFunction() and iterate over all value then mutate double types to x86_fp80.
ref: http://llvm.org/docs/doxygen/html/classllvm_1_1Value.html#ac0f09c2c9951158f9eecfaf7068d7b20
Is it possible to set a variable to 0 (or any other number) in LLVM-IR ? My searches have found me the following 3 line snippet, but is there anything simpler than the following solution ?
%ptr = alloca i32 ; yields i32*:ptr
store i32 3, i32* %ptr ; yields void
%val = load i32, i32* %ptr ; yields i32:val = i32 3
To set a value to zero (or null in general) you can use
Constant::getNullValue(Type)
and to set a value with an arbitrary constant number you can use ConstantInt::get(), but you need to identify the context first, like this:
LLVMContext &context = function->getContext();
/* or BB->getContext(), BB can be any basic block in the function */
Value* constVal = ConstantInt::get(Type::getInt32Ty(context), 3);
LLVM-IR is in static single assignment (SSA) form, so each variable is only assigned once. If you want to assign a value to a memory region you can simply use a store operation as you showed in your example:
store i32 3, i32* %ptr
The type of the second argument is i32* which means that it is a pointer to an integer that is 32 bit long.
I came up with this little code but all the professionals said its dangerous and I should not write code like this. Can anyone highlight its vulnerabilities in 'more' details?
int strlen(char *s){
return (*s) ? 1 + strlen(s + 1) : 0;
}
It has no vulnerabilities per se, this is perfectly correct code. It is prematurely pessimized, of course. It will run out of stack space for anything but the shortest strings, and its performance will suck due to recursive calls, but otherwise it's OK.
The tail call optimization most likely won't cope with such code. If you want to live dangerously and depend on tail-call optimizations, you should rephrase it to use the tail-call:
// note: size_t is an unsigned integertype
int strlen_impl(const char *s, size_t len) {
if (*s == 0) return len;
if (len + 1 < len) return len; // protect from overflows
return strlen_impl(s+1, len+1);
}
int strlen(const char *s) {
return strlen_impl(s, 0);
}
Dangerous it a bit of a stretch, but it is needlessly recursive and likely to be less efficient than the iterative alternative.
I suppose also that given a very long string there is a danger of a stack overflow.
There are two serious security bugs in this code:
Use of int instead of size_t for the return type. As written, strings longer than INT_MAX will cause this function to invoke undefined behavior via integer overflow. In practice, this could lead to computing strlen(huge_string) as some small value like 1, malloc'ing the wrong amount of memory, and then performing strcpy into it, causing a buffer overflow.
Unbounded recursion which can overflow the stack, i.e. Stack Overflow. :-) A compiler may choose to optimize the recursion into a loop (in this case, it's possible with current compiler technology), but there is no guarantee that it will. In a best case, stack overflow will simply crash the program. In a worst case (e.g. running on a thread with no guard page) it could clobber unrelated memory, possibly yielding arbitrary code execution.
The problem with killing the stack that have been pointed out, ought to be fixed by a decent compiler, where the apparent recursive call is flattened into a loop. I verified this hypothesis and asked clang to translate your code:
//sl.c
unsigned sl(char const* s) {
return (*s) ? (1+sl(s+1)) : 0;
}
Compiling and disassembling:
clang -emit-llvm -O1 -c sl.c -o sl.o
# ^^ Yes, O1 is already sufficient.
llvm-dis-3.2 sl.o
And this is the relevant part of the llvm result (sl.o.ll)
define i32 #sl(i8* nocapture %s) nounwind uwtable readonly {
%1 = load i8* %s, align 1, !tbaa !0
%2 = icmp eq i8 %1, 0
br i1 %2, label %tailrecurse._crit_edge, label %tailrecurse
tailrecurse: ; preds = %tailrecurse, %0
%s.tr3 = phi i8* [ %3, %tailrecurse ], [ %s, %0 ]
%accumulator.tr2 = phi i32 [ %4, %tailrecurse ], [ 0, %0 ]
%3 = getelementptr inbounds i8* %s.tr3, i64 1
%4 = add i32 %accumulator.tr2, 1
%5 = load i8* %3, align 1, !tbaa !0
%6 = icmp eq i8 %5, 0
br i1 %6, label %tailrecurse._crit_edge, label %tailrecurse
tailrecurse._crit_edge: ; preds = %tailrecurse, %0
%accumulator.tr.lcssa = phi i32 [ 0, %0 ], [ %4, %tailrecurse ]
ret i32 %accumulator.tr.lcssa
}
I don't see a recursive call. Indeed clang called the looping label tailrecurse which gives us a pointer as to what clang is doing here.
So, finally (tl;dr) yes, this code is perfectly safe and a decent compiler with a decent flag will iron the recursion out.
I have just discovered LLVM and don't know much about it yet. I have been trying it out using llvm in browser. I can see that any C code I write is converted to LLVM byte code which is then converted to native code. The page shows a textual representation of the byte code. For example for the following C code:
int array[] = { 1, 2, 3};
int foo(int X) {
return array[X];
}
It shows the following byte code:
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-linux-gnu"
#array = global [3 x i32] [i32 1, i32 2, i32 3] ; <[3 x i32]*> [#uses=1]
define i32 #foo(i32 %X) nounwind readonly {
entry:
%0 = sext i32 %X to i64 ; <i64> [#uses=1]
%1 = getelementptr inbounds [3 x i32]* #array, i64 0, i64 %0 ; <i32*> [#uses=1]
%2 = load i32* %1, align 4 ; <i32> [#uses=1]
ret i32 %2
}
My question is: Can I write the byte code and give it to the llvm assembler to convert to native code skipping the first step of writing C code altogether? If yes, how do I do it? Does any one have any pointers for me?
One very important feature (and design goal) of the LLVM IR language is its 3-way representation:
The textual representation you can see here
The bytecode representation (or binary form)
The in-memory representation
All 3 are indeed completely interchangeable. Nothing that can be expressed in one cannot be expressed in the 2 others as well.
Therefore, as long as you conform to the syntax, you can indeed write the IR yourself. It is rather pointless though, unless used as an exercise to accustom yourself with the format, whether to be better at reading (and diagnosing) the IR or to produce your own compiler :)
Yes, surely you can. First, you can write LLVM IR by hand. All tools like llc (which will generate a native code for you) and opt (LLVM IR => LLVM IR optimizer) accept textual representation of LLVM IR as input.