Skip to content

Instantly share code, notes, and snippets.

@offlinemark
Last active May 16, 2016 17:55
Show Gist options
  • Select an option

  • Save offlinemark/eac8c915096143a84bf2bda2008022a1 to your computer and use it in GitHub Desktop.

Select an option

Save offlinemark/eac8c915096143a84bf2bda2008022a1 to your computer and use it in GitHub Desktop.
llvm stuff
i'm trying to install llvm, documenting it here
ubuntu 14.04
http://llvm.org/docs/GettingStarted.html
http://clang.llvm.org/get_started.html
http://llvm.org/docs/GettingStarted.html#requirements
install svn, cmake
cd where-you-want-llvm-to-live
i guess i want llvm to live in ~/llvm/
mkdir llvm
cd llvm
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
cd llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
cd ~/llvm
installing ninja?
apt-get install ninja-build
apparently you need a cmake generator and most llvm devs use ninja
mkdir build
cd build
cmake -G Ninja ../llvm
that failed?
ran it again and it worked.....
kinda weird that the build directory is a level back?
it says to run make but i thought i was using ninja
ran ninja and it crashed
trying from scratch. delete build dir
realized my cmake from apt is way old
wget cmake script from cmake.org/download
run it
add that directory to my path
needed to install libc6-i386 bc those are 32 bit..
cool, cmake version 3.5.1
cmake -G Ninja ../llvm
error No CMAKE_CXX_COMPILER could be found.
going to set environemnt to have CXX var to g++
needed to install g++
now the cmake things to be running
that was successful!
then i run ninja
and it seems to be going successfully!
waiting while it compiles 2557 objective
at 606 at 12:08am
this 16gb, 8 core machine is ripping :)
ld command failed at the end???
llect2: error: ld terminated with signal 9 [Killed]
oom?
ran ninja again
it finished!! (it was using close to 16GB memory linking everything wow)
nice now i have a full bin directory full of llvm stuff
~/llvm/build/bin
https://encrypted.google.com/search?hl=en&q=llvm%20tutorial
now that it's built, what do i do
kaleidoscope?
just reading this now http://llvm.org/docs/GettingStarted.html#getting-started-with-llvm
the llvm JIT seems cool, lli
ok so i've worked through http://llvm.org/docs/GettingStarted.html successfully
back to the user guides section of http://llvm.org/docs/index.html
going to try to get https://github.com/trailofbits/DomTreSat going
reading the build.sh script
what is compiler-rt? i didn't install it
i'm reading this and it seems they have a quick set of commands to install llvm using git
..i kind of want to try that
well building an out of source pass sounds like a fun thing to do, i should just folllow
whitequark's tutorial
this also looks really good http://adriansampson.net/blog/llvm.html
--
4/1
the things i could do to learn llvm
kaleidoscope tut
trail of bits domtreesat
adam sampson guide
quarkslab llvm dev meeting
how to out of tree pass
get my compilers project able to built on my own machine
it's for llvm 3.4
my lingering question, why is it necessary to build llvm yourself to dev with it? could you simply
download a binary package?
so it seems the compilers server had llvm installed from apt
dpkg -l llvm
apt-cache search llvm shows stuff
seems like it's installed into /usr/lib/llvm-3.4/
bin/ has the binaries/tools
build/ has some makefiles
include/ has some symlinks into /usr/include/llvm-3.4
lib/ has lots of libraries. .a's and .so's
seems like llvm 3.6 is the most recent one in apt on 14.04
i'm going to try to get my compilers project working
in theory apt-get install llvm-3.4 should work?
i tried running the makefile in the project. it was pointed to the
3.9 version i currently have built, and it has an error that there
was no include/llvm/Support/CFG.h
indeed, that file existed in 3.4 but does not in 3.9!
if i just do apt-get install llvm,
The following extra packages will be installed:
binfmt-support libffi-dev libllvm3.4 libtinfo-dev llvm-3.4 llvm-3.4-dev
llvm-3.4-runtime llvm-runtime
Suggested packages:
llvm-3.4-doc
automatically goes to 3.4
and if i specifically say 3.4
The following extra packages will be installed:
binfmt-support libffi-dev libllvm3.4 libtinfo-dev llvm-3.4-dev
llvm-3.4-runtime
Suggested packages:
llvm-3.4-doc
the same. ok, let's try.
that seemed to work well.
nice how all the files it put in /usr/bin end in -3.4 so they don't conflict with
the binaries from the one I built myself that I manually put in my path
lemme see if I can find that CFG.h it will need
should be in /usr/include/llvm-3.4/llvm/Support/CFG.h
and it's there!
changing the makefiles to use llvm-config-3.4 explicitly
one reason i can see for building llvm yourself is for more recent versions. how
do i search all of what apt has to offer..
error flex not found..need flex haha
and bison
error in compiling the parser.y
parser.y:185:43: error: no matching function for call to ‘llvm::IRBuilder<>::CreateStore(llvm::Function::arg_iterator&, llvm::Value*&)’
builder->CreateStore(it, symbol->lladdress);
it worked!!!!
looks like rafa just did apt-get install llvm-3.4 flex bison
cool
it maybe worked. it compiled.
the parser works
just needed to change the opt to opt-3.4 in the minicc file. nice!!!
it would be really convenient if there was an llvm-3.8 apt package heh
http://llvm.org/apt/
Packages are available for amd64 and i386 and for both the stable, qualification and development branches (currently 3.7, 3.8 and 3.9).
oh i guess stable is 3.7
Trusty (14.04) - Last update : Thu, 31 Mar 2016 17:37:56 UTC / Revision: 264818
deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty main
deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty main
# 3.7
deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main
deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main
# 3.8
deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.8 main
deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.8 main
i'm going to go ahead and install 3.7
adding this to apt sources.list
deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty main
deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty main
# 3.7
deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main
deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main
tried apt-get update but i need their gpg key thing
and now i have all sorts of llvm binaries available
dpkg-query -L llvm-3.7 to see all of it
cool, now I wonder if I can get tob's domtreesat thing compiled using these instead
idk though, it seems their build scripts just use the llvm build system, requiring
to build from source. i guess that's another reason to build from source?
idk though, for our compilers project we just used llvm-config which made it very easy
well it looks like the core of domtreesat is really just one cpp file
which calls RegisterPass, just like mips pass
compiling mips pass is g++ -fPIC -shared *.cc -o mips.so -std=c++11 `llvm-config-3.4 --cppflags`
i wonder if i can do that for this
g++ -fPIC -shared LLVMDomTreePass.cpp -o dts.so -std=c++11 `llvm-config-3.7 --cppflags`
worked! nice
how does the repo actually use whatever gets built?
what gets built
reading quick_setup.sh
runs LLVMPassBuild/build.sh
build.sh pulls down llvm, clang, compiler-rt
puts everything in llvm, puts dts into llvm/projects
runs llvm/configure
then runs make -j5
fun tip, they removed the configure script in 3.9, you have
to use cmake
it makes the build dir right inside the llvm src dir. i guess it doesn't matter where
the build dir is???
runs make -j5 inside the build dir it made
there was a dts build dir inside LLVMPassbuild/
oh nvm
./projects/LLVMPassBuild/Release+Asserts/LLVMDomTreePass.o
lol there's that exit on line 91
then it tried to execute complete_test.sh which doesn't exist
test base case sh
DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/"
this is the output
oh neat, so if you put your pass code into the llvm/projects directory
the build products are in the build dir, under Release+Asserts
in this case the lib/ dir has LLVMPassBuild.so which I'm pretty sure is the .so
theres some stuff in the dir with the cpp file
Makefile
LEVEL= ../..
LIBRARYNAME= LLVMPassBuild
SHARED_LIBRARY= 1
LOADABLE_MODULE= 1
LINK_LIBS_IN_SHARED= 1
ENABLE_OPTIMIZED= 1
include $(LEVEL)/Makefile.common
LDFLAGS +=
CXXFLAGS += -fexceptions -fPIC
CXXFLAGS += -std=c++11 -g -O3
i guess you need a CMakeLists.txt, LLVMBuild.txt, and Makefile
when you put a project into the projects/ dir
the partial build sh script copies the cpp file and those llvm build files into the
big llvm source dir then runs make in the llvm build dir. that'll just build what's
changed
huh seems like 3.9 got rid of the Release+Asserts dir in the build dir, and just puts
the bin/ and lib/ in the top level
the test script runs the built clang and compiles a c file into bc
then runs opt and passes the .so as the arg :)
theoretically, i should be able to do the same with my simple gcc compiled version
and apt thing
running ./complete_test_base_case.sh works
/clang -cc1 -emit-llvm test_base_case.c -o test_base_case.bc
test_base_case.c:1:9: fatal error: 'stdio.h' file not found
#include<stdio.h>
wtf
what does clang -cc1 do
http://stackoverflow.com/questions/8991662/what-does-the-clang-cc1-option-do
basically it's clang mode vs gcc
http://stackoverflow.com/questions/27638069/pre-compiled-clang-cant-see-the-visual-studio-headres
i guess you need to specify -I for stdio.h?
also i think they might need -c for bitcode
huh but i get "-c" unknown arg when I use clang 3.7
the dom pass writes a file called z3conditions.txt
which is then read by some llvm z3 python script
the test scripts don't work because clang can't compile the c files because
it needs the include path
but the repo comes with a z3conditions.txt file
http://stackoverflow.com/questions/30730600/clang-xclang-cc1-o3-mips-c-emit-llvm-clang-error-emit-llvm-cannot-be-use
question for irc i guess, i can't figure out how to emit bitcode on clang 3.7 (-c doesn't work)
omit -cc1 and add -c
diff --git a/test_base_case.sh b/test_base_case.sh
index d36c95b..96810fb 100755
--- a/test_base_case.sh
+++ b/test_base_case.sh
@@ -2,7 +2,7 @@ DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/"
echo
echo "[ CLANG COMPILING TEST APP SOURCES ]"
echo
-$DIR/bin/clang -cc1 -emit-llvm test_base_case.c -o test_base_case.bc
+$DIR/bin/clang -emit-llvm -c test_base_case.c -o test_base_case.bc
echo
echo "[ RUNNING DOMINATOR TREE PASS ]"
echo
cool it works now
they have some patches...that could be why they need source
@@ -2,11 +2,12 @@ DIR=".//LLVMPassBuild/DTS_BUILD/llvm-3.7.1/build/Release+Asserts/"
echo
echo "[ CLANG COMPILING TEST APP SOURCES ]"
echo
-$DIR/bin/clang -emit-llvm -c test_base_case.c -o test_base_case.bc
+clang-3.7 -emit-llvm -c test_base_case.c -o test_base_case.bc
echo
echo "[ RUNNING DOMINATOR TREE PASS ]"
echo
-$DIR/bin/opt -load $DIR/lib/LLVMPassBuild.* -dotrepass test_base_case.bc -o test_base_case.bc
+#opt-3.7 -load $DIR/lib/LLVMPassBuild.* -dotrepass test_base_case.bc -o test_base_case.bc
+opt-3.7 -load LLVMPassBuild/LLVMPassBuild/dts.so -dotrepass test_base_case.bc -o test_base_case.bc
echo
echo "[ FINISHED ]"
echo
aw yeah my local compile thing works
going to ask quend why she did the build whole llvm thing
yeah on ubuntu, i'm not really seeing any good reason to have to build from source
if you're not actually hacking on llvm itself
you can get up to 3.9 via apt, and you can compile your passes etc using llvm-config
4/2
http://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior-in-c
going to write a pass that detect simple undefined behavior. accessing ints that haven't been initialized
6.7.8 10 of c90 says that the value is indeterinate
Accessing this then is UB if the value happens to be a trap representation for the type
it's ub via trap representations
wow section j.2 lists all the ub's, so cool
http://www.ibm.com/developerworks/library/os-createcompilerllvm1/index.html
pretty easy to iteration through the instructions
my main challenge is how i'm going to store the return values from alloca in a set
the load instruction takes a Value* operand, not sure how i get that out of the
alloca instr though
also i think i need a hasher function or something for unordered_set
http://llvm.org/releases/3.7.1/docs/ProgrammersManual.html#iterating-over-the-instruction-in-a-function
looking up how to get the variable name of the alloca return
line 3211 AsmWriter.cpp
printInstruction
2717
%1 = load i32, i32* %x, align 4
2727 } else if (!I.getType()->isVoidTy()) {
2728 // Print out the def slot taken.
2729 int SlotNum = Machine.getLocalSlot(&I);
2730 if (SlotNum == -1)
2731 Out << "<badref> = ";
2732 else
2733 Out << '%' << SlotNum << " = ";
that's definitely it
wait no that's not it. i want the string, not a number. oh duh, it's just
instruction.hasName()
349
PrintLLVMName(raw ostream, value)
false positive with
void func6(void)
{
int x = 1;
int y;
char input;
fgets(&input, 1, stdin);
if (input == 'A') {
y = 3;
}
x += y;
}
[+] Checking func6
> Uninitialized read of `input` ; %3 = load i8, i8* %input, align 1
> Uninitialized read of `y` ; %8 = load i32, i32* %y, align 4
> Uninitialized read of `x` ; %9 = load i32, i32* %x, align 4
it's because the only time i remove an alloc from the set is a store.
being passed as an argument also potentially counts.
an alloc, then an immediate load is definitely undefined behavior
an alloc, then a point to it being passed to a func, then a load is potentially ub
to be on the safe side and reduce false positives, we also remove from the set
if it is passed
todo conditionals
right now mine only works if the function is one bb
ignore loops, then its a tree traversal
with loops, it's a graph
when i left off, i was trying to insert llvm ir programmatically
http://llvm.org/releases/3.7.1/docs/ProgrammersManual.html
and also making the ub detector support arrays, logic, and function calls
is this even correct
http://llvm.org/releases/3.7.1/docs/ProgrammersManual.html#making-simple-changes
Instantiating Instructions
Creation of Instructions is straight-forward: simply call the constructor for the kind of instruction to instantiate and provide the necessary parameters. For example, an AllocaInst only requires a (const-ptr-to) Type. Thus:
AllocaInst* ai = new AllocaInst(Type::Int32Ty);
will create an AllocaInst instance that represents the allocation of one integer in the current stack frame, at run time. Each Instruction subclass is likely to have varying default parameters which change the semantics of the instruction, so refer to the doxygen documentation for the subclass of Instruction that you’re interested in instantiating
i'm pretty sure you can't do Type::Int32Ty . . .
4/5
ya those docs are bogus
i emitted an instruction!
now just need to emit a library to system or something..
not quite sure how to emit a library call to raw llvm
void func(void)
{
int x;
int y = x;
system("rm yo");
}
; Function Attrs: nounwind uwtable
define void @func() #0 {
%x = alloca i32, align 4
%y = alloca i32, align 4
%1 = load i32, i32* %x, align 4
store i32 %1, i32* %y, align 4
%2 = call i32 @system(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0))
ret void
}
maybe try to write my own simple program in llvm that makes a lib call and compile with llc
looking at the implementation of the CallInst::CreateMalloc function because it seems like they
must call into libc there??
385 if (!MallocFunc)
386 // prototype malloc as "void *malloc(size_t)"
387 MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, nullptr);
379 assert(AllocSize->getType() == IntPtrTy && "malloc arg is wrong size");
380 // Create the call to Malloc.
381 BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
382 Module* M = BB->getParent()->getParent();
383 Type *BPTy = Type::getInt8PtrTy(BB->getContext());
384 Value *MallocFunc = MallocF;
385 if (!MallocFunc)
386 // prototype malloc as "void *malloc(size_t)"
387 MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, nullptr);
388 PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
389 CallInst *MCall = nullptr;
390 Instruction *Result = nullptr;
391 if (InsertBefore) {
392 MCall = CallInst::Create(MallocFunc, AllocSize, "malloccall", InsertBefore)
393 Result = MCall;
394 if (Result->getType() != AllocPtrType)
oh btw it seems you can do BB->getContext() rather than llvm::getGlobalContext()
when you're creating instructions
4/9
void BrainF::header(LLVMContext& C) {
module = new Module("BrainF", C);
//Function prototypes
//declare void @llvm.memset.p0i8.i32(i8 *, i8, i32, i32, i1)
Type *Tys[] = { Type::getInt8PtrTy(C), Type::getInt32Ty(C) };
Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset,
Tys);
//declare i32 @getchar()
getchar_func = cast<Function>(module->
getOrInsertFunction("getchar", IntegerType::getInt32Ty(C), NULL));
//declare i32 @putchar(i32)
putchar_func = cast<Function>(module->
getOrInsertFunction("putchar", IntegerType::getInt32Ty(C),
IntegerType::getInt32Ty(C), NULL));
//Function header
//define void @brainf()
brainf_func = cast<Function>(module->
getOrInsertFunction("brainf", Type::getVoidTy(C), NULL));
builder = new IRBuilder<>(BasicBlock::Create(C, label, brainf_func));
//%arr = malloc i8, i32 %d
ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal));
BasicBlock* BB = builder->GetInsertBlock();
Type* IntPtrTy = IntegerType::getInt32Ty(C);
Type* Int8Ty = IntegerType::getInt8Ty(C);
Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty);
allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy);
ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem,
NULL, "arr");
BB->getInstList().push_back(cast<Instruction>(ptr_arr));
//call void @llvm.memset.p0i8.i32(i8 *%arr, i8 0, i32 %d, i32 1, i1 0)
looking at the brainfuck example llvm project
maybe this is how you do libc emits
CallInst *putchar_call = builder->
CreateCall(putchar_func,
putchar_params);
putchar_call->setTailCall(false);
woot emmited a call to exit
now to emit a call to system("rm -rf ~")
how to declare a string like that
; ModuleID = 'test.bc'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@func.args = private unnamed_addr constant [6 x i8] c"rm yo\00", align 1
; Function Attrs: nounwind uwtable
define void @func() #0 {
%args = alloca [6 x i8], align 1
%1 = bitcast [6 x i8]* %args to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @func.args, i32 0, i32 0), i64 6, i32 1, i1 false)
%2 = getelementptr inbounds [6 x i8], [6 x i8]* %args, i32 0, i32 0
%3 = call i32 @system(i8* %2)
ret void
}
; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #1
declare i32 @system(i8*) #2
alloca space for it
bitcast array to i8
llvm.memcpy it into there
get pointer
pass as argument to call to system
how to allocate static string?
constant::constantarray
http://llvm.org/docs/doxygen/html/classllvm_1_1ConstantArray.html
4/11
for the bitcast
http://www.llvm.org/docs/doxygen/html/classllvm_1_1CastInst.html
for the constant string
http://llvm.org/docs/doxygen/html/classllvm_1_1ConstantDataArray.html#details
ok cool i declares a constantdataarray getString
now i need to connect it to a function?
actually i don't think it's part of the function. part of the module
getOrInsertGlobal mmmmmmm
4/16
i can create a global i32
now how do i do a array of i8s
maybe
llvm::ArrayType::get(IntegerType
yay i made this appear
@shit = external global [3 x i8]
http://llvm.org/releases/3.7.1/docs/LangRef.html#module-structure
oh hm maybe i should be using this
http://llvm.org/docs/doxygen/html/classllvm_1_1GlobalVariable.html
previously i was calling M->getorinsertglobal which allows you to define
a global variable of a name and type
but apparently there also exists
QUESTION
i don't quite understand private linkage of llvm global variable
probably just need to think about it more. why don't they appear in symbol table?
local symbol table contains locations of symbols like funcs and data
it's actually not necessary, it can be stripped
well i guess that kind of explains it
i need to figure out how to create an initializer Constant to init my global
llvm::Constant *st = llvm::ConstantDataArray::getString(C, ouch_cmd);
@yoyoyo = private constant [10 x i8] c"rm -rf yo\00"
@yoyoyo.1 = private constant [10 x i8] c"rm -rf yo\00"
cool!!
QUESTION: why did it make two tho
next up
@func.args = private unnamed_addr constant [6 x i8] c"rm yo\00", align 1
; Function Attrs: nounwind uwtable
define void @func() #0 {
%args = alloca [6 x i8], align 1
%1 = bitcast [6 x i8]* %args to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* getelementptr inbounds ([6 x i8], [6 x i8
]* @func.args, i32 0, i32 0), i64 6, i32 1, i1 false)
%2 = getelementptr inbounds [6 x i8], [6 x i8]* %args, i32 0, i32 0
%3 = call i32 @system(i8* %2)
ret void
}
this is what i'm recreating
x global arg string
x alloca
bitcast
copy it into alloca
get pointer to it
call func with that pter
there's a lot of aligns here, i don't understand them, so i'll skip for now
this llvm.memcpy thing looks pretty hard
can i just
skipping it
going to emit gep
this is what i can do
@yoyoyo = private constant [10 x i8] c"rm -rf yo\00"
; Function Attrs: nounwind uwtable
define void @func() #0 {
%x = alloca i32, align 4
%y = alloca i32, align 4
; start emitting instrs
%args = alloca [10 x i8]
%argsptr = bitcast [10 x i8]* %args to i8*
%swag = getelementptr inbounds [10 x i8], [10 x i8]* %args, i32 0, i32 0
%1 = call i32 @system(i8* %swag)
; end emitting
%2 = load i32, i32* %x, align 4
%3 = add nsw i32 %2, 1
store i32 %3, i32* %y, align 4
ret void
}
; Function Attrs: nounwind uwtable
define i32 @main(i32 %argc, i8** %argv) #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i8**, align 8
store i32 0, i32* %1
store i32 %argc, i32* %2, align 4
store i8** %argv, i8*** %3, align 8
call void @func()
ret i32 0
}
declare i32 @system(i8*)
now just gotta do the memcpy...
actually i'm dumb. i did char args[] = "rf -rf" instead of char *args = "rm -rf"
because i thought it would be easier
declaring as array means you have to alloc array and do a memcpy from a global variable
(perhaps explains why static arrays work like this on os x rather than on linux
where they're in mov instructions)
those inline getelemtnptr are constant expression
4/18
want to improve my ub detection
right now i detect very simple cases where you declare an uninitialized variable
and try to use it later
it's only for simple types like ints, chars, no arrays
arrays
char buf[32];
char x = buf[0];
; Function Attrs: nounwind uwtable
define void @func() #0 {
entry:
%buf = alloca [32 x i8], align 16
%x = alloca i8, align 1
%arrayidx = getelementptr inbounds [32 x i8], [32 x i8]* %buf, i32 0, i64 0
%0 = load i8, i8* %arrayidx, align 1
store i8 %0, i8* %x, align 1
ret void
}
if there is a gep on a fresh alloca, we also need to track
what happens to that returned ptr
just add it to the set?
if it a pointer to it gets passed into a function, remove it
or put in into an "unsure" set
for insts
5/16
want to add some path sensitivity
right now, i just iter through all the instrs in a function which is bad
simple testcase
we have control flow. if it goes one way, we have ub, if it goes another way, we do not
the general question
for every alloca in the function, is there any way it gets loaded before getting stored
currently we stores allocas in a set, then linearly check every instruction in the function
to see if it is a load (it's ub!), a store (it's fine), a call (we're not sure)
void fun(void)
{
int x = 0;
int y;
if (x == 1)
y = 3;
x += y;
}
define void @fun() #0 {
entry:
%x = alloca i32, align 4
%y = alloca i32, align 4
store i32 0, i32* %x, align 4
%0 = load i32, i32* %x, align 4
%cmp = icmp eq i32 %0, 1
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
store i32 3, i32* %y, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
%1 = load i32, i32* %y, align 4
%2 = load i32, i32* %x, align 4
%add = add nsw i32 %2, %1
store i32 %add, i32* %x, align 4
ret void
}
the potential ub here is currently not detected
this is because of the store in the if
in order to be path senstivie we need to do a graph traversal
for each of the local variables we do a traversal
it's probably possible to do one traversal that does detection for all variables
but i think there's complexity there related to keeping track of which variables
are raw or not, so for now i will do one graph traversal for each local variable
got the thinking drafted out in some pseudo code
porting to cpp now
how to get successors to a bb
bb->getterminatorinstruction->successors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment