Updated JimDB

At the mobile team meet-up two weeks ago I demonstrated some of the newer features in JimDB, the GDB package used for Fennec development. This past week I pushed out these new changes, and also updated the wiki page, which includes (or will include) all instructions and documentation. You should check it out if you ever need to use GDB to debug Fennec!

JimDB main prompt

Some of the changes since my last blog post include,

  • Support for launching Fennec with environment variables and arguments
  • Support for debugging Mochitests.
    • You can now debug a single test, a whole directory, or use TEST_PATH like before (thanks :jwatt!)
    • Environment variables are supported.
    • Because XRE is needed for running Mochitests, JimDB can automatically download and manage a copy of XRE for you.
  • Experimental Java debugger (JDB) integration.
    • Now you can choose the “Debug using jdb” option to debug Fennec Java code (see the jdb doc page for a quick JDB tutorial; so far at least the print and stop commands work).
    • Or you can launch two JimDB instances to debug C++ and Java simultaneously.
  • Miscellaneous improvements
    • A dump-pseudo-stack command to print the profiler stack (thanks :kats!)
    • Detection of mismatch between objdir version and installed version on device
    • Detection of device changes - now new libraries will be downloaded when the device has a new ROM
    • Automatic update
    • Better way to change settings through gdbinit.local
    • Working tab completion on OS X
    • Fixed a bug where breakpoints with conditions can cause crashes (thanks :jwatt!)
    • Fixed a bug where calling functions from JimDB can cause crashes

With these improvements, give the new JimDB a try! Let me know if you run into issues. You can always find me as jchen in #mobile on IRC. There is also a JimDB component on Bugzilla under Firefox for Android.

Next up, I have some possible new features for the next release

  • Robocop debugging support
  • Reftest debugging support
  • Web app debugging support
  • Support for debugging in ${your_favorite_editor}

Let me know if any of these features would help you!

Firefox logo plate

Went out to a ceramics studio tonight, and I painted a Firefox logo plate! It will take a few more days for it to fire (no pun intended), so I'll have to wait to see how it turns out. Overall a fun night with friends and I highly recommend you visiting one if there's a studio near you!

Firefox logo plate

Debugging C++ Unit Tests on Android

With help from Dan Mosedale (dmose), JimDB now has the ability to debug C++ unit tests running on your Android device [1]. To get started, first update your JimDB Python scripts by running git pull under the utils directory.

The process is fairly automatic. After launching JimDB, choose the second option to debug C++ tests,

Fennec GDB utilities
1. Debug Fennec (default)
2. Debug compiled-code unit test
Enter number from above: 2

Then after choosing the object directory, the actual test is specified along with any environmental variables and arguments. Environmental variables can also be preset in the gdbinit file in the utils directory.

Enter path of unit test (use tab-completion to see possibilities)
    path can be relative to $objdir/dist/bin or absolute
    environmental variables and arguments are supported
    e.g. FOO=bar TestFooBar arg1 arg2
: TestRefPtr

Next, the test can be started simply through the continue command,

Ready. Use "continue" to start execution.
(gdb) c
Continuing.

Output from the test is redirected to the terminal running GDB,

