Opened 6 weeks ago
Closed 3 weeks ago
#19309 closed bug (fixed)
[Debugger] Stack traces inside Gecko are completely wrong
Reported by: | waddlesplash | Owned by: | anevilyak |
---|---|---|---|
Priority: | normal | Milestone: | R1/beta6 |
Component: | Applications/Debugger | Version: | R1/beta5 |
Keywords: | Cc: | ||
Blocked By: | Blocking: | ||
Platform: | All |
Description
For example, on a fork
call, this is the stack trace I get from Debugger:
thread 5250: IPC Launch #1 0x7fa5b31363d0 0x1d6abfb852b fork + 0x1b 0x7fa5b3136460 0x26b036aa24 js::frontend::GeneralParser<js::frontend::SyntaxParseHandler, mozilla::Utf8Unit>::bindingIdentifierOrPattern(js::frontend::DeclarationKind, js::frontend::YieldHandling, js::frontend::TokenKind) + 0x12c 0x7fa5b31364b0 0x26b039e906 js::frontend::Parser<js::frontend::FullParseHandler, char32_t>::globalBody(js::frontend::GlobalSharedContext*) + 0xee 0x7fa5b3136520 0x26b039d618 js::frontend::Parser<js::frontend::FullParseHandler, char32_t>::evalBody(js::frontend::EvalSharedContext*) + 0x240 0x7fa5b3136550 0x26b03a6e8a CompileStandaloneFunction(JSContext*, JS::ReadOnlyCompileOptions const&, JS::SourceText<char32_t>&, mozilla::Maybe<unsigned int> const&, js::frontend::FunctionSyntaxKind, js::GeneratorKind, js::FunctionAsyncKind, JS::Handle<js::Scope*>) + 0x4f2 0x7fa5b31365d0 0x26afd919bf content_analysis::sdk::ContentAnalysisRequest::_InternalParse(char const*, google::protobuf::internal::ParseContext*) + 0x477 0x7fa5b31366c0 0x26afda3918 mozilla::ExtensionPolicyService::GetCoreByHost(nsTSubstring<char> const&) + 0x70 0x7fa5b3136780 0x26afd9f38a mozilla::IdentityCredentialStorageService::DeleteLightweightData(mozIStorageConnection*, mozilla::dom::IPCIdentityCredential const&) + 0x212 0x7fa5b31367b0 0x26afda2147 mozilla::OriginAttrsPatternMatchOriginSQLFunction::OnFunctionCall(mozIStorageValueArray*, nsIVariant**) + 0x17f 0x7fa5b31367f0 0x26b03b11a2 js::frontend::BytecodeEmitter::emitDestructuringOpsArray(js::frontend::ListNode*, js::frontend::DestructuringFlavor) + 0x74a 0x7fa5b3136820 0x26b036f2f4 js::frontend::GeneralParser<js::frontend::FullParseHandler, char32_t>::continueStatement(js::frontend::YieldHandling) + 0xbc 0x7fa5b3136a00 0x26afd9d21e mozilla::IdentityCredentialStorageService::BlockShutdown(nsIAsyncShutdownClient*) + 0x86 0x7fa5b3136a40 0x79fe1a2fc9 _pt_root + 0xb9 0x7fa5b3136a60 0x1d6abf43a35 pthread_thread_entry(void*, void*) + 0x15 00000000 0x7fa5d487c2b0 commpage_thread_exit + 0
And this is the stack trace I get from GDB:
1 fork 0x5677d4a420 2 base::LaunchApp(std::vector<std::string> const&, base::LaunchOptions&&, int *) 0x1ddf3049a29 3 mozilla::ipc::PosixProcessLauncher::DoLaunch() 0x1ddf307d90b 4 mozilla::ipc::BaseProcessLauncher::PerformAsyncLaunch() 0x1ddf307c61b 5 mozilla::detail::ProxyRunnable<mozilla::MozPromise<mozilla::ipc::LaunchResults, mozilla::ipc::LaunchError, true>, RefPtr<mozilla::MozPromise<mozilla::ipc::LaunchResults, mozilla::ipc::LaunchError, true>> (mozilla::ipc::BaseProcessLauncher:: *)(), mozilla::ipc::BaseProcessLauncher>::Run() 0x1ddf3085e8c 6 mozilla::TaskQueue::Runner::Run() 0x1ddf2a709c2 7 nsThreadPool::Run() 0x1ddf2a8291b 8 nsThread::ProcessNextEvent(bool, bool *) 0x1ddf2a7e38d 9 NS_ProcessNextEvent(nsIThread *, bool) 0x1ddf2a8114d 10 mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate *) 0x1ddf30901a7 11 MessageLoop::Run() 0x1ddf304e2f6 12 nsThread::ThreadFunc(void *) 0x1ddf2a7c223 13 _pt_root 0x1d74a9ccfcc 14 pthread_thread_entry(void *, void *) 0x5677cd5948 15 ?? 0x7fff3184d2b0 16 ??
Change History (7)
comment:1 by , 6 weeks ago
comment:3 by , 6 weeks ago
In the case where no frame information is available (.debug/eh_frame), both the user and kernel debugger currently assume the simple case of stack frames delineated by the stack/frame pointer registers. This worked fine back in the day but with newer gcc having made fomit-frame-pointer the default will break spectacularly in the latter case as ebp/rbp will instead contain application data. Handling this correctly requires a significantly more sophisticated algorithm that starts from the beginning of the function to figure out how to get to the current instruction pointer in order to correctly reconstruct the frame and where the return address is. On the plus side this would have the side effect of being able to completely discover all register values for unassisted frames though.
comment:4 by , 6 weeks ago
Well, this file (libxul.so) does appear to contain an .eh_frame:
13 .eh_frame_hdr 00201674 00000000024c2c7c 00000000024c2c7c 024c2c7c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 14 .eh_frame 00bb96b8 00000000026c42f0 00000000026c42f0 026c42f0 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
So why is it failing in this case then?
comment:5 by , 6 weeks ago
Its presence doesn't guarantee it covers all compilation units ; the compiler will only emit unwind info for functions that are called in a context where an exception handler might need to deal with them.
comment:6 by , 5 weeks ago
There's an interesting comment at the top of this thread: https://news.ycombinator.com/item?id=35592446
Implementing the algorithm described there as a "first pass" sounds worthwhile. But if this is also related to #19022 and others, maybe there is something else wrong here.
comment:7 by , 3 weeks ago
Milestone: | Unscheduled → R1/beta6 |
---|---|
Resolution: | → fixed |
Status: | new → closed |
Fixed in hrev58524.
Meanwhile the kernel debugger doesn't even try, it stops at "fork" and prints no more stack frames after that.