Friday, August 20, 2010

Palm Developer Blog: Debugging PDK Applications

Posted: 19 Aug 2010 02:47 PM PDT
When you build a C/C++-based application using the PDK for our webOS devices, you’re effectively doing embedded development. Here are some tips and hints for how you can get data back off the device to see what’s going on.

Getting a Device Shell

PDK developers usually need to get deeper access to their devices than developers using the JavaScript SDK. To facilitate that, we provide a pdk-device-install script in the SDK. This installs an SSH daemon on the device that listens to network connections coming over the USB cable. A tcprelay service installed on your desktop system redirects traffic from your localhost to the device. The usual way to shell into the device is:
  1. If you’ve just updated your OS, or you haven’t installed SSH before, run pdk-device-install install, then wait for the device to reboot.
  2. If you’re using Windows: putty -P 10022 root@localhost
  3. If you’re using Mac OS X: ssh -p 10022 root@localhost
An alternative way to get a shell is available if you’re on Mac OS X. One of the utilities that comes with the SDK on OS X is novaterm. This uses the native novacom protocol to open a shell to the device. Unfortunately, novaterm isn’t available on Windows as part of the SDK, so you’ll need to use SSH/PuTTY there.
Once you have a shell on the device, you have most of the common Linux shell commands available, like cd, cat, ls, cp, du, less, more, and vi. (The vi implementation on device is a version from Busybox, so many of the advanced commands don’t work.)

Logging

When you run a JavaScript-based application, you can use the Mojo.Log methods to write out useful information at runtime. PDK apps can do the same thing using the syslog() system call. To use this, add #include to the top of your source file, call openlog(“mypackageid“, 0, LOG_USER) in your init code, then use syslog(LOG_INFO, “format”, args) calls in your code to log information. You can change the LOG_INFO to match the level of importance your message has.

To view these log messages, you can look in /var/log/messages. One way to monitor this in realtime is to open a shell on the device and run tail -f /var/log/messages. If you just want to show output for your own application, use tail -f /var/log/messages | grep packageid. Unfortunately, you can’t use palm-log to view these messages, as the tool only recognizes output from LunaSysMgr, the WebKit-instance that runs JavaScript code in the system.

Mini-Core Dumps

Traditional Linux systems are setup to generate large core dump files when an application crashes. These can be opened by the debugger and show the whole state of the application at its time of death. Since we don’t have that kind of storage space on webOS, we modified the core dump mechanism to produce files we call “mini-coredumps” instead.

When your app hits a “segmentation fault” or some other error that would cause it to crash, a new file is created in /var/minicores. It has the format RXDXnn_processname.id.minicore.gz. These are just gzipped text files that hold information from the crash, including the stack trace and registers for all the threads in the process. This is often enough to tell you where your app is broken.

Note: to get an effective stack trace, you need to leave debug symbols in your application. This is contrary to our instructions for app distribution, so you may want a separate debug target in your makefile or build scripts that don’t strip the executable.

Using GDB from a SSH/novaterm Shell

One of the command line utilities that we ship on our devices is GDB. This is the standard Linux debugger, and it can be used directly from a device shell. The PDK pdk-device-install script installs an SSH daemon on your device that you can use to shell in, but if you’re on Mac OS X or Linux, you can also use the novaterm command to open a shell.

There are two ways to start GDB. One is to just run the gdb executable. This will open the debugger and load your executable under GDB’s control, but it won’t start debugging until you issue a run command. You also can use the –pid= argument to gdb to have it attach to an already running process.

For GDB to be effective on the device, you’ll need to have built your app with debugging symbols and not stripped them away. You also should have your source code available for GDB to see. This can be done by copying it to the /media/internal partition and using GDB’s directory command to add new locations for it to search for source code. (You can even try using the source code on your desktop computer directly by mounting your system’s directory as an NFS share, but that’s beyond the scope of this article.)
For a good tutorial on using GDB, see this presentation from the University of Maryland.

