{"id":130,"date":"2008-09-23T13:08:32","date_gmt":"2008-09-23T18:08:32","guid":{"rendered":"http:\/\/www.visophyte.org\/blog\/?page_id=130"},"modified":"2023-11-06T12:05:33","modified_gmt":"2023-11-06T17:05:33","slug":"chroniquery","status":"publish","type":"page","link":"https:\/\/www.visophyte.org\/blog\/chroniquery\/","title":{"rendered":"chroniquery"},"content":{"rendered":"<p><strong>Get the code<\/strong><\/p>\n<p>chroniquery itself:<\/p>\n<p><em>bzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/chroniquery\/trunk\/ chroniquery<\/em><\/p>\n<p>chronicle-recorder:<\/p>\n<p><em>bzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/chronicle-recorder\/visbrero-integration\/ chronicle-recorder<br \/>\ncd chronicle-recorder\/chronicle<br \/>\nmv valgrind old-valgrind<br \/>\nbzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/valgrind-chronicle\/valgrind-chronicle\/ valgrind<\/em><\/p>\n<p><strong>Build chronicle<\/strong><\/p>\n<p>in chronicle-recorder, <em>make<\/em><\/p>\n<p><strong>Set up your scripts\/paths<\/strong><\/p>\n<p>You want the chronicle-recorder\/chronicle\/chronicle-query binary to be on your path; symlinking is fine.<\/p>\n<p>You may want to put chroniquery\/python\/chronisole.py on your path too, so that you can invoke it from anywhere.<\/p>\n<p>You probably also want to create a &#8220;chronicle&#8221; script that allows you to easily run a program under chronicle.\u00a0 For example, you might use the following as a basis:<\/p>\n<pre>#!\/bin\/sh\nCHRONBASE=\/path\/to\/chronicle-recorder\/chronicle\/\nappname=$1\nshift\nPATH=$CHRONBASE:$PATH CHRONICLE_DB=`basename $appname`.db VALGRIND_LIB=$CHRONBASE\/valgrind\/.in_place $CHRONBASE\/valgrind\/coregrind\/valgrind --tool=chronicle $appname \"$@\"<\/pre>\n<p>(You can also find the script in chroniquery\/scripts, but you&#8217;ll still need to modify it.)<\/p>\n<p><strong>Run something under chronicle<\/strong><\/p>\n<p>Let&#8217;s try an example program from chroniquery\/examples:<\/p>\n<p><em>g++ fancy.cc -g -o fancy<br \/>\nchronicle .\/fancy<\/em><\/p>\n<p>This should result in chronicle leaving a &#8216;fancy.db&#8217; file in the directory.<\/p>\n<p>Now, let&#8217;s use the &#8220;trace&#8221; mechanism:<\/p>\n<p><em>chronisole.py trace fancy -f main<\/em><\/p>\n<p>This tells chronisole to run the &#8220;trace&#8221; command against the &#8220;fancy&#8221; program.\u00a0 fancy.db is implied, but you could also have done <em>chronisole.py trace fancy fancy.db -f main<\/em>.\u00a0 The &#8220;-f main&#8221; indicates that you want to start tracing from the &#8216;main&#8217; function.<\/p>\n<p><strong>Doing fancy javascript aware tracing<\/strong><\/p>\n<p>First, it&#8217;s a good idea to tell chronisole how to ignore the stuff we don&#8217;t care about.\u00a0 For now, this is done via the ~\/.chroniquery.cfg file.\u00a0 Here are the contents of mine:<\/p>\n<pre>[default]\ninteresting=false\nrecurse=false\n\n[templates]\nboring=true\n\n[dir@mail]\ninteresting=true\ndepth=2\n\n[dir@mailnews]\ninteresting=true\ndepth=3\n\n[dir@mozilla\/db\/mork]\ninteresting=true\n\n# Blanket boring mozilla\n[dir@mozilla]\nboring=true\n\n# Now opt-in things that are perhaps not actually boring...\n[dir@mozilla\/modules\/libpref]\nboring=false\ndepth=0\n\n# Inline things are jerks and need to be banned until our logic improves\n#  (can it? I'm not sure DWARF is on our side here...)\n[func@getter_Copies]\nboring=true\n[class@nsCGetterCopies]\nboring=true\n\n[class@nsID]\nboring=true\n[class@nsIJSID]\nboring=true\n[class@nsAutoRefCnt]\nboring=true\n\n[func@Substring]\nboring=true\n[class@nsCString]\nboring=true\n[class@nsString]\nboring=true\n[class@nsCAutoString]\nboring=true\n[class@nsAutoString]\nboring=True\n[class@nsDependentCString]\nboring=true\n[class@nsDependentString]\nboring=true\n[class@nsDependentSubstring]\nboring=true\n[class@nsFixedCString]\nboring=true\n[class@nsFixedString]\nboring=true\n[class@nsACstring]\nboring=true\n[class@nsAString]\nboring=true\n[class@nsACString_internal]\nboring=true\n[class@nsAString_internal]\nboring=true\n[class@nsSubstring_base]\nboring=true\n[class@nsXPIDLCString]\nboring=true\n\n[class@NS_ConvertUTF8toUTF16]\nboring=true<\/pre>\n<p>Without this, chronicle would want to trace into everything.<\/p>\n<p><em><strong>BEWARE OF HACKS<\/strong><\/em><\/p>\n<p>So, you may note in the above configuration file, we have some paths.\u00a0 If you grep for &#8220;evil&#8221; in the code, you may also note that there is a Chronifer._evilNormalizePath method in chronifer.py.\u00a0 That evil method assumes that you are using comm-central and the top of the repository is also named that way; if this turns out to be true, it strips the path up through comm-central\/.\u00a0 It now also falls back to the possibility that your repository is named mozilla-central, stripping up through mozilla-central\/ and replacing it with just &#8220;mozilla\/&#8221;.\u00a0 It assumes that if you have objdirs for your builds, that the objdir starts with &#8220;obj-&#8221; and that it is found under comm-central or mozilla-central.<\/p>\n<p>This should clearly either not be hardcoded or not stupid.<\/p>\n<p><em><strong>END BEWARE OF HACKS<\/strong><\/em><\/p>\n<p>Let&#8217;s assume you want to trace an xpcshell run.\u00a0 First, you probably want something like this patch against comm-central <a href=\"http:\/\/www.visophyte.org\/blog\/wp-content\/uploads\/2008\/09\/chroni-test\">chroni-test<\/a> and this wrapper script <a href=\"http:\/\/www.visophyte.org\/blog\/wp-content\/uploads\/2008\/09\/chronicle-xpcshell\">chronicle-xpcshell<\/a> (rather like the above helper script, but targetting \/tmp) that you would place in dist\/bin.\u00a0 You also need debug symbols, so your .mozconfig should have <em>&#8211;enable-debugger-info-modules=yes<\/em> in it.\u00a0 You don&#8217;t have to &#8211;enable-debug or &#8211;disable-optimize, in fact you may not want to (as the DEBUG hit and lack of optimization will get even worse with chronicle), but you may want to ramp down the optimization using <em>&#8211;enable-optimize=-O1<\/em> if you are leaving optimization on.\u00a0 Then you can do:<\/p>\n<p><em>USECHRONICLE=1 SOLO_FILE=&#8221;test_name.js&#8221; check-one<\/em><\/p>\n<p>So, to run a javascript aware trace against the resulting xpcshell trace, we do:<\/p>\n<p><em>chronisole.py jstrace path\/to\/xpcshell path\/to\/logfile -d 5<\/em><\/p>\n<p>(-d controls the default maximum recurse depth, you can leave this off if you want, as the configuration file&#8217;s interesting logic can accomplish this more specifically)<\/p>\n<p>Note that the results are basically a good proof-of-concept, but are not perfect.\u00a0 What happens is that we find all calls to JS_NewContext in order to find out all the javascript contexts used in the system.\u00a0 Then, we iterate over each of the context objects, watching for writes to their frame pointer (&#8216;fp&#8217;).<\/p>\n<p>Using some incorrect logic, we attempt to figure out what&#8217;s going on with the stack.\u00a0 (Because of the save frame\/restore frame stuff, the logic can get confused.)\u00a0 What we should be doing is tracing the fp-&gt;down chain until we hit null each time, most likely.\u00a0 But what we do is try and perform only 2 memory reads and figure out if we&#8217;re pushing or popping the stack.\u00a0 If we are pushing, we look for calls made from the current point.<\/p>\n<p>If the call is to the XPC call or getter\/setter function, we do note the interface the call is going through and do some magic to go directly to the actual dispatch, avoiding the intermediary XPConnect stuff we could care less about.<\/p>\n<p>Once we are in general trace space, we use the configuration file previously noted to figure out whether we want to display the current function (we do if it&#8217;s not boring), whether we want to recurse (we do if it&#8217;s interesting), and how deep we want to recurse.<\/p>\n<p>The serious deficiency in this implementation is that we do not attempt to integrate the multiple javascript context interpretations into the same time-line.\u00a0 Additionally, the function tracing is done independently of the known event stream for the context.\u00a0 This means that if we go JS -&gt; XPC -&gt; CPP -&gt; XPC -&gt; JS, the trace we print won&#8217;t accurately represent that at all.\u00a0 What we need to do is maintain a time-ordered series of known events that we populate and dispatch based off of this.\u00a0 (This would also allow us to potentially be more memory efficient for large traces if we integrated on-demand fetching of more events.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Get the code chroniquery itself: bzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/chroniquery\/trunk\/ chroniquery chronicle-recorder: bzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/chronicle-recorder\/visbrero-integration\/ chronicle-recorder cd chronicle-recorder\/chronicle mv valgrind old-valgrind bzr branch http:\/\/www.visophyte.org\/rev_control\/bzr\/valgrind-chronicle\/valgrind-chronicle\/ valgrind Build chronicle in chronicle-recorder, make Set up your scripts\/paths You want the chronicle-recorder\/chronicle\/chronicle-query binary to be on &hellip; <a href=\"https:\/\/www.visophyte.org\/blog\/chroniquery\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-130","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/pages\/130","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/comments?post=130"}],"version-history":[{"count":6,"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/pages\/130\/revisions"}],"predecessor-version":[{"id":134,"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/pages\/130\/revisions\/134"}],"wp:attachment":[{"href":"https:\/\/www.visophyte.org\/blog\/wp-json\/wp\/v2\/media?parent=130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}