Debugging LLVM IR - llvm

I've built an LLVM-targetting frontend which produces some IR. Subsequently and entirely expectedly, the IR output is incorrect in some cases (as in, it appears correct, but the resulting program crashes when executed). However, I haven't found many useful tools to deal with this.
I have tried using lli, but the error message output is spectacularly unhelpful (when you would assume that an interpreter could give very precise error details).
I looked into converting the IR to C code, and then debugging that with Visual Studio, but it seems this functionality was removed from LLVM.
I also looked into dealing with GDB. However, the DWARF debug information format is quite specific to a few existing languages it seems, and in addition, the source that I am translating with my frontend is correct, it's the produced IR which is wrong, so debug symbols for the original source wouldn't be too helpful- for example, I'd need to see the values of a bunch of intermediate register values that don't correspond to any source variable, or breakpoint in compiler-generated functions.
What tools and techniques exist to debug LLVM IR output?

I'm not sure I understand your problem fully. Are you saying that your compiler (from language X to LLVM IR) is producing incorrect output (incorrect LLVM IR) and you're not sure how to debug it? In other words, there are two possibilities:
The IR produced by your compiler is incorrect - you can point at some instruction(s) and say - this is not what I meant to generate.
The IR seems correct but doesn't produce the results I expected it to produce.
I assume it's (1) you're talking about (because this is what the question was saying, before you updated it)
This wouldn't be a LLVM-specific problem, then. Assume you're writing a compiler from language X to native code. The produced native code is incorrect - how do you debug the problem? Well, you debug your compiler, obviously. You try to find the last place where the compiler's understanding of the input was correct, or the first place where it became incorrect. How you do this depends hugely on the architecture of your compiler. However, something that helps a lot is having a printable representation of other intermediate layers in your compiler.
For example, Clang (which produces LLVM IR from C, C++ and Objective C) can dump its full AST. So looking at the AST for the incorrect code can cut the compiler in half, helping determine if the problem is in the front-end (C source -> AST) or code gen (AST -> LLVM IR). The LLVM backend (compiles LLVM IR to native code) also has a few intermediate layers (most notably SelectionDAG and MIs), which can be examined for the sake of debugging. These are just examples of other existing compilers, YMMV with yours.

Will Diez described how he implemented that:
https://groups.google.com/d/msg/llvm-dev/O4Dj9FW1gtM/ovnm6dqoJJsJ
Hi all,
For my own purposes, I wrote a pass that does exactly what you all are
describing: add debug metadata to LLVM IR.
As a pass, it had to tackle the problem of "This file needs to exist
on disk somewhere so gdb can find it", which I solved my dumping it
onto /tmp/ somewhere. Not a great solution (who deletes these?) but
worked well enough.
Another interesting issue is how to coexist with any existing debug
metadata, which can be useful for simultaneously debugging an IR
transform inline with the C source for instrumentation-style passes
like SAFECode, ASan/TSan.
Quick Example:
(gdb) break main
Breakpoint 1 at 0x4010b1: file
/home/wdietz2/magic/test/unit/test_loop.c, line 9.
(gdb) r
Starting program:
/home/wdietz2/llvm/32-obj-make/projects/magic/test/Output/test_loop
Breakpoint 1, main (argc=<value optimized out>, argv=<value optimized
out>) at /home/wdietz2/magic/test/unit/test_loop.c:9
9 unsigned k = 0;
Missing separate debuginfos, use: debuginfo-install
glibc-2.12-1.80.el6_3.5.x86_64 libgcc-4.4.6-4.el6.x86_64
libstdc++-4.4.6-4.el6.x86_64
(gdb) n
10 source(argc != 0, &k);
(gdb) n
14 %and.i.i.i.i104 = and i64 %4, 70368744177660
(gdb) n
15 %5 = load i8** #global, align 8
(gdb) n
18 store i32 16843009, i32* %6, align 1
(gdb) n
19 store i8 1, i8* getelementptr inbounds ([1 x i8]* #array,
i64 0, i64 0), align 1
(gdb) n
20 call coldcc void #runtime_func() nounwind
(gdb) n
11 while(i-- > argc)
(gdb) n
23 %and.i.i.i.i85 = and i64 %7, 70368744177660
(gdb) n
14 while(j++ < i) k += j;
(gdb) n
11 while(i-- > argc)
(gdb) n
14 while(j++ < i) k += j;
(gdb) n
102 %77 = load i8** #global, align 8
(gdb) n
105 %79 = load i32* %78, align 4
(gdb) n
106 %cmp7.i.i.i = icmp ne i32 %79, 0
(gdb) n
108 call void #llvm.memset.p0i8.i64(i8* %add.ptr.i.i.i.i86, i8
%conv8.i.i.i, i64 4, i32 1, i1 false) nounwind
(gdb) n
14 while(j++ < i) k += j;
(gdb) n
15 while(j-- > 0) k *= k + j;
(gdb) n
95 %69 = load i8** #global, align 8
(gdb) n
98 %71 = load i32* %70, align 4
(gdb)
The pass itself is rather simple--the hard problem it solves is
emitting the IR to disk and reasoning about what Instruction* is on
what line, which really shouldn't be a problem if done properly in
LLVM. If desired I can certainly make the code available on request.
In short, it seemed to work well for me and having it done properly in
LLVM itself would be great!
Unfortunately, it seems that the code is not available.

