A -dbg package support
It is quite common for debian packages to have a split package with debug info. The main package contains stripped binaries, but there's a package with the -dbg suffix that contains extracted debug info (before the stripping), placed under /usr/src/debug.
Would it be possible to support this?
I think it might be doable with #61 ?
I don't think so. That one talks about bundling a different binary into the -dbg, which is wrong. The idea with the -dbg package is, you can install it after the fact (eg. when you have a core file) and it works. These don't contain the binary itself, only the debug symbols for the already installed binary. The -dbg package doesn't collide with the base one, it contains additional files.
But the variants support should be able to use different assets configuration for -dbg variant, so you can omit the binary and put debug symbols in it instead?
That sounds like a lot of manual configuration for something that should basically mirror the list of binaries, but yes, maybe it cold be done. However, something still needs to produce the debug symbols by extracting them before stripping.
Right, there are lots of improvements can be done.
How do you usually make the debug variant?
- Which tools do you use to extract debug info to a separate file?
- How is that structured in the debian package? (where is the debug info copied to after install)
- What metadata does the debian control file need to associate it with non-debug package?
Which tools do you use to extract debug info to a separate file?
Usually, the debian helpers do all the magic. However, when I tried to search how to do it, strip seems to be the right way, especially the description in --only-keep-debug flag:
1.<Link the executable as normal. Assuming that is is called>
"foo" then...
1.<Run "objcopy --only-keep-debug foo foo.dbg" to>
create a file containing the debugging info.
1.<Run "objcopy --strip-debug foo" to create a>
stripped executable.
1.<Run "objcopy --add-gnu-debuglink=foo.dbg foo">
to add a link to the debugging info into the stripped executable.
(I think the adding of link should point to the to-be installed path)
It also says placing the full executable instead of foo.dbg would work. Gdb should then be able to follow the link and load the mentioned file as its debug info.
How is that structured in the debian package? (where is the debug info copied to after install)
That depends a bit on the version. On the newest debian, it looks like this (this is from thunderbird-dbg, as an example). I'm not entirely sure how the hashes are computed.:
./
./usr/
./usr/lib/
./usr/lib/debug/
./usr/lib/debug/.build-id/
./usr/lib/debug/.build-id/0d/
./usr/lib/debug/.build-id/0d/97154efe828e447321ff8e49a421d6d7f2f061.debug
./usr/lib/debug/.build-id/16/
./usr/lib/debug/.build-id/16/0d9f5fafc986fda383bfb2d9309c47b101dea3.debug
./usr/lib/debug/.build-id/16/3744601daf42dfea540558de9afa8131064303.debug
./usr/lib/debug/.build-id/1a/
./usr/lib/debug/.build-id/1a/af5330e45d71530a4c11aeab653b61578c13d4.debug
./usr/lib/debug/.build-id/20/
./usr/lib/debug/.build-id/20/23ea33ffe490de4bd827eeb24e40d181cdc625.debug
./usr/lib/debug/.build-id/26/
./usr/lib/debug/.build-id/26/03bcfd0a7def39b19fe4b6a95777ed403d2988.debug
./usr/lib/debug/.build-id/2f/
./usr/lib/debug/.build-id/2f/c851dffa230c06249b54d0d6f44c2222264b7a.debug
./usr/lib/debug/.build-id/33/
./usr/lib/debug/.build-id/33/69fa55ebc134fb64764973af53110d326ddf6d.debug
./usr/lib/debug/.build-id/33/be14c5f83bba86d9f74e25119bdf0af430dcc8.debug
./usr/lib/debug/.build-id/38/
./usr/lib/debug/.build-id/38/f40862cb5b37ceb03c393d6bc30fb3fa43faf7.debug
./usr/lib/debug/.build-id/3a/
./usr/lib/debug/.build-id/3a/02ad89cb04a59792a273e59a4f47d31a97fd61.debug
./usr/lib/debug/.build-id/3f/
./usr/lib/debug/.build-id/3f/6ccdc92afc14c892f4ecf0c72beda8fe71d32a.debug
./usr/lib/debug/.build-id/47/
./usr/lib/debug/.build-id/47/2876795717a908d1eb64cea782cf1b7a1240ae.debug
./usr/lib/debug/.build-id/54/
./usr/lib/debug/.build-id/54/e0ccc2d162d74a8ff97afeebc590e7dd3c2db2.debug
./usr/lib/debug/.build-id/8b/
./usr/lib/debug/.build-id/8b/f055799eae7d13c70b2fa6827713c8543cbdd6.debug
./usr/lib/debug/.build-id/97/
./usr/lib/debug/.build-id/97/8486b48a92a9180211377d3e2d0a513ed71a8e.debug
./usr/lib/debug/.build-id/a6/
./usr/lib/debug/.build-id/a6/e9a4bb8ee97c8b2f7fdc54181c715a5e7049d7.debug
./usr/lib/debug/.build-id/ba/
./usr/lib/debug/.build-id/ba/17598148dbfef06cdc2720b800f564120f5ecf.debug
./usr/lib/debug/.build-id/cc/
./usr/lib/debug/.build-id/cc/6ebe257c3d8cb32a092b616cddc7c279d47347.debug
./usr/lib/debug/.build-id/d6/
./usr/lib/debug/.build-id/d6/ccde2bb3831a03a766f012b594e1579586870b.debug
./usr/lib/debug/.build-id/f1/
./usr/lib/debug/.build-id/f1/6dacb7f63c9a95164c21b17737b8ca556607e5.debug
./usr/lib/debug/.build-id/fe/
./usr/lib/debug/.build-id/fe/0e4d6e7720699ea63c86e07f0ea333315dc04f.debug
./usr/share/
./usr/share/doc/
./usr/share/doc/thunderbird-dbg/
./usr/share/doc/thunderbird-dbg/changelog.Debian.gz
./usr/share/doc/thunderbird-dbg/copyright
./usr/share/lintian/
./usr/share/lintian/overrides/
./usr/share/lintian/overrides/thunderbird-dbg
The alternative way I've seen is to put the path under /usr/lib/debug ‒ if I have debug info for /usr/bin/foo, I'd place it as /usr/lib/debug/usr/bin/foo.debug. I think that would be better in the case of this „external“ tool and it was used previously.
What metadata does the debian control file need to associate it with non-debug package?
AFAIK it just depends on the non-debug one, otherwise it has the same descriptions, etc. Once again the control file from the thunderbird-dbg:
Package: thunderbird-dbg
Source: thunderbird
Version: 1:52.7.0-1~deb9u1
Architecture: amd64
Maintainer: Carsten Schoenert <[email protected]>
Installed-Size: 373194
Depends: thunderbird (= 1:52.7.0-1~deb9u1)
Breaks: icedove-dbg (<< 1:45.6.0-2.1~)
Replaces: icedove-dbg (<< 1:45.6.0-2.1~)
Provides: icedove-dbg
Section: debug
Priority: extra
Multi-Arch: same
Homepage: http://www.mozilla.org/thunderbird/
Description: Debug Symbols for Thunderbird
Thunderbird is an mail client suitable for free distribution. The goal of
Thunderbird is to produce a cross platform stand-alone mail application using
the XUL user interface language.
It supports different mail accounts, no matter of the used protocol like
POP(s) or IMAP(s), has an integrated learning Spam filter, and offers easy
organization of mails with tagging and virtual folders. Also, more features
can be added by installing extensions.
.
This package contains the debug symbols for Thunderbird. Install this package
if you need to debug such a program or if you need a useful backtrace of a
crash.
Build-Ids: 0d97154efe828e447321ff8e49a421d6d7f2f061 160d9f5fafc986fda383bfb2d9309c47b101dea3 163744601daf42dfea540558de9afa8131064303 1aaf5330e45d71530a4c11aeab653b61578c13d4 2023ea33ffe490de4bd827eeb24e40d181cdc625 2603bcfd0a7def39b19fe4b6a95777ed403d2988 2fc851dffa230c06249b54d0d6f44c2222264b7a 3369fa55ebc134fb64764973af53110d326ddf6d 33be14c5f83bba86d9f74e25119bdf0af430dcc8 38f40862cb5b37ceb03c393d6bc30fb3fa43faf7 3a02ad89cb04a59792a273e59a4f47d31a97fd61 3f6ccdc92afc14c892f4ecf0c72beda8fe71d32a 472876795717a908d1eb64cea782cf1b7a1240ae 54e0ccc2d162d74a8ff97afeebc590e7dd3c2db2 978486b48a92a9180211377d3e2d0a513ed71a8e a6e9a4bb8ee97c8b2f7fdc54181c715a5e7049d7 ba17598148dbfef06cdc2720b800f564120f5ecf cc6ebe257c3d8cb32a092b616cddc7c279d47347 d6ccde2bb3831a03a766f012b594e1579586870b f16dacb7f63c9a95164c21b17737b8ca556607e5 fe0e4d6e7720699ea63c86e07f0ea333315dc04f
In a sense, it is a mostly unrelated package (just with the dependency), only with the -dbg suffix convention, so the user can install it when needed.
In general it's best to create Debian source packages (.dsc) rather than binary .debs directly. debcargo is the official Debian crate-to-package converter we're using which takes this approach, and uses debhelper to automatically create -dbgsym packages like is wanted here.
$ ls -gG *dbgsym*.deb
-rw-rw-r-- 1 119152 Jun 20 02:01 aho-corasick-dbgsym_0.6.4-1_amd64.deb
-rw-rw-r-- 1 20046152 Jun 20 03:41 cargo-dbgsym_0.27.0-1_amd64.deb
-rw-rw-r-- 1 51948 Jun 20 02:03 cc-dbgsym_1.0.17-1_amd64.deb
-rw-rw-r-- 1 553628 Jun 20 02:40 crossbeam-dbgsym_0.3.2-1_amd64.deb
-rw-rw-r-- 1 19122516 Jun 20 03:47 debcargo-dbgsym_2.1.0-1_amd64.deb
-rw-rw-r-- 1 206668 Jun 20 02:04 error-chain-dbgsym_0.11.0-1_amd64.deb
-rw-rw-r-- 1 2131544 Jun 20 03:08 exa-dbgsym_0.8.0-1_amd64.deb
-rw-rw-r-- 1 16884200 Jun 20 02:49 mdbook-dbgsym_0.1.7-1_amd64.deb
-rw-rw-r-- 1 68188 Jun 20 02:29 open-dbgsym_1.2.1-1_amd64.deb
-rw-rw-r-- 1 622464 Jun 20 02:27 pulldown-cmark-dbgsym_0.1.2-1_amd64.deb
-rw-rw-r-- 1 8148640 Jun 20 03:15 ripgrep-dbgsym_0.8.1-1_amd64.deb
-rw-rw-r-- 1 18072 Jun 20 02:00 rustc-demangle-dbgsym_0.1.8-1_amd64.deb
$ dpkg -c cargo-dbgsym_0.27.0-1_amd64.deb
drwxr-xr-x root/root 0 2018-06-20 01:43 ./
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/lib/
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/lib/debug/
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/lib/debug/.build-id/
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/lib/debug/.build-id/33/
-rw-r--r-- root/root 21408376 2018-06-20 01:43 ./usr/lib/debug/.build-id/33/122f88ca1ff49fb0eb16e8806eca20c1787cea.debug
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/share/
drwxr-xr-x root/root 0 2018-06-20 01:43 ./usr/share/doc/
lrwxrwxrwx root/root 0 2018-06-20 01:43 ./usr/share/doc/cargo-dbgsym -> cargo
$ dpkg -I cargo-dbgsym_0.27.0-1_amd64.deb
new Debian package, version 2.0.
size 20046152 bytes: control archive=532 bytes.
362 bytes, 12 lines control
106 bytes, 1 lines md5sums
Package: cargo-dbgsym
Source: rust-cargo
Version: 0.27.0-1
Auto-Built-Package: debug-symbols
Architecture: amd64
Maintainer: Rust Maintainers <[email protected]>
Installed-Size: 20917
Depends: cargo (= 0.27.0-1)
Section: debug
Priority: optional
Description: debug symbols for cargo
Build-Ids: 33122f88ca1ff49fb0eb16e8806eca20c1787cea
@vorner
I'm not entirely sure how the hashes are computed.:
That hash is a Build ID(sha1 on some info in the ELF header that identifies that specific build) that the compiler calculates and stores inside the binary. This hash is not guaranteed to be generated(the compiler needs to be compiled with that option enabled - distros usually have the feature enabled while "generic package managers" like Habitat, Brew, etc... don't have it[at least, at the moment]...).
Sentry has a good library(I use it for one of my own projects) that can get that Build ID in a way that works with binaries compiled for different architectures: https://docs.rs/symbolic-debuginfo/6.1.3/symbolic_debuginfo/elf/struct.ElfObject.html#method.code_id
GDB automatically searches for the build_id when debug info is not found. You can split that hash into different directories to speed up the lookup of the debug info.
One advantage here would be that you can store i386 and x86_64 debug_info for the same library, instead of having a single conflicting: /usr/lib/debug/some_library.debug.
Edit: Code snippet(without error handling), if it helps:
// Read the contents of that input file
let buffer = {
let mut buf = Vec::new();
let mut file = File::open(&input_path).unwrap();
file.read_to_end(&mut buf).unwrap();
buf
};
// Check that the file could contain an ELF object
if ! symbolic_debuginfo::elf::ElfObject::test(&buffer) {
eprintln!("\"{}\" is not an ELF file(binary file). Please pass a binary file.", input_path);
std::process::exit(1);
}
// Parse the ELF object to see that it actually contains debug info, before splitting it
let elf_object = match symbolic_debuginfo::elf::ElfObject::parse(&buffer) {
Ok(elf) => elf,
Err(_) => {
eprintln!("Could not parse the ELF header. Is this a binary file?");
std::process::exit(1);
}
};
// Get the "build_id"
let build_id = if elf_object.has_debug_info() {
elf_object.code_id().unwrap()
} else {
eprintln!("\"{}\" does not have debug info", input_path);
std::process::exit(1);
};