Firefox analysis with source codes

After compiling Firefox 12, and then going a “gdb firefox” and then “break main” and then “run”:

We get:

Breakpoint 1, main (argc=1, argv=0x7fffffffe268)
at /mnt/cdrive/firefox/mozilla-beta/browser/app/nsBrowserApp.cpp:212
212 {

Now the function has stopped at main(), located at the above file (nsBrowserApp.c) and “list” in gdb to see source codes:

(gdb) list
207
208 return result;
209 }
210
211 int main(int argc, char* argv[])
212 {
213 char exePath[MAXPATHLEN];
214
215 #ifdef XP_MACOSX
216 TriggerQuirks();

Now we use “next” to step over the functions execution:

(gdb) next
219 nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
(gdb)
225 char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
(gdb) next
226 if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
(gdb)
225 char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
(gdb)
226 if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
(gdb)
229 strcpy(++lastSlash, XPCOM_DLL);
(gdb)
107 return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
(gdb) list
102 #endif
103
104 __extern_always_inline char *
105 __NTH (strcpy (char *__restrict __dest, __const char *__restrict __src))
106 {
107 return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
108 }
109
110 #ifdef __USE_GNU
111 __extern_always_inline char *
(gdb) n
234 gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
(gdb)
246 XPCOMGlueEnablePreload();
(gdb)
250 rv = XPCOMGlueStartup(exePath);
(gdb)
251 if (NS_FAILED(rv)) {
(gdb) list
246 XPCOMGlueEnablePreload();
247 }
248
249
250 rv = XPCOMGlueStartup(exePath);
251 if (NS_FAILED(rv)) {
252 Output("Couldn't load XPCOM.\n");
253 return 255;
254 }
255 // Reset exePath so that it is the directory name and not the xpcom dll name
(gdb) n
252 Output("Couldn't load XPCOM.\n");
(gdb)
251 if (NS_FAILED(rv)) {
(gdb)
258 rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
(gdb)
256 *lastSlash = 0;
(gdb)
258 rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
(gdb)
259 if (NS_FAILED(rv)) {
(gdb)
268 if (gotCounters) {
(gdb)
283 int(initialRUsage.ru_majflt));
(gdb)
285 if (!getrusage(RUSAGE_SELF, &newRUsage)) {
(gdb)
287 int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
(gdb)
294 ScopedLogging log;
(gdb)
295 result = do_main(exePath, argc, argv);
(gdb)

Now once it goes into do_main() it will not return, and thus “control-C” and then setting other breakpoints is needed.

In our cases, “rbreak nsHtml5Parser::*” is executed to stop all any of the functions in the nsHtml5Parser object.

Now a backtrace (bt) revealed all the functions executed:

Breakpoint 2, nsHtml5Parser::AddRef (this=0x7fffcf429a00)
at /mnt/cdrive/firefox/mozilla-beta/parser/html/nsHtml5Parser.cpp:71
71 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5Parser)
(gdb) bt
#0 nsHtml5Parser::AddRef (this=0x7fffcf429a00)
at /mnt/cdrive/firefox/mozilla-beta/parser/html/nsHtml5Parser.cpp:71
#1 0x00007ffff4243b9b in nsHtml5Module::NewHtml5Parser ()
at /mnt/cdrive/firefox/mozilla-beta/parser/html/nsHtml5Module.cpp:108
#2 0x00007ffff40e21d7 in nsHTMLDocument::StartDocumentLoad (
this=0x7fffcece2800, aCommand=0x7ffff4cccb5f "view",
aChannel=0x7fffce8b7050, aLoadGroup=<value optimized out>,
aContainer=<value optimized out>, aDocListener=<value optimized out>,
aReset=<value optimized out>, aSink=0x0)
at /mnt/cdrive/firefox/mozilla-beta/content/html/document/src/nsHTMLDocument.cpp:656
#3 0x00007ffff3dfc80a in nsContentDLF::CreateDocument (
this=<value optimized out>, aCommand=0x7ffff4cccb5f "view",
aChannel=0x7fffce8b7050, aLoadGroup=0x7fffdcf24d40,
aContainer=0x7fffdcf8d940, aDocumentCID=<value optimized out>,
aDocListener=0x7fffcf4fcb18, aContentViewer=0x7fffffffb180)
at /mnt/cdrive/firefox/mozilla-beta/layout/build/nsContentDLF.cpp:461
#4 0x00007ffff3dfcfce in nsContentDLF::CreateInstance (
this=<value optimized out>, aCommand=0x7ffff4cccb5f "view",
aChannel=0x7fffce8b7050, aLoadGroup=0x7fffdcf24d40,
aContentType=0x7fffd0625228 "text/html", aContainer=0x7fffdcf8d940,
aExtraInfo=0x0, aDocListener=0x7fffcf4fcb18, aDocViewer=0x7fffffffb180)
at /mnt/cdrive/firefox/mozilla-beta/layout/build/nsContentDLF.cpp:263
---Type <return> to continue, or q <return> to quit---
#5 0x00007ffff4446f48 in nsDocShell::NewContentViewerObj (
this=<value optimized out>, aContentType=0x7fffd0625228 "text/html",
request=<value optimized out>, aLoadGroup=<value optimized out>,
aContentHandler=<value optimized out>, aViewer=0x7fffffffb180)
at /mnt/cdrive/firefox/mozilla-beta/docshell/base/nsDocShell.cpp:7544
#6 0x00007ffff4451017 in nsDocShell::CreateContentViewer (
this=0x7fffdcf8d800, aContentType=<value optimized out>,
request=0x7fffce8b7050, aContentHandler=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/docshell/base/nsDocShell.cpp:7357
#7 0x00007ffff44544ef in nsDSURIContentListener::DoContent (
this=0x7fffdcd13f40, aContentType=0x7fffd0625228 "text/html",
aIsContentPreferred=true, request=0x7fffce8b7050,
aContentHandler=0x7fffcf4fcb18, aAbortProcess=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/docshell/base/nsDSURIContentListener.cpp:164
#8 0x00007ffff44579fc in nsDocumentOpenInfo::TryContentListener (
this=0x7fffcf4fcb00, aListener=0x7fffdcd13f40, aChannel=0x7fffce8b7050)
at /mnt/cdrive/firefox/mozilla-beta/uriloader/base/nsURILoader.cpp:709
#9 0x00007ffff4457bd5 in nsDocumentOpenInfo::DispatchContent (
this=0x7fffcf4fcb00, request=0x7fffce8b7050, aCtxt=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/uriloader/base/nsURILoader.cpp:406
#10 0x00007ffff445834c in nsDocumentOpenInfo::OnStartRequest (
this=0x7fffcf4fcb00, request=0x7fffce8b7050, aCtxt=0x0)
---Type <return> to continue, or q <return> to quit---
at /mnt/cdrive/firefox/mozilla-beta/uriloader/base/nsURILoader.cpp:294
#11 0x00007ffff3d51135 in nsHttpChannel::CallOnStartRequest (
this=0x7fffce8b7000)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:764
#12 0x00007ffff3d514eb in nsHttpChannel::ContinueProcessNormal (
this=0x7fffce8b7000, rv=4115409808)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:1260
#13 0x00007ffff3d554f5 in nsHttpChannel::ProcessNormal (this=0x7fffce8b7000)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:1197
#14 0x00007ffff3d55a0a in nsHttpChannel::ProcessResponse (this=0x7fffce8b7000)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:1099
#15 0x00007ffff3d55c6a in nsHttpChannel::OnStartRequest (this=0x7fffce8b7000,
request=0x7fffd4e5f4e0, ctxt=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:4164
#16 0x00007ffff3cdc1a9 in nsInputStreamPump::OnStateStart (this=0x7fffd4e5f4e0)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/base/src/nsInputStreamPump.cpp:444
#17 0x00007ffff3cdc552 in nsInputStreamPump::OnInputStreamReady (
---Type <return> to continue, or q <return> to quit---
this=0x7fffd4e5f4e0, stream=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/base/src/nsInputStreamPump.cpp:399

