Last active
December 28, 2015 00:59
-
-
Save wbrown/7417466 to your computer and use it in GitHub Desktop.
This LLVM IR shows the logic that is used to store function pointers in a global heap, which is then retrieved and cast as a function to be executed. It crashes right when it tries to execute the pointer.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; constants to help with multiplatform stuff | |
%pntr = type i64* | |
%cell = type i64 | |
; for ease of debugging, allows us to print a value to stdout | |
@valueString = internal constant [7 x i8] c"%llu\0D\0A\00" | |
declare i32 @printf(i8*, ... ) | |
define void @printValue32(i32 %value) { | |
%string = getelementptr [7 x i8]* @valueString, i32 0, i32 0 | |
%printf_ret = call i32 (i8*, ... )* @printf(i8* %string, i32 %value) | |
ret void | |
} | |
define void @printValue64(i64 %value) { | |
%string = getelementptr [7 x i8]* @valueString, i32 0, i32 0 | |
%printf_ret = call i32 (i8*, ... )* @printf(i8* %string, %cell %value) | |
ret void | |
} | |
define void @printValueCell(%cell %value) { | |
%string = getelementptr [7 x i8]* @valueString, i32 0, i32 0 | |
%printf_ret = call i32 (i8*, ... )* @printf(i8* %string, %cell %value) | |
ret void | |
} | |
; in the program, we use a global pointer | |
@heapPtr = weak global %pntr null | |
; given an index value, get a pointer to the heap value at that index | |
define %pntr @getHeap_ptr(%cell %index) { | |
; load our heap pointer, which is stored as a pointer | |
%heapPtr = load %pntr* @heapPtr | |
; retrieve and return our value pointer | |
%valuePtr = getelementptr %pntr %heapPtr, %cell %index | |
ret %pntr %valuePtr | |
} | |
; given an index and value, place the value at the heap | |
define void @putHeap(%cell %index, %cell %value) { | |
%valuePtr = call %pntr @getHeap_ptr(%cell %index) | |
store %cell %value, %pntr %valuePtr | |
ret void | |
} | |
; given an index and value, get the value from the index on the heap | |
define %cell @getHeap(%cell %index) { | |
%valuePtr = call %pntr @getHeap_ptr(%cell %index) | |
%value = load %pntr %valuePtr | |
ret %cell %value | |
} | |
; given a function and an index, insert the pointer cast | |
; as an int into the heap at the index | |
define void @insertFunction(%cell %index, void ()* %fn) { | |
%insPtr = call %pntr @getHeap_ptr(%cell %index) | |
%fnPtrInt32 = ptrtoint void ()* %fn to i32 | |
%fnPtrInt64 = ptrtoint void ()* %fn to i64 | |
%fnPtrIntCell = ptrtoint void ()* %fn to %cell | |
call void @putHeap(%cell %index, %cell %fnPtrIntCell) | |
; print our 32-bit pointer as integer | |
call void @printValue32(i32 %fnPtrInt32) | |
; print the 64-bit integer to see if it's a different | |
; value | |
call void @printValue64(i64 %fnPtrInt64) | |
ret void | |
} | |
; given an index, load the int stored at the heap, | |
; convert it to a pointer and execute it | |
define void @executeFunction(%cell %index) { | |
%functionPtrInt = call %cell @getHeap(%cell %index) | |
; print our retrieved pointer before we go on | |
call void @printValueCell(%cell %functionPtrInt) | |
; cast our int as a function pointer and then call it, | |
; this is where it crashes | |
%functionPtr = inttoptr %cell %functionPtrInt to void ()* | |
call void %functionPtr() | |
ret void | |
} | |
define void @testFn() { | |
call void @printValueCell(%cell 11111111111) | |
ret void | |
} | |
define %cell @main() { | |
; allocate our heap | |
%heapPtr = alloca %cell, %cell 1024 | |
; store the pointer to our heap in a global value | |
store %pntr %heapPtr, %pntr* @heapPtr | |
; place our function onto the heap | |
call void @insertFunction(%cell 0, void ()* @testFn) | |
; call our function on the heapPtr | |
call void @executeFunction(%cell 0) | |
ret %cell 0 | |
} |
Third revision abstracts out the type to %cell and %pointer.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Second revision corrected this -- it was a 64bit vs 32bit issue with pointers.