135 bytes, text/plain
26.13 KB, text/plain
2.87 KB, patch
|Details | Diff | Splinter Review|
I have no idea what I'm talking about, do I? That assertion is talking about the PC in terms of the pointer into the bytecode stream, not JITted instructions. So this has more to do with a JM frame's register store getting the wrong PC in it. I don't understand how the PC syncing works for stub calls, though, but I wanted to suppress any wrong trails I left in that initial comment.
while it's possible this is a bug in jsd, it's more likely to be a bug in your own code or js.
This bug is present in an unmodified tracemonkey checkout, so it is not a bug in my code. As to whether it is a bug in jsd or js, I agree that it is more likely to be a bug in js. Or if it turns out to be a bug in jsd, then the js side is still missing an assertion. I've been chasing my tail around coming up with steps to reproduce, until I finally realized that my firebug modifications are irrelevant -- what matters is your profile. The problem seems to only occur when a breakpoint is loaded from <profile>/firebug/breakpoints.json. It must be getting set before debugMode is on or some other preparation has been done. Exact steps to reproduce: 1. Create a fresh profile (unnecessary, but never mind) 2. Install firebug-1.7 into it: mkdir ~/firebug cd ~/firebug svn checkout http://fbug.googlecode.com/svn/branches/firebug1.7 mkdir <profile>/extensions ln -s $HOME/firebug/branches/firebug1.7 firstname.lastname@example.org (I'll admit I haven't tested these exact instructions) 3. Fire up the browser 4. Navigate to the attached crash.html page (file:/// URI is fine) 5. Click the bug in the bottom right to enable firebug for the page 6. Reload to see the script panel 7. Set a breakpoint on the 'for' line by clicking to the left of it If you like, you can now reload again and see it break on that line. It won't matter; you're not going to see the crash on this run. 8. Exit out of the browser. (When the bug is active, this will trigger a crash.) 9. Start the browser again and go back to that page. This time, it will remember your breakpoint settings (which seems to be the trigger of the problem.) 10. When you are sitting on the breakpoint, Ctrl-Q to exit the browser. You will see the crash. The exact crash seems 100% reproducible from run to run, but perturbing anything will change what the exact crash is. It usually shows up as either an assertion failure (pc is out of script->code..script->code+length, or perhaps script->main..script->main+length, depending on which assertion you hit) or a segmentation fault. There will be JM frames on the stack. Often (always?), the first JM frame's return address will be invalid. The one I looked at closely would point into the middle of an instruction if I decompiled the surrounding region. I've even managed to capture a bunch of a run in gdb's reverse debugging record target, but I don't know enough about how gdb unwinds x86_64 stack frames to figure out whether the return address was patched within the scope of my recorded execution. (I want a memory location that I could set a watch on.) You can make the crash go away for one run by stopping the browser, deleting <profile>/firebug/*.json, and restarting. Hopefully, I can pinpoint this now that I've figured out the real STR. (Having its occurrence tied to saved profile settings was sending me down all kinds of wrong ratholes.) I just wanted to record the STR before I continued debugging.
Ugh. This took me way too long. I shouldn't really tackle things this messy yet; I don't have a firm enough grasp of the JS engine. I take back what I said about it being stable and reproducible. It usually reproduces, but from run to identical run, it sometimes won't, and when it won't, it will disappear for a whole bunch of consecutive runs. Which makes it much more challenging to pin down. (The profile thing is probably mostly irrelevant, other than another source of random perturbation.) The problem is that JM ends up writing some new machine code over a memory region that is still live on the stack. So when you return up the stack into that JITted code, you land in the middle of the new code. It does this when you're sitting at a breakpoint and you exit. This results in jsd_DebuggerOff(), which calls _destroyJSDContext(), which releases JSD's 'dumbContext'. And that ends up throwing out all the compiled code, some of which is still executing. I'm attaching a sample stack from my 'dumbbt' tool (see <http://infomonkey.cdleary.com/questions/29/how-can-i-see-a-c-stack-trace-above-mjitted-stack-frames>). It also contains a regular gdb backtrace, which has proper filename:lineno entries until it gets lost in jitted code.
Summary: Crashes after turning debugging off → Crashes after turning debugging off because JM releases running code
9 years ago
Assignee: general → dvander
Status: NEW → ASSIGNED
Comment on attachment 492497 [details] [diff] [review] don't allocate JIT code across compartments Thanks, Steve, for debugging this down to exactly what was going wrong. JSD's dummy context and compartment bites us again, this time fooling us into generating code into the wrong compartment's executable pool.
Attachment #492497 - Flags: review?(dmandelin)
Attachment #492497 - Flags: review?(dmandelin) → review+
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.