Executing further:
(gdb) bt
#0 nsHTMLDocument::StartDocumentLoad (this=0x7fffcece2800,
aCommand=0x7ffff4cccb5f "view", aChannel=0x7fffce8b7050,
aLoadGroup=<value optimized out>, aContainer=<value optimized out>,
aDocListener=<value optimized out>, aReset=<value optimized out>,
aSink=0x0)
at /mnt/cdrive/firefox/mozilla-beta/content/html/document/src/nsHTMLDocument.cpp:860
#1 0x00007ffff3dfc80a in nsContentDLF::CreateDocument (
this=<value optimized out>, aCommand=0x7ffff4cccb5f "view",
aChannel=0x7fffce8b7050, aLoadGroup=0x7fffdcf24d40,
aContainer=0x7fffdcf8d940, aDocumentCID=<value optimized out>,
aDocListener=0x7fffcf4fcb18, aContentViewer=0x7fffffffb180)
at /mnt/cdrive/firefox/mozilla-beta/layout/build/nsContentDLF.cpp:461

and looking at the source code:
(gdb) list nsHTMLDocument::StartDocumentLoad
559 nsILoadGroup* aLoadGroup,
560 nsISupports* aContainer,
561 nsIStreamListener **aDocListener,
562 bool aReset,
563 nsIContentSink* aSink)
564 {
565 nsCAutoString contentType;
566 aChannel->GetContentType(contentType);

and jumpping ahead – here a check is done if the document is from POST command:

783 // check if current doc is from POST command
784 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
785 if (httpChannel) {
786 nsCAutoString methodStr;
787 rv = httpChannel->GetRequestMethod(methodStr);
788 isPostPage = (NS_SUCCEEDED(rv) &&
(gdb)
789 methodStr.EqualsLiteral("POST"));
790 }

and next is the tokenization of the the HTML stream:
(gdb) bt
#0 nsHtml5Parser::StartTokenizer (this=0x7fffcf429a00, aScriptingEnabled=true)
at /mnt/cdrive/firefox/mozilla-beta/parser/html/nsHtml5Parser.cpp:742
#1 0x00007ffff424a432 in nsHtml5StreamParser::OnStartRequest (
this=0x7fffd6043bc0, aRequest=<value optimized out>,
aContext=<value optimized out>)
at /mnt/cdrive/firefox/mozilla-beta/parser/html/nsHtml5StreamParser.cpp:926
#2 0x00007ffff445836a in nsDocumentOpenInfo::OnStartRequest (
this=0x7fffcf4fcb00, request=0x7fffce8b7050, aCtxt=0x0)
at /mnt/cdrive/firefox/mozilla-beta/uriloader/base/nsURILoader.cpp:304
#3 0x00007ffff3d51135 in nsHttpChannel::CallOnStartRequest (
this=0x7fffce8b7000)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:764
#4 0x00007ffff3d514eb in nsHttpChannel::ContinueProcessNormal (
this=0x7fffce8b7000, rv=1)
at /mnt/cdrive/firefox/mozilla-beta/netwerk/protocol/http/nsHttpChannel.cpp:1260