30 Second Intro to Getting a Stackdump With GDB
  1. Launch GDB, e.g. gdb ./myapp
  2. Type r to run
  3. Interact with the application on device until you get it to crash
  4. At the GDB prompt, type bt to get a back trace. If you have source, you can use l to list the source code around the crash and p var to output variable values.
  5. Type quit to end the debugging session and kill the crashed app.

Using gdbserver for Remote Debugging

gdbserver is a mini-version of GDB that runs on the device, but instead of giving a command prompt, it listens to a network port and takes commands over that connection. You run it on the device using a command like
gdbserver host:2345 application
This starts up the server with a new app and has it listen to port 2345. You’ll see the stdout output from the app here. Tcprelay on the desktop will map this to port 12345, so there you’d run the command:
arm-none-linux-gnueabi-gdb application
pointing to your local copy of the application. To setup the remote connection, you then give GDB the command:
target remote :12345
and if all goes well, you’ll be stopped in your app. Then, if you want to start stepping at the main() function, you’d type the commands
break main
continue
and your app will start running. You then reenter the debugger at main. If you build the app with the -g compiler option and didn’t strip the executable on your local system, you can see the source here.

Running Inside the Jail

Starting in webOS 1.4.5, PDK applications are no longer run as the root user, but instead run in an unprivileged account and in a chroot jail. This means that we’ve setup a special file system just for the application and that it can’t see files that aren’t exposed to it. However, if you shell into the device and just start your application directly, you’re bypassing the jail and not really running it in its expected environment. To invoke the jail properly, you should use the jailer command.

If you just run jailer, you’ll get a quick command line summary:
Usage: jailer [-d][-D] [-t type] [-p homepath] -i appId program [args]
This command is used by LunaSysMgr to start a PDK app in the proper  environment where it has limited access to the rest of the system and  it’s running as a non-root user.

The -d option turns on debugging output from the jailer. Seeing what the jailer process does can be useful, as it can tell you to what your jailed application will have access. The -t option is used to pick the appropriate jail mode to use. For your apps, you should use -t pdk. You should use -p to point to the location where your app is installed, then -i to specify the application id, and finally the name of the app.

The usage to just start your app like it would be started from the launcher is pretty simple:
jailer -p /media/cryptofs/apps/usr/palm/applications/com.mydomain.myapp -i com.mydomain.myapp myapp
The -i specifies the package of the app, while the next parameter is  the full path to your executable file. This will probably be a path into /media/cryptofs where 3rd-party apps are installed. You can also  specify arguments to your app after the executable name if you wish.

If you want to work with your app for a while, you can start a shell in the jail environment, then run your app from that. To do that, change the jailer line to read:
jailer -p /media/cryptofs/apps/usr/palm/applications/com.mydomain.myapp -i com.mydomain.myapp /bin/sh
If you want to start the jailer and the debugger at the same time, the easiest way is to run a jailed shell, then use gdb or gdbserver from there.

Be very careful when working with the /var/palm/jail folders when running as root. It’s very easy to destroy your device’s filesystem. If you do a rm -rf on a folder in /var/palm/jail, you can easily destroy files all over the device. The proper way to remove a jail when it’s no longer needed is to use the jailer with the -D option. That will make sure everything is unbound correctly before removing the jail files. Usually, your device root file system is mounted as read-only so you won’t be able to damage /bin or /usr, but you can still easily modify the /var tree as root which can make your phone unbootable.

http://developer.palm.com/blog/2010/08/debugging-pdk-applications/?utm_source=feedburner&utm_medium=email&utm_campaign=Feed%3A+pdnblog+%28Palm+Developer+Connection+Blog%29&utm_content=Yahoo!+Mail

  

No comments:

Post a Comment

[Invitation] Galaxy Unpacked 2024, Jan 17: Opening a New Era of Mobile AI.

A revolutionary mobile experience is coming. Get ready to discover a new era full of possibilities with the latest Galaxy innovations, desig...

Popular Posts