out> BEGIN unit tests for |nsRefPtr|, compiled Dec 10 2012
out> >>main()
out> sizeof(nsRefPtr<Foo>) --> 4
out> >>CreateBar() -->   new Foo@0x43f02098 [#1]
out>   new Bar@0x43f02098
out> Bar@0x43f02098
out> Foo@0x43f02098::AddRef(), refcount --> 1
out> <<CreateBar()
out> Bar@0x43f02098::QueryInterface()
out> Foo@0x43f02098::AddRef(), refcount --> 2
out> total constructions/destructions --> 1/0
out> Foo@0x43f02098::Release(), refcount --> 1
out> >>Foo@0x43f02098::Release(), refcount --> 0
out>   delete Foo@0x43f02098
out> <<Foo@0x43f02098::Release()
out> Bar@0x43f02098::~Bar()
out> Foo@0x43f02098::~Foo() [#1]
out> >>CreateBar() -->   new Foo@0x43f02098 [#2]
out>   new Bar@0x43f02098
out> Bar@0x43f02098
out> Foo@0x43f02098::AddRef(), refcount --> 1
out> <<CreateBar()
out> Bar@0x43f02098::QueryInterface()
out> Foo@0x43f02098::AddRef(), refcount --> 2
out> total constructions/destructions --> 2/1
out> Foo@0x43f02098::Release(), refcount --> 1
out> >>Foo@0x43f02098::Release(), refcount --> 0
out>   delete Foo@0x43f02098
out> <<Foo@0x43f02098::Release()
out> Bar@0x43f02098::~Bar()
out> Foo@0x43f02098::~Foo() [#2]
out> 
out> ### Test  1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?
out>   new Foo@0x43f02098 [#3]
out> Foo@0x43f02098::QueryInterface()
out> Foo@0x43f02098::AddRef(), refcount --> 1
...

Support is limited to C++ unit tests for now, but the plan is to include more types of tests that you can debug (mochitest, reftests, etc.). Stay tuned! Feel free to ping me (jchen) on IRC #mobile if you have questions, or file bugs under the Firefox for Android > JimDB component on Bugzilla.

Tunnelling ADB through SSH

TL;DR adb start-server && ssh -R 5037:localhost:5037 remote

In my current workflow, I use a MacBook Air to ssh to a Linux machine for developing and building Fennec (mostly because the Linux box has a way beefier CPU for building than the 2-core MacBook; also it saves battery when I'm not plugged in). But since everything is on the Linux box, I needed a way to make ADB talk to my phone which is connected to my MacBook.

A quick Google search didn't reveal anything, but turns out it's pretty easy to tunnel the ADB protocol over SSH. ADB uses a client-server model. The client is the actual adb command that you use, the server is responsible for talking to the phone, and they communicate through port 5037. So to tunnel it over SSH, you simply need to add a port forwarding rule to the .ssh/config file on your local machine (in my case the MacBook). For example,

Host super-awesome-linux-box
RemoteForward 5037 localhost:5037

This way, every time the client needs to talk to the server on the Linux box, it will be forwarded to the MacBook. You do have to make sure that the ADB server is running on the MacBook, by running

adb start-server

Also, the two machines should have the same version of adb.

However, one drawback of this is that, say you go over to your Linux box while your MacBook is still ssh'd in. Because your ADB is still being forwarded, you cannot use ADB on any devices connected to the Linux box directly. One way to solve this is by using a different port for forwarding ADB,

Host super-awesome-linux-box
RemoteForward 5038 localhost:5037

This forwards the Linux port 5038 to the MacBook port 5037. Then, on the Linux box, you can tell your ADB client to use port 5038 by adding the following to your shell profile script on the Linux remote host,

if [[ -n $SSH_CONNECTION ]]; then
  export ANDROID_ADB_SERVER_PORT=5038
fi

This snippet sets the ADB client port to 5038 only when you are ssh'd in. That way, ADB over SSH will use one port, and ADB used locally will use another port.

Finally, to debug Fennec, you would need a second forwarded port for tunnelling the gdbserver protocol,

Host super-awesome-linux-box
RemoteForward 5038 localhost:5037 # adb
RemoteForward 5039 localhost:5039 # gdbserver

If you pull the latest gdbutils for JimDB, you can uncomment the following line in utils/gdbinit to use this port for gdbserver.

python feninit.default.gdbserver_port = 5039

That's it! If you have any questions, feel free to ping me (jchen) in #mobile on irc.mozilla.org


Edit: Thanks kats for pointing out an unclear part about which .ssh/config file to edit, and that you need the same version of adb.

Updated Android gdb and gdbutils

I took some time today to update both the Fennec Android gdb (aka 'jimdb') and gdbutils. Build instructions should be the same. You can also grab the pre-built Linux tarball. Note that the pre-built binaries require libpython2.7.

gdb

The updated gdb is faster when setting up remote debugging. Sometimes it can get pretty frustrating when you have to debug a lot of sessions, and you have to wait half a minute each time just to get started. This update will hopefully make it a little better. (This is not an issue if you have an intern at your disposal ;)

gdbutils

gdbutils is a set of Python scripts that works with Android gdb. The updated gdbutils includes the following modules:

feninit

feninit automatically sets up the debug environment. The updated version adds support for B2G (see gdbinit for details; thanks ThinkerYzu!) and various bug fixes.

tracebt

tracebt is a stack unwinder that works by tracing assembly. The updated version adds a sanity check to stop unwinding before the script gets stuck somewhere and becomes depressed.

fastload

fastload is a new module that automatically pulls system libraries from the device in the background. This way you don't have to wait minutes just to download system libraries when debugging on a new device.

adblog

adblog is a new module that redirects the output of 'adb logcat' to the gdb terminal when Fennec is running. It also colorizes the logs according to the order they arrived, their priority, or the threads that generated them, like this:

adblog example

You can find additional documentation for gdbutils in the README. Feel free to ping me on IRC (jchen) or file issues on github! Thanks!


Also follow me on twitter! :D