My favorites | Sign in
Logo
             
Search
for
Updated Oct 27, 2009 by tony.chromium
Labels: Linux
LinuxDebugging  
tips for debugging on Linux

This page is for Chromium-specific debugging tips; learning how to run gdb is out of scope.

GDB

Multiprocess Tricks

Getting renderer subprocesses into gdb

Since Chromium itself spawns the renderers, it can be tricky to grab a particular with gdb. This command does the trick:

chrome --renderer-cmd-prefix='gdb --args'

Note that if you're using Emacs and M-x gdb, you must quote it like

chrome "--renderer-cmd-prefix=gdb --args"

Note: using the --renderer-cmd-prefix option bypasses the zygote launcher, so the renderers won't be sandboxed. It is generally not an issue, except when you are trying to debug interactions with the sandbox. If that's what you are doing, you will need to attach your debugger to a running renderer process (see below).

Choosing which renderers to debug

If you are starting multiple renderers then the above means that multiple gdb's start and fight over the console. Instead, you can set the prefix to point to this shell script:

#!/bin/sh

echo "**** Child $$ starting: y to debug"
read input
if [ "$input" == "y" ] ; then
  gdb --args $*
else
  $*
fi

Connecting to a running renderer

Usually ps aux | grep chrome will not give very helpful output. Try pstree -p | grep chrome to get something like

        |                      |-bash(21969)---chrome(672)-+-chrome(694)
        |                      |                           |-chrome(695)---chrome(696)-+-{chrome}(697)
        |                      |                           |                           \-{chrome}(709)
        |                      |                           |-{chrome}(675)
        |                      |                           |-{chrome}(678)
        |                      |                           |-{chrome}(679)
        |                      |                           |-{chrome}(680)
        |                      |                           |-{chrome}(681)
        |                      |                           |-{chrome}(682)
        |                      |                           |-{chrome}(684)
        |                      |                           |-{chrome}(685)
        |                      |                           |-{chrome}(705)
        |                      |                           \-{chrome}(717)

Most of those are threads. In this case the browser process would be 672 and the (sole) renderer process is 696. You can use gdb -p 696 to attach.

Note: by default, sandboxed processes can't be attached by a debugger. To be able to do so, you will need to pass the --allow-sandbox-debugging option.

Debugging all renderers

chrome --renderer-cmd-prefix='xterm -e gdb --args'

Ain't it cute?

To auto-start the renderers in the debugger, send the "run" command to the debugger:

chrome --renderer-cmd-prefix='xterm -e gdb --eval-command=run --args'

Plugin Processes

Same strategies as renderers, but the flag is called --plugin-launcher.

Single-Process mode

Depending on whether it's relevant to the problem, it's often easier to just run in "single process" mode where the renderer threads are in-process. Then you can just run gdb on the main process.

gdb --args chrome --single-process

Printing Chromium types

Here's code for printing WebCore::String types in gdb 7:

import gdb
import re

class WebCoreAtomicStringPrinter:
    "Print a WebCore::AtomicString"
    def __init__(self, val):
        self.val = val  

    def display_hint(self):
        return 'string'

    def to_string(self): 
        return self.val['m_string']


