{"id":135,"date":"2011-09-27T22:39:23","date_gmt":"2011-09-27T21:39:23","guid":{"rendered":"http:\/\/blog.mozilla.org\/jseward\/?p=135"},"modified":"2011-09-27T22:56:27","modified_gmt":"2011-09-27T21:56:27","slug":"valgrind-on-android-current-status","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/jseward\/2011\/09\/27\/valgrind-on-android-current-status\/","title":{"rendered":"Valgrind on Android &#8212; Current Status"},"content":{"rendered":"<p>This is a long post.\u00a0 Here&#8217;s a summary.<\/p>\n<ul>\n<li>the good news: Valgrind&#8217;s Memcheck tool now works well enough on Nexus S that it can run Firefox and find real bugs, for example <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=688733\">bug 688733<\/a>.\u00a0 The false error rate from Memcheck is pretty low, certainly low enough to be usable.<\/li>\n<\/ul>\n<ul>\n<li>as of this morning, all required Valgrind fixes are in the Valgrind SVN trunk repo.<\/li>\n<\/ul>\n<ul>\n<li>the bad news: this requires building a custom ROM and kernel for the Nexus S, that is to say, mucho hoop jumping.\u00a0 Not the faint hearted.<\/li>\n<\/ul>\n<p>The rest of this post explains what the constraints are and approximately what is necessary to get started.<\/p>\n<h3>Constraints<\/h3>\n<p>The main difficulty is the need to build a custom ROM and kernel.\u00a0 There are three reasons for this:<\/p>\n<ul>\n<li>To have a swap enabled kernel.\u00a0 Starting a debuggable build of Firefox on Memcheck gives a process size of around 800MB.\u00a0 Without swap, it gets OOM-killed at around 270MB.\u00a0 But the default kernel isn&#8217;t configured for swap, hence a rebuild is required, as per <a href=\"http:\/\/glandium.org\/blog\/?p=2214\">Mike Hommey&#8217;s instructions<\/a>.\u00a0 Once in place, I gave the kernel a 1GB swap file parked in \/sdcard, and that seemed to work ok.<\/li>\n<\/ul>\n<ul>\n<li>Libraries with symbols.\u00a0 Memcheck needs to have symbol information for \/system\/lib\/libc.so and \/system\/bin\/linker (libc and the dynamic linker).\u00a0 Without these it generates huge numbers of false error reports and is unusable.\u00a0 Symbols for the other libraries are nice (better stacktraces) but not essential.<\/li>\n<\/ul>\n<ul>\n<li>To make it possible to start Firefox on Valgrind.\u00a0 Valgrind can only insert itself into a process at an exec() transition, that is, when the process starts from new.\u00a0 On normal Unixes this is no problem, since the shell from which you start Valgrind does the normal fork-exec thing.\u00a0 But application start on Android is completely different, and doesn&#8217;t involve exec().<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">Instead, there is a master process called the Zygote.\u00a0 To start an application (eg Firefox), a message is sent via a socket to the Zygote.\u00a0 This creates a child with fork(), and the child then goes on to load the relevant bytecode and (presumably) native code and &#8220;becomes&#8221; Firefox.\u00a0 So there&#8217;s no exec()\u00a0 boundary for Valgrind to enter at.<\/p>\n<p style=\"padding-left: 30px;\">Fortunately the AOSP folks provided a solution a couple of months back.\u00a0 They modified Zygote so that it can start selected processes under the control of a user-specified wrapper, which is precisely the hook we need.\u00a0 The AOSP tree now has this fix.<\/p>\n<h3>Overview of getting started<\/h3>\n<p>Here&#8217;s an overview of the process.\u00a0 It doesn&#8217;t contain enough details to simply copy and paste, but it does give some idea of the hoop jumping that is unfortunately still required.<\/p>\n<p>Download sources and build Android images, as per directions at <a href=\"http:\/\/source.android.com\/source\/building.html\">http:\/\/source.android.com\/source\/building.html<\/a>.\u00a0 This in itself is a major exercise.\u00a0 The relevant &#8220;lunch&#8221; flavour is full_crespo-eng, I think.\u00a0 At the end of this stage, you&#8217;ll have (amongst things) libraries with symbols and a wrapper-enabled Zygote.\u00a0 But not a swap enabled kernel.<\/p>\n<p>Build a swap enabled kernel as per <a href=\"http:\/\/glandium.org\/blog\/?p=2214\">Mike Hommey&#8217;s instructions<\/a>, and incorporate it into the images built in the previous stage.\u00a0 In fact, I skipped this step &#8212; Mike kindly did it for me.<\/p>\n<p>Push the images onto the phone, reboot, check it&#8217;s still alive.<\/p>\n<p>Check out a copy of the Valgrind trunk from svn:\/\/svn.valgrind.org\/valgrind\/trunk, and build as described in detail in README.android.\u00a0 If you complete that successfully, you&#8217;ll have a working installation of Valgrind on the phone at \/data\/local\/Inst\/bin\/valgrind.<\/p>\n<p>Install busybox on the phone, to make life a little less austere in the shell.<\/p>\n<p>On the Linux host, generate a 1GB swap file and transfer it to \/sdcard on the phone (that&#8217;s the only place it will fit).\u00a0 Then enable swapping:<\/p>\n<pre>  cat \/proc\/swaps\r\n  \/data\/local\/Bin\/busybox swapon \/sdcard\/swapfile1G\r\n  cat \/proc\/swaps<\/pre>\n<p>Note you&#8217;ll have to manually re-enable swapping every time the phone is rebooted.<\/p>\n<p>Copy from the host, the contents of out\/target\/product\/crespo\/symbols\/system to \/sdcard\/symbols\/system.\u00a0 These are the debuginfo objects for the system libraries.\u00a0 Valgrind expects them to be present, as per comments above, so it can read symbols for libc.so and \/system\/bin\/linker.\u00a0 This will copy far more than that, which is not essential but nice for debugging.<\/p>\n<p>Build a Firefox you want to debug.\u00a0 That of course means with line number info and with the flags &#8211;disable-jemalloc &#8211;enable-valgrind.\u00a0 I strongly suggest you use &#8220;-O -g&#8221; for a good compromise between speed and debuggability.\u00a0 When the build finishes, ask the build system to make an .apk file with the debug info in place, and install it.\u00a0 The .apk will be huge, about 125MB:<\/p>\n<pre>  (cd $objdir &amp;&amp; make package PKG_SKIP_STRIP=1)\r\n  adb install -r $objdir\/dist\/fennec-9.0a1.en-US.eabi-arm.apk<\/pre>\n<p>We&#8217;re nearly there.\u00a0 We have a device which is all set up, and a debuggable Firefox on it.\u00a0 But we need to tell Zygote that we want to start Firefox with a wrapper, namely Valgrind.\u00a0 In the shell on the phone, do this:<\/p>\n<pre>  setprop wrap.org.mozilla.fennec_sewardj \"logwrapper \/data\/local\/start_valgrind_fennec\"<\/pre>\n<p>This tells Zygote that any startup of &#8220;org.mozilla.fennec_sewardj&#8221; should be done via an exec() of \/data\/local\/start_valgrind_fennec applied to Zygote-specified arguments.\u00a0 So, now we can put any old thing in a shell script, and Zygote will run it.\u00a0 Here&#8217;s what I have for \/data\/local\/start_valgrind_fennec:<\/p>\n<pre>  #!\/system\/bin\/sh\r\n  VGPARAMS='--error-limit=no'\r\n  export TMPDIR=\/data\/data\/org.mozilla.fennec_sewardj\r\n  exec \/data\/local\/Inst\/bin\/valgrind $VGPARAMS $*<\/pre>\n<p>Obviously you can put any Valgrind params you want in VGPARAMS; you get the general idea.\u00a0 Note that this is ARM, so you don&#8217;t need the &#8211;smc-check= flag that&#8217;s necessary on x86 targets.<\/p>\n<p>Only two more hoops to jump through now.\u00a0 One question is where the Valgrind output should go.\u00a0 Initially I tried using Valgrind&#8217;s little-known but very useful &#8211;log-socket= parameter (see <a href=\"http:\/\/valgrind.org\/docs\/manual\/manual-core.html#manual-core.basicopts\">here<\/a> for details), but it seemed to crash the phone on a regular basis.<\/p>\n<p>So I abandoned that.\u00a0 By default, Valgrind&#8217;s output winds up in the phone&#8217;s system log, mixed up with lots of other stuff.\u00a0 In the end I wound up running the following on the host, which works pretty well:<\/p>\n<pre>  adb logcat -c ; adb logcat | grep --line-buffered start_valgrind \\\r\n    | sed -u sQ\/data\/local\/start_valgrind_QQg | tee logfile.txt<\/pre>\n<p>And finally .. we need to start Firefox.\u00a0 Now, due to recent changes in how the libraries are packaged for Android, you can&#8217;t start it by pressing on the Fennec icon (well, you can, but Valgrind won&#8217;t read the debuginfo.)\u00a0 Instead, issue this command in a shell on the phone:<\/p>\n<pre>  am start -a org.mozilla.gecko.DEBUG -n org.mozilla.fennec_sewardj\/.App<\/pre>\n<p>This requests a &#8220;debug intent&#8221; startup of Firefox, which sidesteps the fancy dynamic unpacking of libraries into ashmem, and instead does the old style thing of unpacking them into \/data\/data\/org.mozilla.fennec_sewardj.\u00a0 From there Valgrind can read debuginfo in the normal way.<\/p>\n<p>One minor last hint: run &#8220;top -d 2 -s cpu -m 19&#8221;.\u00a0 Because Valgrind runs slowly on the phone, I&#8217;m\u00a0 often in the situation of wondering am-I-waiting-for-it or is-it-waiting-for-me?\u00a0 Running top pretty much answers that question.<\/p>\n<p>And .. so .. it works!\u00a0 It&#8217;s slow, but it appears to be stable, and, crucially, the false error rate from\u00a0 Memcheck is low enough to be usable.<\/p>\n<p>So, what&#8217;s next?\u00a0 Writing this reminded me what a hassle it is to get all the ducks lined up right.\u00a0 We need to streamline it.\u00a0 Suggestions welcome!.<\/p>\n<p>One thing I&#8217;ve been thinking about is to to avoid the need to have debuginfo on the target, by allowing Valgrind to query the host somehow.\u00a0 Another thing I plan to do is make the Callgrind tool work, so we can get profile information too.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a long post.\u00a0 Here&#8217;s a summary. the good news: Valgrind&#8217;s Memcheck tool now works well enough on Nexus S that it can run Firefox and find real bugs, for example bug 688733.\u00a0 The false error rate from Memcheck &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/jseward\/2011\/09\/27\/valgrind-on-android-current-status\/\">Continue reading<\/a><\/p>\n","protected":false},"author":240,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/posts\/135"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/users\/240"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/comments?post=135"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/posts\/135\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/media?parent=135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/categories?post=135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/jseward\/wp-json\/wp\/v2\/tags?post=135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}