Related

LLVM IR Loading type name mangling

I'm having a hard time fixing this problem with loading LLVM-IR modules.
First of all here is the problem.
I have this LLVM-IR File with this instruction:
%7 = getelementptr inbounds %struct.hoge, %struct.hoge* %6, i32 0, i32 0, !dbg !34
Now, when I load it using my tool, it turns to this:
%7 = getelementptr inbounds %struct.hoge.0, %struct.hoge.0* %6, i32 0, i32 0, !dbg !34
My goal is to get rid of this .0 at the end of all struct types.
Here is some code,
Module loading:
Module *FPR_::load(const path &input) const {
// Construct module
SMDiagnostic err;
unique_ptr<Module> module{parseIRFile(input.string(), err, ctx, true, "")};
...
Module printing:
ofstream ofs("hoge.ll");
string str;
raw_string_ostream rso(str);
module->print(rso, NULL, true, true);
ofs << str;
Now, let me tell you what I've done so far.
I've debugged my instrumentation tool and found out that this .0 gets added when the module is LOADED not PRINTED. I found this out because my tool outputs some instructions for debug purposed and they already have the .0s right after loading.
I've tried to load and print the same module multiple times and this is the result.
%7 = getelementptr inbounds %struct.hoge.0.0.0.0.0.0, %struct.hoge.0.0.0.0.0.0* %6, i32 0, i32 0, !dbg !34
Which would be funny if this isn't stopping me from developing my tool.
Verified that this does not happen with the opt tool.
[user#host]opt hoge.ll -o foo.ll
[user#host]diff hoge.ll foo.ll
[user#host]
Which means there must be something I'm missing that opt does.
Read opt's source code.
Some of the code felt like they mattered. And here is what I've ended up with.
LLVMContext ctx;
ctx.setDiscardValueNames(false);
ctx.enableDebugTypeODRUniquing();
FPR_::FPR_ FPR_(path(src_ll.getValue()), path(dep_ll.getValue()), ctx, options); // Module gets loaded in this constructor.
The options in the Context is all I found that opt seemed to do different. But no results so far.
Frankly, I'm out of ideas on how to fix this. So any help would be greatly appreciated.
And as a side note, I know that it is recommended to use the opt tool itself for static analysis or instrumentation.
But the problem is, the tool I am trying to make uses the static analysis for dynamic analysis as well. So I do not want my program to end when it outputs the instrumented LLVM-IR.
I could do some dirty hack and not return from the runOnModule method and just print the Module from there. But I do want to avoid that if possible.
Thank you in advance!
Short Answer:
Do not use the same LLVMContext to read modules if they are NOT supposed to be in the same program.
Long Answer:
By reading multiple Modules with the same LLVMContext, you imply that those Modules are supposed to be within the same program.
So what happens is that, when there are multiple Modules that have the same type name , they get indexed in order to avoid conflict.
Thank you for all the help in the comments. :)

Using global variables in JIT yields garbage result

I'm using the llvm-c API and want to use the JIT. I've created the following module
; ModuleID = '_tmp'
#a = global i64 5
define i64 #__tempfunc() {
entry:
%a_val = load i64* #a
ret i64 %a_val
}
This output is generated by LLVMDumpModule just before I call LLVMRunFunction. Which yields a LLVMGenericValueRef. However converting the result to a 64bit integer via LLVMGenericValueToInt(gv, true), it results in 360287970189639680 or something similar - not 5. Converting via LLVMGenericValueToInt(gv, false) didn't help either.
How can I use global variables in a JIT situation? Is anything wrong with the IR?
Edit: Well, i figured out that it has to do with the datalayout, since 360287970189639680 actually is 0x50...0. So I'd like to change the question to "How do I set the correct datalayout for a module? I've tried: LLVMSetDataLayout(mod, "x86_64-pc-linux") which aborts my program.
The data layout format is described in http://llvm.org/docs/LangRef.html#data-layout. And it's certainly not a target triple. Best, if you would simply feed dummy .c file to clang for your target, compile via -S -emit-llvm and grab the full data layout string from there.

gdb: print doesn't recognize variables with non-standard names or characters?

I'm writing a little BASIC compiler using LLVM, everything works fine. I'm trying to get debugging to work, and it's going fine, but I have a weird issue with variable names and GDB's print statement.
A little background on BASIC for those not familiar:
In BASIC, variable names use a symbol on the end to determine their type. So a variable x% would be integer, and variable x$ would be a string, and both can co-exist.
The statement DEFINT A-Z means that any variable starting with any letter from A to Z will be type INT, even without the trailing %. But, internally, my compiler will store the name mangled with the trailing % to avoid overlap with another variable with a trailing $.
Here is my little test program:
defint a-z
x = 5
y = 100
z = x + y
if x = 5 then
print "z=";z
else
print "z!=";z
end if
So 'x' is actually stored internally and put into the symbol table as x%.
OK, so I load my compiled EXE into GDB...
D:\dev\BasicParser>gdb t.exe
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\dev\BasicParser\t.exe...done.
(gdb) b _jbc_main
Breakpoint 1 at 0x401000: file t.bas, line 1.
(gdb) r
Starting program: D:\dev\BasicParser\t.exe
[New Thread 1532.0x25b8]
Breakpoint 1, _jbc_main () at t.bas:1
1 defint a-z
(gdb) n
4 x = 5
(gdb) info address x%
Symbol "x%" is static storage at address 0x4263c4.
At this point, you can see that GDB recognizes the symbol x% because it recognizes and display it's address. But the following "print" fails:
(gdb) print x%
No symbol "x" in current context.
Hmmm... that's interesting ... it dropped the % symbol.
But I can look at the memory location where x% is stored and this looks correct:
(gdb) x 0x4263c4
0x4263c4 <x%>: 0x00000000
If I show all symbols I get this as expected:
(gdb) info variables
All defined variables:
File t.bas:
static i32 x%;
static i32 y%;
static i32 z%;
Continuing on, to show that x% does get modified by the code:
(gdb) n
5 y = 100
(gdb) print x%
No symbol "x" in current context.
(gdb) x 0x4263c4
0x4263c4 <x%>: 0x00000005
(gdb)
And as you can see, the memory that GDB thinks x% is at is definitely updated.
For some reason, the "print" command doesn't like the % symbol.
Here is the "info source" results on this module, you can see I didn't specify C as the language:
(gdb) info source
Current source file is t.bas
Compilation directory is D:\dev\BasicParser
Located in D:\dev\BasicParser\t.bas
Contains 18 lines.
Source language is minimal.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
Any ideas for workarounds? I've been searching and searching and can't find a solution.
Thanks!
gdb simply interprets your command as modulo operation. It is not an error in gdb.
See, info source shows minimal for your file. This is from gdb's doc: http://sourceware.org/gdb/current/onlinedocs/gdb/Unsupported-Languages.html#Unsupported-Languages
In addition to the other fully-supported programming languages, GDB
also provides a pseudo-language, called minimal. It does not represent
a real programming language, but provides a set of capabilities close
to what the C or assembly languages provide.
So, what does this warning in your debugging session mean?
(gdb) print x%
No symbol "x" in current context.
Since minimal is a set of capabilities close C then gdb must iterpret this as trying to get remainder of division (http://en.wikipedia.org/wiki/Modulo_operation) - according to C programming language rules. So x is left arg, % is operation and the right arg is missing.
Let me show you example. This is a test C++ program that shows the minimal debugging session:
D:\src-c++\tests\test.vars>cat minimal.cpp
int main()
{
int k;
k = 1;
k = 2;
return 0;
}
And this is a debugging session:
D:\src-c++\tests\test.vars>gdb -q minimal.exe
Reading symbols from D:\src-c++\tests\test.vars\minimal.exe...done.
(gdb) start
Temporary breakpoint 1 at 0x4016be: file minimal.cpp, line 5.
Starting program: D:\src-c++\tests\test.vars/minimal.exe
[New Thread 2872.0x8c0]
Temporary breakpoint 1, main () at minimal.cpp:5
5 k = 1;
(gdb) show language
The current source language is "auto; currently c++".
(gdb) set language minimal
Warning: the current language does not match this frame.
(gdb) show language
The current source language is "minimal".
Warning: the current language does not match this frame.
(gdb) n
6 k = 2;
(gdb) print k
$1 = 1
(gdb) print k%
A syntax error in expression, near `'.
(gdb) print kk%
No symbol "kk" in current context.
Look -- No symbol "kk" in current context, the same error that you have.
Just a cross-reference, in case anybody else like me that might need help with this: I found this answer
In GDB, how to print the content of a symbol which has special characters?
where they indicate that you can quote names by starting with ampersand (&) and quote the name with single ticks ('), that is use something like
p &'my#complex.symbol%name'
x &'my#complex.symbol%name'
to inspect symbols with names beyond the usual C-style naming convention. I'm not completely clear what characters you can use at that point, but it seems like a good improvement.
As the other answer also points out, the GDB manual often refers to escaping symbol names just using single ticks (say something like p 'foo.c'). After some further reading I found in the GDB manual that this use of & seems to be an extension added for Windows support (see section titled "Features for Debugging MS Windows PE Executables", numbered 21.1.4 in the current edition), so I'm not sure if this may work outside of the Windows environment

llvm dependencies alloca-load

I have some problems of finding dependencies. I want to get the corresponding Alloca from every Load (corresponding from the point of view of the variable used, meaning that the Load is using a variable based/dependent on the Alloca or Allocas).
Hence, I have a chain like : Alloca -> Load(1) -> ... -> Computation where the variable might be changed -> Store(new_var) -> ... -> Load(n)
"Computation where the variable is changed" means that : I might have Alloca(a), c=a+7000*b[32], Load(c).
First, I tried to use methods from AliasAnalysis class.
The plan was the following: after I get all the must-aliases, I categorize them into 2 :
category A : aliases with allocas
category B: aliases without allocas
For category A, is straight ahead for what I need.
For category B, I check if there is an instruction where the variable is used also from an instruction from the aliases of category A. If it is, it is ok.
For some methods I cannot use Alloca, so I try to find dependencies among Loads (I have all the Load instructions in an array loadInstrArray) and then check if some Load use the same variable as an Alloca.
But the following gave me no result at all (and they should, I have dependencies in my target test code - meaning that Load j is used multiple times in my code, so the pointers should be must-alias) :
if( AA.isMustAlias(Loci,Locj) ) - no results
if( AA.alias(Loci,Locj) ) - wrong results, like "LOAD %2 = load i32* %j, align 4 IS DEPENDENT ON %3 = load i32* %c, align 4"
where j is totally independent from c
3". if( AA.getModRefInfo(allocaInstrArray[j],Loci) ) - no results
where Loci is AliasAnalysis::Location from a Load, allocaInstrArray is an array with all allocas
Second, I tried to use methods from DependencyAnalysis class.
if (DA.depends(loadInstrArray[i],loadInstrArray[j],false)) - no results
Third, I tried methods from MemoryDependenceAnalysis class - the existing pass http://llvm.org/docs/doxygen/html/MemDepPrinter_8cpp_source.html .
I have wrong results, like : %1 = load i32* %j, align 4 IS Clobber FROM: store i32 0, i32* %c, align 4
then I tried to get only DEF (not clobber), since I only need to see the correspondent Alloca for every Load. I don't have any results for Loads. I also checked with getDef() method, Loads being dependent on themselves.
I have to mention that I commented line 00131, since I had an unsolved segfault and not the parameters are the problem.
What do you think I should focus on, what approach is better to take into account and what to eliminate?
Thank you a lot for your time !
In addition, you should check if all the time the ICMP operands are referring to a Load instruction. If not, seek recursive for Load instructions from both ICMP operands (0 and 1). There might be other intermediate operations between Loads and ICMP.
Use getOperand(0)/getOperand(1) of the ICMP instructions. If there is isa<LoadInst> valid, then cast them to LoadInst. getPointerOperand() will get the Value* that is the actual variable which is searched.
Do the same procedure between Load instructions and Alloca instructions. getOperand(0) applied on Load gives the corresponding Alloca instruction.
Link the two results together, by checking the dependencies. The result of doing it manually passes the tests.

Need info on "set endian" on solaris machine

Can any 1 please tell or show the difference in the behaviour of any program before and after I "set endian little" in gdb on solaris machine?
I want to know the effect of changing it.
Thanks!
You should never have to set endianness when doing native (as opposed to remote) debugging.
You can however observe the ill effects of doing that:
(This is on Linux/x86 machine, but I expect you'll get similar results on Solaris/x86 and Solaris/SPARC).
int main()
{
int x = 0x1020304;
return x;
}
gdb -q a.out
Reading symbols from /tmp/a.out...done.
(gdb) b 4
Breakpoint 1 at 0x804835c: file t.c, line 4.
(gdb) r
Breakpoint 1, main () at t.c:4
4 return x;
(gdb) show endian
The target endianness is set automatically (currently little endian)
(gdb) p &x
$1 = (int *) 0xffffce60
(gdb) p/x *(int*)0xffffce60
$2 = 0x1020304
(gdb) set endian big
The target is assumed to be big endian
(gdb) p/x *(int*)0xffffce60
$3 = 0x4030201
To fully answer your question, this setting will have absolutely no effect whatsoever on the debugged program, only on gdb output as Employed Russian already stated.