class WebCoreStringPrinter:  
    "Print a WebCore::String"
    def __init__(self, val):
        self.val = val   

    def display_hint(self):  
        return 'string'    

    def get_length(self):
        if not self.val['m_impl']['m_ptr']:
            return 0
        return self.val['m_impl']['m_ptr']['m_length']

    def to_string(self):
        if 0 == self.get_length():
            return '(null)'
        uchar_ptr = self.val['m_impl']['m_ptr']['m_data']
        char_vals = [int((uchar_ptr + i).dereference()) for i in xrange(self.get_length())
        def m(x):
          if x < 128:                      
            return chr(x)
          else:          
            return '?'
        chars = [m(x) for x in char_vals]
        return ''.join(chars)


def lookup_function(val):
    lookup_tag = val.type.tag
    if lookup_tag == None: 
        return None
    if lookup_tag.find("WebCore::AtomicString") != -1:
        return WebCoreAtomicStringPrinter(val)
    if lookup_tag.find("WebCore::String") != -1:
        return WebCoreStringPrinter(val)

    return None

gdb.pretty_printers.append(lookup_function)

Put the above into a file somewhere called webcore.py and load it by adding the following to the end of ~/.gdbinit:

python
import sys
sys.path.append("/path/to/script")
import webcore

Pretty printers for std types shouldn't be necessary in gdb 7, but they're provided here in case you're using an older gdb. Put the following into ~/.gdbinit:

# Print a C++ string.
define ps
  print $arg0.c_str()
end

# Print a C++ wstring or wchar_t*.
define pws
  printf "\""
  set $c = (wchar_t*)$arg0
  while ( *$c )
    if ( *$c > 0x7f )
      printf "[%x]", *$c
    else
      printf "%c", *$c
    end
    set $c++
  end
  printf "\"\n"
end

# Print a FilePath.
define pfp
  print $arg0.value().c_str()
end

More STL GDB macros

Running Tests

Browser tests

By default the browser_tests forks itself for each test. When debugging, it's useful to pass --child flag and --gtest_filter. This is the command line for the forked child.

Layout tests

See LayoutTestsLinux for some tips. In particular, it's possible to debug a layout test via sshing to a Linux box; you don't need anything on screen if you use Xvfb.

UI tests

Like layout tests, you're better off running running ui tests within Xvfb or Xephyr. See above.

Logging

Seeing all LOG(foo) messages

Default log level hides LOG(INFO). Run with --log-level=0 and --enable-logging=stderr flags.

Seeing IPC debug messages

Run with CHROME_IPC_LOGGING=1 eg.

CHROME_IPC_LOGGING=1 sconsbuild/Debug/chrome

or within gdb:

set environment CHROME_IPC_LOGGING 1

Using valgrind

To run valgrind on the browser and renderer processes, with our suppression file and flags:

$ cd $CHROMIUM_ROOT/src
$ chrome/tools/valgrind/valgrind.sh sconsbuild/Debug/chrome

You can use valgrind on chrome and/or on the renderers e.g valgrind --smc-check=all ../sconsbuild/Debug/chrome or by passing valgrind as the argument to --render-cmd-prefix.

Beware that there are several valgrind "false positives" e.g. pickle, sqlite and some instances in webkit that are ignorable. On systems with prelink and address space randomization (e.g. Fedora), you may also see valgrind errors in libstdc++ on startup and in gnome-breakpad.

i18n

We obey your system locale. Try something like:

LANG=ja_JP.UTF-8 sconsbuild/Debug/chrome

If this doesn't work, make sure that the LANGUAGE environment variable isn't set -- it can override LANG.

RTL

Note that GTK needs translation data to properly RTL-ize in an RTL locale, so install that if you're testing an RTL language:

sudo apt-get install language-pack-ar language-pack-he language-pack-gnome-ar language-pack-gnome-he

Note that the --lang flag does not work properly for this; we should just remove it on Linux.

On non-Debian systems, you need the gtk20.mo files. (Please update these docs with the appropriate instructions if you know what they are.)

Tracking Down Bugs

Regression Testing

Old builds are archived here: http://build.chromium.org/buildbot/snapshots/chromium-rel-linux/

Screen recording for bug reports

sudo apt-get install gtk-recordmydesktop

Bugs in Ubuntu packages

Since we don't build the Ubuntu packages (Ubuntu does) we can't get useful backtraces from them. Direct users to https://wiki.ubuntu.com/Chromium/Debug .

Bugs in Fedora packages

Like Ubuntu, but direct users to https://fedoraproject.org/wiki/TomCallaway/Chromium_Debug .

Libraries we depend on

GTK

See Running GLib Applications for notes on how to make GTK warnings fatal.

See also LinuxDebuggingGtk.

Xlib

If you're trying to track down X errors like:

The program 'chrome' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadDrawable (invalid Pixmap or Window parameter)'.

Some strategies are:

Window Managers

To test on various window managers, you can use a nested X server like Xephyr. Instructions for how to use Xephyr are on the LayoutTestsLinux page.

If you need to test something with hardware accelerated compositing (e.g., compiz), you can use Xgl (sudo apt-get install xserver-xgl). E.g.:

Xgl :1 -ac -accel glx:pbuffer -accel xv:pbuffer -screen 1024x768

Mozilla Tips

https://developer.mozilla.org/en/Debugging_Mozilla_on_Linux_FAQ