android_webview
apps
ash
base
build
build_overrides
buildtools
cc
chrome
chromecast
chromeos
clank
codelabs
components
content
crypto
dbus
device
docs
accessibility
autofill
chromeos
design
enterprise
experiments
fuchsia
gpu
graphics
images
infra
intl
ios
linux
build_instructions.md
building_debug_gtk.md
cast_build_instructions.md
cert_management.md
chromium_arm.md
chromium_packages.md
crash_dumping.md
debugging.md
debugging_gtk.md
debugging_minidump.md
debugging_ssl.md
dependencies.md
dev_build_as_default_browser.md
development.md
eclipse_dev.md
graphics_pipeline.md
gtk_theme_integration.md
hw_video_decode.md
instrumented_libraries.md
minidump_to_core.md
ozone_drm.md
password_storage.md
pid_namespace_support.md
plugins.md
profiling.md
proxy_config.md
sandbox_ipc.md
suid_sandbox_development.md
sysroot.md
using_a_chroot.md
zygote.md
login
mac
media
memory
memory-infra
patterns
privacy
privacy_budget
process
security
speed
speed_metrics
standards
telemetry_extension
testing
transcripts
ui
updater
webapps
website
webui
workflow
DIR_METADATA
OWNERS
README.md
accessibility.md
ad_tagging.md
adding_to_third_party.md
android_accessing_cpp_enums_in_java.md
android_accessing_cpp_features_in_java.md
android_accessing_cpp_switches_in_java.md
android_build_instructions.md
android_cast_build_instructions.md
android_debugging_instructions.md
android_dynamic_feature_modules.md
android_emulator.md
android_isolated_splits.md
android_jni_ownership_best_practices.md
android_logging.md
android_native_libraries.md
android_studio.md
angle_in_chromium.md
api_keys.md
asan.md
atom.md
benchmark_performance_regressions.md
bfcache.md
bitmap_pipeline.md
branch_gardener.md
building_old_revisions.md
callback.md
ccache_mac.md
chrome_browser_design_principles.md
chrome_os_logging.md
chrome_settings.md
chromedriver_status.md
chromeos_build_instructions.md
chromeos_glossary.md
chromium_browser_vs_google_chrome.md
cipd_and_3pp.md
cl_respect.md
cl_tips.md
clang.md
clang_code_coverage_wrapper.md
clang_format.md
clang_gardening.md
clang_sheriffing.md
clang_static_analyzer.md
clang_tidy.md
clang_tool_refactoring.md
clangd.md
clion.md
closure_compilation.md
cocoa_tips_and_tricks.md
code_review_owners.md
code_reviews.md
commit_checklist.md
component_build.md
configuration.md
contributing.md
cq_fault_attribution.md
cr_respect.md
cr_user_manual.md
cross_platform_ui.md
cygwin_dll_remapping_failure.md
dangling_ptr.md
dangling_ptr_guide.md
dbus_mojo_connection_service.md
debugging_with_crash_keys.md
dependencies.md
deterministic_builds.md
disassemble_code.md
documentation_best_practices.md
documentation_guidelines.md
early-hints.md
eclipse.md
emacs.md
erc_irc.md
flag_expiry.md
flag_guarding_guidelines.md
flag_ownership.md
frame_trees.md
gardener.md
gcs_dependencies.md
gdbinit.md
gerrit_guide.md
get_the_code.md
git_cookbook.md
git_submodules.md
git_tips.md
google_chrome_branded_builds.md
google_play_services.md
graphical_debugging_aid_chromium_views.md
gwp_asan.md
history_manipulation_intervention.md
how_cc_works.md
how_to_add_your_feature_flag.md
how_to_extend_web_test_framework.md
idn.md
initialize_blink_features.md
inlined_stack_traces.md
installation_at_vmware.md
ios_build_instructions.md
ios_infra.md
ios_voiceover.md
kiosk_mode.md
life_of_a_frame.md
lldbinit.md
mac_arm64.md
mac_build_instructions.md
mac_lld.md
modifying_session_history_serialization.md
modules.md
mojo_and_services.md
mojo_ipc_conversion.md
mojo_testing.md
native_relocations.md
navbar.md
navigation-request-navigation-state.gv
navigation-request-navigation-state.png
navigation.md
navigation_concepts.md
network_traffic_annotations.md
no_sources_assignment_filter.md
orderfile.md
origin_trials_integration.md
ozone_overview.md
parsing_test_results.md
pgo.md
piranha_plant.md
process_model_and_site_isolation.md
profiling.md
profiling_content_shell_on_android.md
proxy_auto_config.md
qtcreator.md
release_branch_guidance.md
render-frame-host-lifecycle-state.gv
render-frame-host-lifecycle-state.png
render_document.md
rust-ffi.md
rust.md
seccomp_sandbox_crash_dumping.md
servicification.md
session_history.md
sheriff.md
shutdown.md
special_case_urls.md
static_initializers.md
sublime_ide.md
system_hardening_features.md
tab_helpers.md
threading_and_tasks.md
threading_and_tasks_faq.md
threading_and_tasks_testing.md
toolchain_support.md
tour_of_luci_ui.md
tpm_quick_ref.md
translation_screenshots.md
unretained_dangling_ptr_guide.md
unsafe_buffers.md
updating_clang.md
updating_clang_format_binaries.md
use_counter_wiki.md
useful_urls.md
user_data_dir.md
user_data_storage.md
user_handle_mapping.md
vanilla_msysgit_workflow.md
vscode.md
vscode_python.md
webview_policies.md
win_cross.md
win_order_files.md
windows_build_instructions.md
windows_native_window_occlusion_tracking.md
windows_pwa_integration.md
windows_shortcut_and_taskbar_handling.md
windows_split_dll.md
windows_virtual_desktop_handling.md
wmax_tokens.md
working_remotely_with_android.md
writing_clang_plugins.md
extensions
fuchsia_web
gin
google_apis
gpu
headless
infra
internal
ios
ios_internal
ipc
media
mojo
native_client
native_client_sdk
net
pdf
ppapi
printing
remoting
rlz
sandbox
services
signing_keys
skia
sql
storage
styleguide
testing
third_party
tools
ui
url
v8
webkit
.clang-format
.clang-tidy
.clangd
.git-blame-ignore-revs
.gitallowed
.gitattributes
.gitignore
.gitmodules
.gn
.mailmap
.rustfmt.toml
.vpython3
.yapfignore
ATL_OWNERS
AUTHORS
BUILD.gn
CODE_OF_CONDUCT.md
CPPLINT.cfg
CRYPTO_OWNERS
DEPS
DIR_METADATA
LICENSE
LICENSE.chromium_os
OWNERS
PRESUBMIT.py
PRESUBMIT_test.py
PRESUBMIT_test_mocks.py
README.md
WATCHLISTS
codereview.settings

