Bug 13431 - jit code registration cleanup
Summary: jit code registration cleanup
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: unknown
: P2 normal
Target Milestone: 7.5
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-22 21:31 UTC by Steve Fink
Modified: 2016-03-31 18:38 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Test case for __jit_debug_descriptor (251 bytes, text/plain)
2011-12-16 19:56 UTC, Steve Fink
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steve Fink 2011-11-22 21:31:35 UTC
When using the JIT CFI registration API, I very commonly run into

  Unsupported JIT protocol version in descriptor!

Or, when I'm unlucky, extremely bizarre behavior: the inferior starts jumping to invalid locations. I generally notice it when it lands between two instructions and I get a SIGILL, though I have noticed at least one case where it just silently executed the wrong code.

I haven't seen the latter failure mode for a while.

I believe the problem is triggered when I am debugging a binary, and then I recompile it in a way that changes the location of __jit_debug_descriptor. It seems to reload the object file, then use the old location to unregister the old JIT code. Or something.

The exact series of events goes something like:

  1. (gdb) run
  2. ...stop at a breakpoint...
  3. recompile
  4. (gdb) run
Unsupported JIT protocol version in descriptor!
  5. (gdb) run
`/home/sfink/src/MI-jitprofiler/obj/dist/bin/js' has changed; re-reading symbols.
Unsupported JIT protocol version in descriptor!
  6. (gdb) run
Warning:
Cannot insert breakpoint -14865.
Error accessing memory address 0x378d805b60: Input/output error.
Cannot insert breakpoint -14866.
Error accessing memory address 0x378d805b70: Input/output error.
  7. (gdb) run
Now it runs, but all CFI information is completely mangled. Stack traces have bogus return addresses.
Comment 1 Steve Fink 2011-12-16 19:56:28 UTC
Created attachment 6115 [details]
Test case for __jit_debug_descriptor

Exact steps to reproduce:

1. Save the attached file to /tmp/jitrereg.c
2. gcc -o jitrereg /tmp/jitrereg.c
3. gdb ./jitrereg
4. gdb> run
5. Edit /tmp/jitrereg.c. Uncomment the line 'int spacer = 4'
6. From another shell (ie, without exiting gdb), redo step 2
7. From the same gdb as was running before, enter 'run' again

Observed:

(gdb) run
Unsupported JIT protocol version in descriptor!
Comment 2 Steve Fink 2011-12-16 20:01:06 UTC
Note that I've found this to be a serious usability issue. I control whether the JIT code registration does anything with an environment variable, but that doesn't help with this bug -- as long as __jit_debug_descriptor is defined in any linked object file, you'll occasionally get this problem. In my experience, it isn't even necessary to modify the file containing the __jit_debug_descriptor definition (or its headers) in order for it to be moved around. (Probably the linker is putting the object file at a different address or something.) And yet, you'll sometimes get lucky and recompile with major modifications without seeing this issue.
Comment 3 cvs-commit@gcc.gnu.org 2012-02-01 20:21:31 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	tromey@sourceware.org	2012-02-01 20:21:22

Modified files:
	gdb            : ChangeLog jit.c 
	gdb/testsuite  : ChangeLog 
Added files:
	gdb/testsuite/gdb.base: jit-simple.c jit-simple.exp 

Log message:
	PR gdb/13431:
	* jit.c (struct jit_inferior_data): Rewrite.
	(struct jit_objfile_data): New.
	(get_jit_objfile_data): New function.
	(add_objfile_entry): Update.
	(jit_read_descriptor): Return int.  Replace descriptor_addr
	argument with inf_data.  Update.  Don't call error.
	(jit_breakpoint_re_set_internal): Reorder logic.  Update.  Look up
	descriptor here.
	(jit_inferior_init): Don't look up descriptor.  Don't call error.
	(jit_reset_inferior_data_and_breakpoints)
	(jit_inferior_created_observer): Remove.
	(jit_inferior_exit_hook): Update.
	(jit_executable_changed_observer): Remove.
	(jit_event_handler): Update.
	(free_objfile_data): Reset inferior data if needed.
	(_initialize_jit): Update.
	gdb/testsuite
	* gdb.base/jit-simple.exp: New file.
	* gdb.base/jit-simple.c: New file.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.13799&r2=1.13800
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/jit.c.diff?cvsroot=src&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3053&r2=1.3054
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/jit-simple.c.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/jit-simple.exp.diff?cvsroot=src&r1=NONE&r2=1.1
Comment 4 Tom Tromey 2012-02-01 20:22:16 UTC
I think this is fixed.
I'd appreciate it if you gave it a try.
Comment 5 Steve Fink 2012-02-09 20:24:10 UTC
Yes, this seems to fix it for my actual code. Thanks!

(Sorry for the delay; I use git://sourceware.org/git/archer.git with a reverted patch that I need for it to work, and it took me a while to find the source tree where this patch was applied. I finally gave up and just used the CVS tree.)
Comment 6 Steve Fink 2012-02-16 00:54:13 UTC
I suspect this is a different issue, but it started happening recently, and one major recent change is the switch to the CVS version of gdb. At least as likely, though, is that I'm seeing this on optimized builds (of my app); I also started doing that recently (normally I always run nonoptimized, debug builds.)

Any chance you could take a quick look and tell me if I should file it separately?

(gdb) bt
#0  inlineFrames (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1146
#1  callSites (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1152
#2  commonSectionLimit (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1158
#3  getGlobalNames (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1165
#4  setGlobalNames (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1171
#5  callICs (this=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1178
#6  js::mjit::JITScript::nativeToPC (this=0x9251d0, returnAddress=0x7ffff7fe0401, pinline=0x7fffffffd4c0) at /home/sfink/src/MI-jitprofiler/js/src/methodjit/MethodJIT.cpp:1467
#7  0x0000000000540419 in GrabJSStack (reason=0x7fffffffd51c, rt=0x7ffff1e94010, sample=0x7ffff0d0f760) at /home/sfink/src/MI-jitprofiler/js/src/devtools/profiler/Backtrace.cpp:680
#8  js::profiler::CaptureStack (sample=0x7ffff0d0f760, rt=0x7ffff1e94010, flags=<optimized out>, numJunkFrames=<optimized out>, reason=0x7fffffffd51c) at /home/sfink/src/MI-jitprofiler/js/src/devtools/profiler/Backtrace.cpp:770
#9  0x0000000000572747 in ProfileSignalHandler (vucx=<optimized out>) at /home/sfink/src/MI-jitprofiler/js/src/devtools/profiler/Profiler.cpp:706
#10 <signal handler called>
BFD: BFD (GNU Binutils) 2.22.52.20120215 internal error, aborting at reloc.c line 6394 in bfd_generic_get_relocated_section_contents

BFD: Please report this bug.

Debugger exited abnormally with code 1
Comment 7 Tom Tromey 2012-02-16 18:16:16 UTC
Yeah, I think a new bug would be good.
Comment 8 cvs-commit@gcc.gnu.org 2016-03-31 18:33:42 UTC
The master branch has been updated by Pedro Alves <palves@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9bb84c9f97cb81df81f18f4e47d6b24fa37b597c

commit 9bb84c9f97cb81df81f18f4e47d6b24fa37b597c
Author: Yichao Yu <yyc1992@gmail.com>
Date:   Thu Mar 31 19:28:47 2016 +0100

    Fix PR gdb/19858: GDB doesn't register the JIT libraries on attach
    
    Ref: https://sourceware.org/ml/gdb/2016-03/msg00023.html
    
    GDB currently fails to fetch the list of already-registered JIT
    modules on attach.
    
    Nothing is calling jit_inferior_init, which is what is responsible for
    walking the JIT object list at init time.
    
    Despite the misleading naming, jit_inferior_created_hook ->
    jit_inferior_init is only called when the inferior execs.
    
    This regressed with the fix for PR gdb/13431 (03bef283c2d3):
     https://sourceware.org/ml/gdb-patches/2012-02/msg00023.html which
    removed the inferior_created (jit_inferior_created_observer)
    observer.
    
    Adding an inferior_created observer back fixes the issue.
    
    In turn, this exposes a bug in jit_breakpoint_re_set_internal as well,
    which is returning the wrong result when we already have the
    breakpoint at the right address.
    
    gdb/ChangeLog:
    2016-03-31  Yichao Yu  <yyc1992@gmail.com>
    
    	PR gdb/19858
    	* jit.c (jit_breakpoint_re_set_internal): Return 0 if we already
    	got the breakpoint at the right address.
    	(jit_inferior_created): New function.
    	(_initialize_jit): Install jit_inferior_created as
    	inferior_created observer.
    
    Signed-off-by: Pedro Alves <palves@redhat.com>
Comment 9 cvs-commit@gcc.gnu.org 2016-03-31 18:38:52 UTC
The gdb-7.11-branch branch has been updated by Pedro Alves <palves@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cd64cabb8c66a5565fc33bf66a07c08bc767e413

commit cd64cabb8c66a5565fc33bf66a07c08bc767e413
Author: Yichao Yu <yyc1992@gmail.com>
Date:   Thu Mar 31 19:28:47 2016 +0100

    Fix PR gdb/19858: GDB doesn't register the JIT libraries on attach
    
    Ref: https://sourceware.org/ml/gdb/2016-03/msg00023.html
    
    GDB currently fails to fetch the list of already-registered JIT
    modules on attach.
    
    Nothing is calling jit_inferior_init, which is what is responsible for
    walking the JIT object list at init time.
    
    Despite the misleading naming, jit_inferior_created_hook ->
    jit_inferior_init is only called when the inferior execs.
    
    This regressed with the fix for PR gdb/13431 (03bef283c2d3):
     https://sourceware.org/ml/gdb-patches/2012-02/msg00023.html which
    removed the inferior_created (jit_inferior_created_observer)
    observer.
    
    Adding an inferior_created observer back fixes the issue.
    
    In turn, this exposes a bug in jit_breakpoint_re_set_internal as well,
    which is returning the wrong result when we already have the
    breakpoint at the right address.
    
    gdb/ChangeLog:
    2016-03-31  Yichao Yu  <yyc1992@gmail.com>
    
    	PR gdb/19858
    	* jit.c (jit_breakpoint_re_set_internal): Return 0 if we already
    	got the breakpoint at the right address.
    	(jit_inferior_created): New function.
    	(_initialize_jit): Install jit_inferior_created as
    	inferior_created observer.
    
    Signed-off-by: Pedro Alves <palves@redhat.com>