Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(831)

Issue 91042: Implement LLVM JIT side of GDB JIT debugging interface (Closed)

Can't Edit
Can't Publish+Mail
Start Review
Created:
15 years, 4 months ago by Reid Kleckner
Modified:
15 years, 2 months ago
CC:
llvm-commits_cs.uiuc.edu, unladen-swallow_googlegroups.com
Base URL:
http://llvm.org/svn/llvm-project/llvm/trunk/
Visibility:
Public.

Description

This patch implements the JIT side of the GDB JIT debugging interface that I added to GDB. To enable this feature, either build the JIT in debug mode to enable it by default or pass -jit-emit-debug to lli. Right now, the only debug information that this communicates to GDB is call frame information, since it's already being generated to support exceptions in the JIT. Eventually, when DWARF generation isn't tied so tightly to AsmPrinter, it will be easy to push that information to GDB through this interface. Here's a step-by-step breakdown of how the feature works: - The JIT generates the machine code and DWARF call frame info (.eh_frame/.debug_frame) for a function into memory. - The JIT copies that info into an in-memory ELF file with a symbol for the function. - The JIT creates a code entry pointing to the ELF buffer and adds it to a linked list hanging off of a global descriptor at a special symbol that GDB knows about. - The JIT calls a function marked noinline that GDB knows about and has put an internal breakpoint in. - GDB catches the breakpoint and reads the global descriptor to look for new code. - When sees there is new code, it reads the ELF from the inferior's memory and adds it to itself as an object file. - The JIT continues, and the next time we stop the program, we are able to produce a proper backtrace. Consider running the following program through the JIT: #include <stdio.h> void baz(short z) { long w = z + 1; printf("%d, %x\n", w, *((int*)NULL)); // SEGFAULT here } void bar(short y) { int z = y + 1; baz(z); } void foo(char x) { short y = x + 1; bar(y); } int main(int argc, char** argv) { char x = 1; foo(x); } Here is a backtrace before this patch: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x2aaaabdfbd10 (LWP 25476)] 0x00002aaaabe7d1a8 in ?? () (gdb) bt #0 0x00002aaaabe7d1a8 in ?? () #1 0x0000000000000003 in ?? () #2 0x0000000000000004 in ?? () #3 0x00032aaaabe7cfd0 in ?? () #4 0x00002aaaabe7d12c in ?? () #5 0x00022aaa00000003 in ?? () #6 0x00002aaaabe7d0aa in ?? () #7 0x01000002abe7cff0 in ?? () #8 0x00002aaaabe7d02c in ?? () #9 0x0100000000000001 in ?? () #10 0x00000000014388e0 in ?? () #11 0x00007fff00000001 in ?? () #12 0x0000000000b870a2 in llvm::JIT::runFunction (this=0x1405b70, F=0x14024e0, ArgValues=@0x7fffffffe050) at /home/rnk/llvm-gdb/lib/ExecutionEngine/JIT/JIT.cpp:395 #13 0x0000000000baa4c5 in llvm::ExecutionEngine::runFunctionAsMain (this=0x1405b70, Fn=0x14024e0, argv=@0x13f06f8, envp=0x7fffffffe3b0) at /home/rnk/llvm-gdb/lib/ExecutionEngine/ExecutionEngine.cpp:377 #14 0x00000000007ebd52 in main (argc=2, argv=0x7fffffffe398, envp=0x7fffffffe3b0) at /home/rnk/llvm-gdb/tools/lli/lli.cpp:208 And a backtrace after this patch: Program received signal SIGSEGV, Segmentation fault. 0x00002aaaabe7d1a8 in baz () (gdb) bt #0 0x00002aaaabe7d1a8 in baz () #1 0x00002aaaabe7d12c in bar () #2 0x00002aaaabe7d0aa in foo () #3 0x00002aaaabe7d02c in main () #4 0x0000000000b870a2 in llvm::JIT::runFunction (this=0x1405b70, F=0x14024e0, ArgValues=...) at /home/rnk/llvm-gdb/lib/ExecutionEngine/JIT/JIT.cpp:395 #5 0x0000000000baa4c5 in llvm::ExecutionEngine::runFunctionAsMain (this=0x1405b70, Fn=0x14024e0, argv=..., envp=0x7fffffffe3c0) at /home/rnk/llvm-gdb/lib/ExecutionEngine/ExecutionEngine.cpp:377 #6 0x00000000007ebd52 in main (argc=2, argv=0x7fffffffe3a8, envp=0x7fffffffe3c0) at /home/rnk/llvm-gdb/tools/lli/lli.cpp:208

Patch Set 1 #

Total comments: 42

Patch Set 2 : Addressed reviewer's comments. #

Total comments: 16

Patch Set 3 : Addressed Jeff's comments. #

Total comments: 11

Patch Set 4 : Added hooks for GDB to automatically add the symbol file. #

Patch Set 5 : Move the object files off disk and into memory. #

Patch Set 6 : Synced with TOT. #

Unified diffs Side-by-side diffs Delta from patch set Stats (+389 lines, -19 lines) Patch
M docs/CompilerDriver.html View 1 chunk +1 line, -1 line 0 comments Download
M include/llvm/Target/TargetOptions.h View 1 2 3 4 5 1 chunk +4 lines, -0 lines 0 comments Download
M lib/CodeGen/ELFWriter.h View 1 2 3 4 5 2 chunks +2 lines, -0 lines 0 comments Download
M lib/ExecutionEngine/JIT/JIT.h View 1 2 3 4 5 1 chunk +2 lines, -1 line 0 comments Download
M lib/ExecutionEngine/JIT/JIT.cpp View 1 2 3 4 5 1 chunk +1 line, -1 line 0 comments Download
A lib/ExecutionEngine/JIT/JITDebugRegisterer.h View 1 2 3 4 1 chunk +116 lines, -0 lines 0 comments Download
A lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp View 1 2 3 4 5 1 chunk +204 lines, -0 lines 0 comments Download
M lib/ExecutionEngine/JIT/JITDwarfEmitter.h View 5 1 chunk +2 lines, -1 line 0 comments Download
M lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp View 5 2 chunks +2 lines, -2 lines 0 comments Download
M lib/ExecutionEngine/JIT/JITEmitter.cpp View 1 2 3 4 5 9 chunks +42 lines, -12 lines 0 comments Download
M lib/Target/TargetMachine.cpp View 1 2 3 4 5 3 chunks +13 lines, -1 line 0 comments Download

Messages

Total messages: 9
Reid Kleckner
Here is an example session for how to use this feature: # Put this program ...
15 years, 4 months ago (2009-07-02 20:17:53 UTC) #1
Jeffrey Yasskin
Nick, any thoughts? http://codereview.appspot.com/91042/diff/1/7 File lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp (right): http://codereview.appspot.com/91042/diff/1/7#newcode16 Line 16: #include "../../CodeGen/ELF.h" Nice. http://codereview.appspot.com/91042/diff/1/7#newcode34 Line ...
15 years, 4 months ago (2009-07-03 22:01:52 UTC) #2
nlewycky
Jeff's review was thoroughly exhaustive. I agree with his comments and had merely a few ...
15 years, 4 months ago (2009-07-04 01:27:07 UTC) #3
Reid Kleckner
Amidst the many "Done"s below, there are a couple of questions. I'm going to svn ...
15 years, 4 months ago (2009-07-06 21:07:01 UTC) #4
Jeffrey Yasskin
http://codereview.appspot.com/91042/diff/1/7 File lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp (right): http://codereview.appspot.com/91042/diff/1/7#newcode67 Line 67: // Copy the binary into the .text section. ...
15 years, 4 months ago (2009-07-08 00:40:43 UTC) #5
Reid Kleckner
So should we commit this to our local version of LLVM, or should I try ...
15 years, 4 months ago (2009-07-08 01:35:04 UTC) #6
Jeffrey Yasskin
More nitpicks below. I think it's time to stop sending me iterations and send it ...
15 years, 4 months ago (2009-07-08 17:52:08 UTC) #7
Reid Kleckner
I didn't touch ELFWriter.h, I just did svn up. I'll send this upstream now, but ...
15 years, 4 months ago (2009-07-08 18:07:04 UTC) #8
Reid Kleckner
15 years, 3 months ago (2009-08-21 23:53:08 UTC) #9
Hello LLVM devs,

I've been working on a debugging interface between GDB and LLVM, and I'd like to
get comments on the LLVM side of the interface now that the GDB side has been
committed.  I don't plan to check this in until after the code freeze.  Please
take a look on Rietveld.  I expect to iterate on this a couple more times.

Here's the description of the change from Rietveld:
---------------------

This patch implements the JIT side of the GDB JIT debugging interface that I
added to GDB.  To enable this feature, either build the JIT in debug mode to
enable it by default or pass -jit-emit-debug to lli.

Right now, the only debug information that this communicates to GDB is call
frame information, since it's already being generated to support exceptions in
the JIT.  Eventually, when DWARF generation isn't tied so tightly to AsmPrinter,
it will be easy to push that information to GDB through this interface.

Here's a step-by-step breakdown of how the feature works:
- The JIT generates the machine code and DWARF call frame info
(.eh_frame/.debug_frame) for a function into memory.
- The JIT copies that info into an in-memory ELF file with a symbol for the
function.
- The JIT creates a code entry pointing to the ELF buffer and adds it to a
linked list hanging off of a global descriptor at a special symbol that GDB
knows about.
- The JIT calls a function marked noinline that GDB knows about and has put an
internal breakpoint in.
- GDB catches the breakpoint and reads the global descriptor to look for new
code.
- When sees there is new code, it reads the ELF from the inferior's memory and
adds it to itself as an object file.
- The JIT continues, and the next time we stop the program, we are able to
produce a proper backtrace.

Consider running the following program through the JIT:

#include <stdio.h>
void baz(short z) {
  long w = z + 1;
  printf("%d, %x\n", w, *((int*)NULL));  // SEGFAULT here
}
void bar(short y) {
  int z = y + 1;
  baz(z);
}
void foo(char x) {
  short y = x + 1;
  bar(y);
}
int main(int argc, char** argv) {
  char x = 1;
  foo(x);
}

Here is a backtrace before this patch:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x2aaaabdfbd10 (LWP 25476)]
0x00002aaaabe7d1a8 in ?? ()
(gdb) bt
#0  0x00002aaaabe7d1a8 in ?? ()
#1  0x0000000000000003 in ?? ()
#2  0x0000000000000004 in ?? ()
#3  0x00032aaaabe7cfd0 in ?? ()
#4  0x00002aaaabe7d12c in ?? ()
#5  0x00022aaa00000003 in ?? ()
#6  0x00002aaaabe7d0aa in ?? ()
#7  0x01000002abe7cff0 in ?? ()
#8  0x00002aaaabe7d02c in ?? ()
#9  0x0100000000000001 in ?? ()
#10 0x00000000014388e0 in ?? ()
#11 0x00007fff00000001 in ?? ()
#12 0x0000000000b870a2 in llvm::JIT::runFunction (this=0x1405b70,
F=0x14024e0, ArgValues=@0x7fffffffe050)
   at /home/rnk/llvm-gdb/lib/ExecutionEngine/JIT/JIT.cpp:395
#13 0x0000000000baa4c5 in llvm::ExecutionEngine::runFunctionAsMain
(this=0x1405b70, Fn=0x14024e0, argv=@0x13f06f8, envp=0x7fffffffe3b0)
   at /home/rnk/llvm-gdb/lib/ExecutionEngine/ExecutionEngine.cpp:377
#14 0x00000000007ebd52 in main (argc=2, argv=0x7fffffffe398,
envp=0x7fffffffe3b0) at /home/rnk/llvm-gdb/tools/lli/lli.cpp:208

And a backtrace after this patch:
Program received signal SIGSEGV, Segmentation fault.
0x00002aaaabe7d1a8 in baz ()
(gdb) bt
#0  0x00002aaaabe7d1a8 in baz ()
#1  0x00002aaaabe7d12c in bar ()
#2  0x00002aaaabe7d0aa in foo ()
#3  0x00002aaaabe7d02c in main ()
#4  0x0000000000b870a2 in llvm::JIT::runFunction (this=0x1405b70,
F=0x14024e0, ArgValues=...)
   at /home/rnk/llvm-gdb/lib/ExecutionEngine/JIT/JIT.cpp:395
#5  0x0000000000baa4c5 in llvm::ExecutionEngine::runFunctionAsMain
(this=0x1405b70, Fn=0x14024e0, argv=..., envp=0x7fffffffe3c0)
   at /home/rnk/llvm-gdb/lib/ExecutionEngine/ExecutionEngine.cpp:377
#6  0x00000000007ebd52 in main (argc=2, argv=0x7fffffffe3a8,
envp=0x7fffffffe3c0) at /home/rnk/llvm-gdb/tools/lli/lli.cpp:208

----------------

Thanks!
Reid
Sign in to reply to this message.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b