Change-Id: I6ecc111cdf78b4f2ab385674dd3e036adcdd5df0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4566687 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Ben Wagner <bungeman@chromium.org> Cr-Commit-Position: refs/heads/main@{#1164352}
185 lines
8.9 KiB
Markdown
185 lines
8.9 KiB
Markdown
# Linux Minidump Code Lab
|
|
|
|
[TOC]
|
|
|
|
## About Minidumps
|
|
|
|
Minidump is a file format for storing parts of a program's state for later
|
|
inspection. [Microsoft's
|
|
Documentation](https://docs.microsoft.com/en-us/windows/desktop/api/minidumpapiset/)
|
|
defines the format though the [Rust
|
|
Documentation](https://docs.rs/minidump/latest/minidump/format/index.html)
|
|
is sometimes easier to navigate. The minidump implementation and tools used by
|
|
Chrome are
|
|
[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/refs/heads/main/README.md)
|
|
and
|
|
[Crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/main/README.md).
|
|
However, the tools of interest here are from the Breakpad project.
|
|
|
|
## Create a Minidump
|
|
|
|
When Chrome crashes it writes out a minidump file. The minidump file is written
|
|
under the application product directory. On Linux this is
|
|
`<XDG_CONFIG_HOME>/<app-name>/Crash Reports`. The default for `XDG_CONFIG_HOME`
|
|
is `~.config`. Common `<app-name>`s are `chromium`, `google-chrome`,
|
|
`google-chrome-beta`, and `google-chrome-unstable`. A typical example is
|
|
`~.config/google-chrome/Crash Reports`. When a minidump is uploaded it will be
|
|
moved between the `new`, `pending`, and `completed` subdirectories. The minidump
|
|
file is named something like `<uuid>.dmp`. If the minidump is uploaded to the
|
|
crash reporting system, the `<uuid>.meta` file will contain the crash report id.
|
|
Those with access can find the uploaded report at `go/crash/<report-id>`, where
|
|
the minidump file will be available with a name like
|
|
`upload_file_minidump-<report-id>.dmp`.
|
|
|
|
To create a minidump, you can use a local build of Chromium or a release
|
|
version of Chrome. Run the browser with the environment variable
|
|
`CHROME_HEADLESS=1`, which enables crash dumping but prevents crash dumps from
|
|
being uploaded and deleted. Something like `$ env CHROME_HEADLESS=1
|
|
./out/debug/chrome-wrapper` or `$ env CHROME_HEADLESS=1
|
|
/opt/google/chrome/google-chrome`. Navigate to `chrome://crash` to trigger a
|
|
crash in the renderer process or reproduce your current crash bug. A crash dump
|
|
file should appear in the `Crash Reports` directory.
|
|
|
|
## Inspect the Minidump
|
|
|
|
To get an idea about what is in a minidump file, install the Okteta hex editor
|
|
and add the [Minidump Structure
|
|
Definition](https://github.com/bungeman/structures/tree/main/okteta-minidump).
|
|
Open the minidump previously created and explore the information it contains.
|
|
|
|
One quirk to notice is that there is a `ThreadListStream` which contains
|
|
`MINIDUMP_THREAD`s which contain a `MINIDUMP_THREAD_CONTEXT` and an
|
|
`ExceptionStream` which also contains a `MINIDUMP_THREAD_CONTEXT`. The thread
|
|
list contains the thread contexts as they existed when the crash reporter was
|
|
running. The exception's thread context is the state of the crashing thread at
|
|
the time that it crashed, which is generally the most interesting thread
|
|
context. When using the Breakpad tools for Linux (like `minidump_stackwalk` and
|
|
`minidump-2-core`) the thread context from the exception record is used in place
|
|
of the thread context associated with the corresponding thread.
|
|
|
|
Each `MINIDUMP_THREAD` contains a `StackMemoryRva` which is a reference to to a
|
|
copy of the stack on that thread at the time the crash handler was running.
|
|
Parsing a stack usefully requires additional debug information.
|
|
`minidump_stackwalk` or a debugger may be used to parse the stack memory to
|
|
create a usable trace.
|
|
|
|
## Get the Tools
|
|
|
|
From a Chromium checkout `ninja -C out/release minidump-2-core
|
|
minidump_stackwalk dump_syms`. From a [Breakpad
|
|
checkout](https://chromium.googlesource.com/breakpad/breakpad/) `make`. It can
|
|
be useful to use Breakpad directly on machines where one does not already have
|
|
a Chromium checkout.
|
|
|
|
When working at this level, one will also want to have `readelf` and
|
|
`objdump` available, which are available from most distributions.
|
|
|
|
## Get Executables and Symbols
|
|
|
|
In addition to the minidump, you will need the exact executables of Chromium or
|
|
Chrome which produced the minidump and those executable's symbols. If the
|
|
minidump was created locally, you already have the executables. Symbols for
|
|
Google Chrome's official builds are available from
|
|
`https://edgedl.me.gvt1.com/chrome/linux/symbols/google-chrome-debug-info-linux64-${VERSION}.zip`
|
|
where `${VERSION}` is any version of Google Chrome that has recently been served
|
|
to Stable, Beta, or Unstable (Dev) channels on Linux, like `114.0.5696.0`. Those
|
|
with access can find both executables and symbols for unreleased builds at
|
|
`go/chrome-symbols`.
|
|
|
|
For symbols outside of Chrome (like when the crash is happening in a shared
|
|
library) then symbols for the files of interest must be found. If the minidump
|
|
was created locally then install the symbol packages from your distribution. If
|
|
not, you will need to track down the exact symbol files, which can be an
|
|
interesting exercise. For some distributions using the
|
|
[debuginfod](https://sourceware.org/elfutils/Debuginfod.html) system can be
|
|
quite helpful.
|
|
|
|
To ensure the correct binaries and debug symbols are used, the minidump contains
|
|
the build-id for each loaded module in the `ModuleListStream` in the
|
|
`CvRecordRva`'s `Signature`. This build-id is matched against a note
|
|
section of type `NT_GNU_BUILD_ID`, usually named `.note.gnu.build-id` in the
|
|
executable and symbol files. This note can be inspected with `readelf -n
|
|
<file>` like `readelf -n chrome` or `readelf -n chrome.debug` and looking for
|
|
the `.note.gnu.build-id` section. `readelf` reports the `Build ID` as the flat
|
|
bytes in the note, but Breakpad binaries like `stackwalk_minidimp` and
|
|
`dump_syms` will report and expect this truncated to a formatted Type 2 GUID
|
|
(without dashes). This means `readelf` will output a `<build-id>` like
|
|
33221100554477668899AABBCCDDEEFFXXXXXXXX but crashpad binaries will expect and
|
|
report this as a `<build-uuid>` of 00112233445566778899AABBCCDDEEFF.
|
|
|
|
The `.gnu_debuglink` section states which debug symbol file to use with a
|
|
striped binary. For example `readelf --string-dump=.gnu_debuglink chrome`
|
|
produces `chrome.debug`. This can be helpful to know for libraries with
|
|
interesting debug symbol setup, like libc.so.6.
|
|
|
|
## Create Symbolized Stack
|
|
|
|
Given a minidump with the name `mini.dmp`
|
|
|
|
`minidump_stackwalk mini.dmp > mini.stackwalk.nosym`
|
|
|
|
This will produce a mostly unsymbolized summary of the crash. To symbolize, look
|
|
toward the bottom of the output for `WARNING: No symbols, <file>, <build-uuid>`.
|
|
For each `<file>` which is of interest, `mkdir -p symbols/<file>/<build-uuid>` then
|
|
`dump_syms <file> <directory-with-file.debug> >
|
|
symbols/<file>/<build-uuid>/<file>.sym`. Ensure this output `<file>.sym`
|
|
contains the expected `<build-uuid>`. Then re-run `minidump_stackwalk` but
|
|
with the symbols directory, like `minidump_stackwalk mini.dmp symbols/ >
|
|
mini.stackwalk`.
|
|
|
|
The output of `minidump_stackwalk` is often quite useful and enough to track
|
|
down many issues. However, it does not fully use all of the information from
|
|
DWARF, so it is possible sometimes to get much better stack traces from a full
|
|
debugger like gdb. This is particularly true when functions have been
|
|
aggressively inlined.
|
|
|
|
## Create Core File
|
|
|
|
`minidump-2-core mini.dmp > mini.core`
|
|
|
|
## Loading into GDB
|
|
|
|
This works best if the binaries, symbols, and core files are all in different
|
|
directories to prevent gdb from automatically loading them into the wrong
|
|
locations. This is also generally necessary when using a system installed
|
|
version of Chrome. For full details see [the gdb
|
|
manual](https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html).
|
|
The easiest way is to rename and move the .debug files to a directory structure
|
|
like `<debugdir>/debug/.build-id/nn/nnnnnnnn.debug` where `nn` are the first
|
|
two hex characters of the `build-id`, and `nnnnnnnn` are the rest of the hex
|
|
characters of the `build-id`. Note that this `build-id` is exactly what is
|
|
reported by `readelf -n <binary> | grep "Build ID"` and not the `build-uuid`
|
|
used by Breakpad. Then in gdb use `show debug-file-directory` to get the
|
|
`<previous-directories>` and `set debug-file-directory
|
|
<previous-directories>:<debugdir>/debug`.
|
|
|
|
The `offset`s used here are the offsets of the corresponding module from the
|
|
output of `minidump_stackwalk` or (equivalently) the value of
|
|
`ModuleListStream::Modules[]::BaseOfImage` from the minidump file (which can be
|
|
read with the structure definition).
|
|
|
|
```
|
|
$ gdb
|
|
(gdb) file <executable>
|
|
(gdb) show debug-file-directory
|
|
<previous directories>
|
|
(gdb) set debug-file-directory <previous directories>:<debugdir>/debug
|
|
(gdb) symbol-file <executable> -o <executable-offset>
|
|
(gdb) core-file <mini.core>
|
|
```
|
|
|
|
Running the commands in this order avoids needing to load the symbols twice and
|
|
maps the `<executable>` to the expected location.
|
|
|
|
To add an additional shared library it is possible to
|
|
`(gdb) add-symbol-file <shared-library> -o <shared-library-offset>`
|
|
|
|
Source paths in Chrome builds are relative to the `out/<build>` directory. If you
|
|
have a Chromium checkout at or around when the Chrome build was created, it can
|
|
be added to the debugger search path, like
|
|
|
|
```
|
|
(gdb) directory <path-to-chromium>/chromium/src/out/<build>/
|
|
```
|
|
|