
GTK2 code was historically kept around to keep the electron build working. But as of Nov 26, 2017, electron now uses GTK3 [1], so it should now be safe to remove all of the old GTK2-only code. [1] https://github.com/electron/electron/issues/2927#issuecomment-347092515 BUG=876558 R=sky Change-Id: I78402053ae508ccd8fc7ac73697a861bb1ebacf6 Reviewed-on: https://chromium-review.googlesource.com/1183858 Commit-Queue: Thomas Anderson <thomasanderson@chromium.org> Reviewed-by: Scott Violet <sky@chromium.org> Cr-Commit-Position: refs/heads/master@{#585265}
536 lines
18 KiB
Markdown
536 lines
18 KiB
Markdown
# Tips for debugging on Linux
|
|
|
|
This page is for Chromium-specific debugging tips; learning how to run gdb is
|
|
out of scope.
|
|
|
|
[TOC]
|
|
|
|
## Symbolized stack trace
|
|
|
|
The sandbox can interfere with the internal symbolizer. Use `--no-sandbox` (but
|
|
keep this temporary) or an external symbolizer (see
|
|
`tools/valgrind/asan/asan_symbolize.py`).
|
|
|
|
Generally, do not use `--no-sandbox` on waterfall bots, sandbox testing is
|
|
needed. Talk to security@chromium.org.
|
|
|
|
## GDB
|
|
|
|
*** promo
|
|
GDB-7.7 is required in order to debug Chrome on Linux.
|
|
***
|
|
|
|
Any prior version will fail to resolve symbols or segfault.
|
|
|
|
### Basic browser process debugging
|
|
|
|
gdb -tui -ex=r --args out/Debug/chrome --disable-seccomp-sandbox \
|
|
http://google.com
|
|
|
|
### Allowing attaching to foreign processes
|
|
|
|
On distributions that use the
|
|
[Yama LSM](https://www.kernel.org/doc/Documentation/security/Yama.txt) (that
|
|
includes Ubuntu and Chrome OS), process A can attach to process B only if A is
|
|
an ancestor of B.
|
|
|
|
You will probably want to disable this feature by using
|
|
|
|
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
|
|
|
|
If you don't you'll get an error message such as "Could not attach to process".
|
|
|
|
Note that you'll also probably want to use `--no-sandbox`, as explained below.
|
|
|
|
### 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 --no-sandbox --renderer-cmd-prefix='xterm -title renderer -e gdb --args'
|
|
```
|
|
|
|
The `--no-sandbox` flag is needed because otherwise the seccomp sandbox will
|
|
kill the renderer process on startup, or the setuid sandbox will prevent xterm's
|
|
execution. The "xterm" is necessary or gdb will run in the current terminal,
|
|
which can get particularly confusing since it's running in the background, and
|
|
if you're also running the main process in gdb, won't work at all (the two
|
|
instances will fight over the terminal). To auto-start the renderers in the
|
|
debugger, send the "run" command to the debugger:
|
|
|
|
chrome --no-sandbox --renderer-cmd-prefix='xterm -title renderer -e gdb \
|
|
-ex run --args
|
|
|
|
If you're using Emacs and `M-x gdb`, you can do
|
|
|
|
chrome "--renderer-cmd-prefix=gdb --args"
|
|
|
|
*** note
|
|
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).
|
|
***
|
|
|
|
You may also want to pass `--disable-hang-monitor` to suppress the hang monitor,
|
|
which is rather annoying.
|
|
|
|
You can also use `--renderer-startup-dialog` and attach to the process in order
|
|
to debug the renderer code. Go to
|
|
https://www.chromium.org/blink/getting-started-with-blink-debugging for more
|
|
information on how this can be done.
|
|
|
|
#### 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:
|
|
|
|
```sh
|
|
#!/bin/sh
|
|
|
|
echo "**** Child $$ starting: y to debug"
|
|
read input
|
|
if [ "$input" = "y" ] ; then
|
|
gdb --args $*
|
|
else
|
|
$*
|
|
fi
|
|
```
|
|
|
|
#### Selective breakpoints
|
|
|
|
When debugging both the browser and renderer process, you might want to have
|
|
separate set of breakpoints to hit. You can use gdb's command files to
|
|
accomplish this by putting breakpoints in separate files and instructing gdb to
|
|
load them.
|
|
|
|
```
|
|
gdb -x ~/debug/browser --args chrome --no-sandbox --disable-hang-monitor \
|
|
--renderer-cmd-prefix='xterm -title renderer -e gdb -x ~/debug/renderer \
|
|
--args '
|
|
```
|
|
|
|
Also, instead of running gdb, you can use the script above, which let's you
|
|
select which renderer process to debug. Note: you might need to use the full
|
|
path to the script and avoid `$HOME` or `~/.`
|
|
|
|
#### 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.
|
|
Alternatively, you might find out the process ID from Chrome's built-in Task
|
|
Manager (under the Tools menu). Right-click on the Task Manager, and enable
|
|
"Process ID" in the list of columns.
|
|
|
|
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.
|
|
|
|
If the problem only occurs with the seccomp sandbox enabled (and the previous
|
|
tricks don't help), you could try enabling core-dumps (see the **Core files**
|
|
section). That would allow you to get a backtrace and see some local variables,
|
|
though you won't be able to step through the running program.
|
|
|
|
Note: If you're interested in debugging LinuxSandboxIPC process, you can attach
|
|
to 694 in the above diagram. The LinuxSandboxIPC process has the same command
|
|
line flag as the browser process so that it's easy to identify it if you run
|
|
`pstree -pa`.
|
|
|
|
#### Getting GPU subprocesses into gdb
|
|
|
|
Use `--gpu-launcher` flag instead of `--renderer-cmd-prefix` in the instructions
|
|
for renderer above.
|
|
|
|
#### Getting `browser_tests` launched browsers into gdb
|
|
|
|
Use environment variable `BROWSER_WRAPPER` instead of `--renderer-cmd-prefix`
|
|
switch in the instructions above.
|
|
|
|
Example:
|
|
|
|
```shell
|
|
BROWSER_WRAPPER='xterm -title renderer -e gdb --eval-command=run \
|
|
--eval-command=quit --args' out/Debug/browser_tests --gtest_filter=Print
|
|
```
|
|
|
|
#### Plugin Processes
|
|
|
|
Same strategies as renderers above, but the flag is called `--plugin-launcher`:
|
|
|
|
chrome --plugin-launcher='xterm -e gdb --args'
|
|
|
|
*** note
|
|
Note: For now, this does not currently apply to PPAPI plugins because they
|
|
currently run in the renderer process.
|
|
***
|
|
|
|
#### 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
|
|
|
|
Currently, the `--disable-gpu` flag is also required, as there are known crashes
|
|
that occur under TextureImageTransportSurface without it. The crash described in
|
|
https://crbug.com/361689 can also sometimes occur, but that crash can be
|
|
continued from without harm.
|
|
|
|
Note that for technical reasons plugins cannot be in-process, so
|
|
`--single-process` only puts the renderers in the browser process. The flag is
|
|
still useful for debugging plugins (since it's only two processes instead of
|
|
three) but you'll still need to use `--plugin-launcher` or another approach.
|
|
|
|
### Printing Chromium types
|
|
|
|
gdb 7 lets us use Python to write pretty-printers for Chromium types. The
|
|
directory `tools/gdb/` contains a Python gdb scripts useful for Chromium code.
|
|
There is a similar script in `thrid_party/blink/tools/gdb`, which came from
|
|
WebKit.
|
|
|
|
To include these pretty-printers with your gdb, put the following into
|
|
`~/.gdbinit`:
|
|
|
|
```python
|
|
python
|
|
import sys
|
|
sys.path.insert(0, "<path/to/chromium/src>/tools/gdb/")
|
|
import gdb_chrome
|
|
```
|
|
|
|
This will import Blink pretty-printers as well.
|
|
|
|
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
|
|
```
|
|
|
|
[More STL GDB macros](http://www.yolinux.com/TUTORIALS/src/dbinit_stl_views-1.01.txt)
|
|
|
|
### Graphical Debugging Aid for Chromium Views
|
|
|
|
The following link describes a tool that can be used on Linux, Windows and Mac under GDB.
|
|
|
|
[graphical_debugging_aid_chromium_views](graphical_debugging_aid_chromium_views.md)
|
|
|
|
### Faster startup
|
|
|
|
Use the `gdb-add-index` script (e.g.
|
|
`build/gdb-add-index out/Debug/browser_tests`)
|
|
|
|
Only makes sense if you run the binary multiple times or maybe if you use the
|
|
component build since most `.so` files won't require reindexing on a rebuild.
|
|
|
|
See
|
|
https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/gdb-add-index/chromium-dev/ELRuj1BDCL4/5Ki4LGx41CcJ
|
|
for more info.
|
|
|
|
You can improve GDB load time significantly at the cost of link time by
|
|
splitting symbols from the object files. In GN, set `use_debug_fission=false` in
|
|
your "gn args".
|
|
|
|
### Source level debug with -fdebug-compilation-dir
|
|
|
|
When you enable GN config `strip_absolute_paths_from_debug_symbols`, this is
|
|
enabled by default for goma on Linux build, you need to add following command
|
|
to your `~/.gdbinit` for source level debugging to load customized
|
|
[gdbinit](../tools/gdb/gdbinit) or copy the content of the file to your
|
|
`~/.gdbinit`.
|
|
|
|
```
|
|
source path/to/chromium/src/tools/gdb/gdbinit
|
|
```
|
|
|
|
## Core files
|
|
|
|
`ulimit -c unlimited` should cause all Chrome processes (run from that shell) to
|
|
dump cores, with the possible exception of some sandboxed processes.
|
|
|
|
Some sandboxed subprocesses might not dump cores unless you pass the
|
|
`--allow-sandbox-debugging` flag.
|
|
|
|
If the problem is a freeze rather than a crash, you may be able to trigger a
|
|
core-dump by sending SIGABRT to the relevant process:
|
|
|
|
kill -6 [process id]
|
|
|
|
## Breakpad minidump files
|
|
|
|
See [linux_minidump_to_core.md](linux_minidump_to_core.md)
|
|
|
|
## Running Tests
|
|
|
|
Many of our tests bring up windows on screen. This can be annoying (they steal
|
|
your focus) and hard to debug (they receive extra events as you mouse over them).
|
|
Instead, use `Xvfb` or `Xephyr` to run a nested X session to debug them, as
|
|
outlined on [layout_tests_linux.md](layout_tests_linux.md).
|
|
|
|
### Browser tests
|
|
|
|
By default the `browser_tests` forks a new browser for each test. To debug the
|
|
browser side of a single test, use a command like
|
|
|
|
```
|
|
gdb --args out/Debug/browser_tests --single_process --gtest_filter=MyTestName
|
|
```
|
|
|
|
**note the underscore in `single_process`** -- this makes the test harness and
|
|
browser process share the outermost process.
|
|
|
|
|
|
To debug a renderer process in this case, use the tips above about renderers.
|
|
|
|
### Layout tests
|
|
|
|
See [layout_tests_linux.md](layout_tests_linux.md) for some tips. In particular,
|
|
note that it's possible to debug a layout test via `ssh`ing to a Linux box; you
|
|
don't need anything on screen if you use `Xvfb`.
|
|
|
|
### UI tests
|
|
|
|
UI tests are run in forked browsers. Unlike browser tests, you cannot do any
|
|
single process tricks here to debug the browser. See below about
|
|
`BROWSER_WRAPPER`.
|
|
|
|
To pass flags to the browser, use a command line like
|
|
`--extra-chrome-flags="--foo --bar"`.
|
|
|
|
### Timeouts
|
|
|
|
UI tests have a confusing array of timeouts in place. (Pawel is working on
|
|
reducing the number of timeouts.) To disable them while you debug, set the
|
|
timeout flags to a large value:
|
|
|
|
* `--test-timeout=100000000`
|
|
* `--ui-test-action-timeout=100000000`
|
|
* `--ui-test-terminate-timeout=100000000`
|
|
|
|
### To replicate Window Manager setup on the bots
|
|
|
|
Chromium try bots and main waterfall's bots run tests under Xvfb&openbox
|
|
combination. Xvfb is an X11 server that redirects the graphical output to the
|
|
memory, and openbox is a simple window manager that is running on top of Xvfb.
|
|
The behavior of openbox is markedly different when it comes to focus management
|
|
and other window tasks, so test that runs fine locally may fail or be flaky on
|
|
try bots. To run the tests on a local machine as on a bot, follow these steps:
|
|
|
|
Make sure you have openbox:
|
|
|
|
apt-get install openbox
|
|
|
|
Start Xvfb and openbox on a particular display:
|
|
|
|
Xvfb :6.0 -screen 0 1280x1024x24 & DISPLAY=:6.0 openbox &
|
|
|
|
Run your tests with graphics output redirected to that display:
|
|
|
|
DISPLAY=:6.0 out/Debug/browser_tests --gtest_filter="MyBrowserTest.MyActivateWindowTest"
|
|
|
|
You can look at a snapshot of the output by:
|
|
|
|
xwd -display :6.0 -root | xwud
|
|
|
|
Alternatively, you can use testing/xvfb.py to set up your environment for you:
|
|
|
|
testing/xvfb.py out/Debug/browser_tests \
|
|
--gtest_filter="MyBrowserTest.MyActivateWindowTest"
|
|
|
|
### BROWSER_WRAPPER
|
|
|
|
You can also get the browser under a debugger by setting the `BROWSER_WRAPPER`
|
|
environment variable. (You can use this for `browser_tests` too, but see above
|
|
for discussion of a simpler way.)
|
|
|
|
BROWSER_WRAPPER='xterm -e gdb --args' out/Debug/browser_tests
|
|
|
|
### Replicating try bot Slowness
|
|
|
|
Try bots are pretty stressed, and can sometimes expose timing issues you can't
|
|
normally reproduce locally.
|
|
|
|
You can simulate this by shutting down all but one of the CPUs
|
|
(http://www.cyberciti.biz/faq/debian-rhel-centos-redhat-suse-hotplug-cpu/) and
|
|
running a CPU loading tool (e.g., http://www.devin.com/lookbusy/). Now run your
|
|
test. It will run slowly, but any flakiness found by the try bot should replicate
|
|
locally now - and often nearly 100% of the time.
|
|
|
|
## Logging
|
|
|
|
### Seeing all LOG(foo) messages
|
|
|
|
Default log level hides `LOG(INFO)`. Run with `--log-level=0` and
|
|
`--enable-logging=stderr` flags.
|
|
|
|
Newer versions of Chromium with VLOG may need --v=1 too. For more VLOG tips, see
|
|
[the chromium-dev thread](https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/dcd0cd7752b35de6?pli=1).
|
|
|
|
### Seeing IPC debug messages
|
|
|
|
Run with `CHROME_IPC_LOGGING=1` eg.
|
|
|
|
CHROME_IPC_LOGGING=1 out/Debug/chrome
|
|
|
|
or within gdb:
|
|
|
|
set environment CHROME_IPC_LOGGING 1
|
|
|
|
If some messages show as unknown, check if the list of IPC message headers in
|
|
[chrome/common/logging_chrome.cc](/chrome/common/logging_chrome.cc) is
|
|
up to date. In case this file reference goes out of date, try looking for usage
|
|
of macros like `IPC_MESSAGE_LOG_ENABLED` or `IPC_MESSAGE_MACROS_LOG_ENABLED`.
|
|
|
|
## Profiling
|
|
|
|
See
|
|
https://sites.google.com/a/chromium.org/dev/developers/profiling-chromium-and-webkit
|
|
and [Linux Profiling](linux_profiling.md).
|
|
|
|
## i18n
|
|
|
|
We obey your system locale. Try something like:
|
|
|
|
LANG=ja_JP.UTF-8 out/Debug/chrome
|
|
|
|
If this doesn't work, make sure that the `LANGUAGE`, `LC_ALL` and `LC_MESSAGE`
|
|
environment variables aren't set -- they have higher priority than LANG in the
|
|
order listed. Alternatively, just do this:
|
|
|
|
LANGUAGE=fr out/Debug/chrome
|
|
|
|
Note that because we use GTK, some locale data comes from the system -- for
|
|
example, file save boxes and whether the current language is considered RTL.
|
|
Without all the language data available, Chrome will use a mixture of your
|
|
system language and the language you run Chrome in.
|
|
|
|
Here's how to install the Arabic (ar) and Hebrew (he) language packs:
|
|
|
|
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.
|
|
|
|
On non-Debian systems, you need the `gtk30.mo` files. (Please update these docs
|
|
with the appropriate instructions if you know what they are.)
|
|
|
|
## Breakpad
|
|
|
|
See the last section of [Linux Crash Dumping](linux_crash_dumping.md); you
|
|
need to set a gyp variable and an environment variable for the crash dump tests
|
|
to work.
|
|
|
|
## Drag and Drop
|
|
|
|
If you break in a debugger during a drag, Chrome will have grabbed your mouse
|
|
and keyboard so you won't be able to interact with the debugger! To work around
|
|
this, run via `Xephyr`. Instructions for how to use `Xephyr` are on the
|
|
[Running layout tests on Linux](layout_tests_linux.md) page.
|
|
|
|
## Tracking Down Bugs
|
|
|
|
### Isolating Regressions
|
|
|
|
Old builds are archived here:
|
|
https://build.chromium.org/buildbot/snapshots/chromium-rel-linux/
|
|
(TODO: does not exist).
|
|
|
|
`tools/bisect-builds.py` in the tree automates bisecting through the archived
|
|
builds. Despite a computer science education, I am still amazed how quickly
|
|
binary search will find its target.
|
|
|
|
### Screen recording for bug reports
|
|
|
|
sudo apt-get install gtk-recordmydesktop
|
|
|
|
## Version-specific issues
|
|
|
|
### Google Chrome
|
|
|
|
Google Chrome binaries don't include symbols. Googlers can read where to get
|
|
symbols from
|
|
[the Google-internal wiki](http://wiki/Main/ChromeOfficialBuildLinux#The_Build_Archive).
|
|
|
|
### Ubuntu Chromium
|
|
|
|
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/Debugging
|
|
|
|
### Fedora's Chromium
|
|
|
|
Like Ubuntu, but direct users to
|
|
https://fedoraproject.org/wiki/TomCallaway/Chromium_Debug
|
|
|
|
### 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:
|
|
|
|
* pass `--sync` on the command line to make all X calls synchronous
|
|
* run chrome via [xtrace](http://xtrace.alioth.debian.org/)
|
|
* turn on IPC debugging (see above section)
|
|
|
|
### 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
|
|
[Running layout tests on Linux](layout_tests_linux.md) 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
|