Continue next time.

Advertisements

4 responses to this post.

  1. From above, what is the role of:

    nsInputStreamPump::OnInputStreamReady()

    From:

    https://people.mozilla.com/~choller/firefox/clang-static/2012-01-12-1/report-3nhRVC.html

    We can see that it is a state machine, and identify three different state:

    switch (mState) {
    case STATE_START:
    nextState = OnStateStart();
    break;
    case STATE_TRANSFER:
    nextState = OnStateTransfer();
    break;
    case STATE_STOP:
    nextState = OnStateStop();
    break;
    }


    These processing correspond to the stream processing of the web traffic, prior to HTML parsing and tokenization. To further understand the details, the following URL is recommended:

    http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/

    http://taligarsiel.com/Projects/howbrowserswork1.htm

    And the complex processing flow can be shown here:

    http://www.scribd.com/ytakanoster3382/d/6247563–incompleted-version-of-the-life-of-an-HTML-HTTP-request-in-Firefox-3

    Reply

  2. From this URL (profile analysis, which is runtime-based):

    http://forums.mozillazine.org/viewtopic.php?f=23&t=2367863&start=195

    and this (code coverage analysis, which is static-time based):

    http://people.mozilla.org/~jcranmer2/c-ccov/netwerk/base/src/nsInputStreamPump.cpp.func.html

    we can see how often some of the API described above is called.

    Reply

  3. To understand the sequence of event before nsInputStreamPump::OnStateStart() is called:

    https://bugzilla.mozilla.org/show_bug.cgi?id=336280

    which approximately goes like this:

    12 libxpcom_core.dylib 0x00f1a645 nsInputStreamReadyEvent::EventHandler(PLEvent*) + 45
    13 libxpcom_core.dylib 0x00eef129 PL_HandleEvent + 21
    14 libxpcom_core.dylib 0x00eef3e2 PL_ProcessPendingEvents + 103
    15 com.apple.CoreFoundation 0x9082363d CFRunLoopRunSpecific + 1213
    16 com.apple.CoreFoundation 0x90823179 CFRunLoopRunInMode + 61
    17 com.apple.HIToolbox 0x92ef9c5c RunCurrentEventLoopInMode + 285
    18 com.apple.HIToolbox 0x92fee049 GetNextEventMatchingMask + 419
    19 com.apple.HIToolbox 0x92fedd35 WNEInternal + 123
    20 com.apple.HIToolbox 0x92fedca3 WaitNextEvent + 57
    21 org.mozilla.firefox 0x005ea40c nsMacMessagePump::GetEvent(EventRecord&) + 82
    22 org.mozilla.firefox 0x005eb171 nsMacMessagePump::DoMessagePump() + 45
    23 org.mozilla.firefox 0x002a0c4c nsAppShell::Run() + 38
    24 org.mozilla.firefox 0x0033a642 nsAppStartup::Run() + 50
    25 org.mozilla.firefox 0x00006254 XRE_main + 5246
    26 org.mozilla.firefox 0x000030f8 main + 32
    27 org.mozilla.firefox 0x0000307e start + 270
    28 org.mozilla.firefox 0x00002f99 start + 41

    Reply

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: