Codebase list debian-goodies / debian/0.84 find-dbgsym-packages
debian/0.84

Tree @debian/0.84 (Download .tar.gz)

find-dbgsym-packages @debian/0.84

9b50849
 
 
 
 
edcd9d9
 
 
 
9b50849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d40e3a7
0c68097
9b50849
 
 
5a28782
9b50849
 
 
4dd472b
 
9b50849
73cd2e2
9b50849
 
 
 
 
9a82dbc
9b50849
 
 
b369493
9b50849
4dd472b
9b50849
 
 
b369493
 
54c3b51
b369493
9b50849
54c3b51
9b50849
 
 
 
 
 
 
73cd2e2
 
 
 
 
 
 
 
9b50849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73cd2e2
db8dbef
 
9b50849
 
 
db8dbef
9b50849
db8dbef
9b50849
db8dbef
9b50849
db8dbef
73cd2e2
db8dbef
 
9b50849
b369493
 
9a82dbc
21a4a82
73cd2e2
3877ed3
 
 
21a4a82
9b50849
 
 
54c3b51
9b50849
 
 
 
 
 
b369493
 
 
 
73cd2e2
 
 
b369493
9b50849
54c3b51
9b50849
 
 
 
 
9a82dbc
 
 
 
 
 
 
1eb5e96
9a82dbc
 
 
 
 
 
54c3b51
9a82dbc
 
 
 
 
 
 
 
 
0c68097
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a82dbc
 
 
 
 
 
4dd472b
9a82dbc
 
 
 
 
 
 
 
 
 
 
 
 
 
9b50849
 
 
e2edf26
9b50849
 
 
 
 
 
 
e2edf26
9b50849
 
 
 
 
 
 
 
 
 
d40e3a7
9b50849
8956a37
9b50849
 
 
b369493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54c3b51
b369493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d40e3a7
 
54c3b51
b369493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b50849
 
 
7c49e86
9b50849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#!/usr/bin/perl

# Get list of debug symbol packages relevant for a core file or ELF
# program/library.
#
# Copyright (C) 2017      Stefan Fritsch <sf@debian.org>
# Copyright (C) 2017      Paul Wise <pabs@debian.org>
# Copyright (C) 2017-2018 Axel Beckert <abe@debian.org>
# Copyright (C) 2018      Jakub Wilk <jwilk@jwilk.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

use strict;
use warnings FATAL => 'all';
use autodie qw(:all);
use v5.14;
use IPC::System::Simple qw(capturex $EXITVAL);
use File::Which;

$ENV{LC_ALL} = 'C';

if (scalar @ARGV == 0 or $ARGV[0] eq '--help' or $ARGV[0] eq '-h') {
    usage();
}

my $vdso_regexp = qr/^linux-(gate|vdso\d*)[.]so[.]/;

my %pkgs;
my @out_of_date_files;
foreach my $arg (@ARGV) {
    my %build_ids;
    if ($arg =~ /^\d+$/) {
        %build_ids = get_build_ids_from_pid($arg);
    } else {
        %build_ids = get_build_ids_from_file($arg);
    }

    foreach my $id (keys %build_ids) {
        my ($path, $name) = @{$build_ids{$id}};

        next if $name =~ $vdso_regexp;

        my @p = get_debs_from_id($id);
        if (scalar @p == 0) {
            @p = get_debs_from_path($path);
            if (scalar @p == 0) {
                warn "W: Cannot find debug package for $name ($id)\n";
            }
        } elsif (scalar @p > 1) {
            warn "W: Multiple packages for $name ($id): @p\n";
        }
        foreach my $p (@p) {
            $pkgs{$p} = 1;
        }
    }
}

if (@out_of_date_files) {
    warn
        "W: The following files were reported by eu-unstrip as \"deleted\":\n".
        "W:    ".join("\nW:    ", @out_of_date_files)."\n".
        "W: If $0 reports already installed dbgsym packages as necessary,\n".
        "W: they are not at the expected (usually older) package version.\n";
}

say join(" ", sort keys %pkgs);

exit 0;

#### sub routines ####

sub parse_eu_unstrip
{
    my ($output) = @_;

    my %ids;

    foreach my $line (split(/\n/, $output)) {
        # 0x7fa9b8017000+0x39e9a0 79450f6e36287865d093ea209b85a222209925ff@0x7fa9b8017280 /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/debug/.build-id/79/450f6e36287865d093ea209b85a222209925ff.debug libc.so.6
        # 0x7f7f7235e000+0x17000 - /usr/share/locale/de/LC_MESSAGES/bash.mo - /usr/share/locale/de/LC_MESSAGES/bash.mo
        # 0x7ffd4098a000+0x2000 de7dac2df9f596f46fa94a387858ef25170603ec@0x7ffd4098a7d0 . - [vdso: 1740]
        # 0x7f37090fb000+0x2a000 dc5cb16f5e644116cac64a4c3f5da4d081b81a4f@0x7f37090fb248 - - /lib/x86_64-linux-gnu/ld-2.27.so (deleted)
        if ($line =~ m{
                      ^(?: 0 | 0x[[:xdigit:]]+ )
                      [+]
                      0x[[:xdigit:]]+
                      \s+
                      ( [[:xdigit:]]{40} [@] 0x[[:xdigit:]]+ | - )
                      \s+
                      ( \S+ )
                      \s+
                      ( \S+ )
                      \s+
                      (?: ( \S+ ) | ( \[vdso: \s+ \d+\] ) )?
                      ( \s+ \(deleted\) )?
                      $
                      }ix) {
            my $id = $1;
            my $path = $2;
            my $debug = $3;
            my $name = $4 // $path;
            my $vdso = $5;
            my $deleted = $6;
            if ($debug ne '-') {
                next;
            }
            if (defined $vdso) {
                next;
            }
            if ($id eq '-') {
                warn "W: No build-ID for $name\n";
                next;
            } elsif ($id =~ /^([[:xdigit:]]{40})[@]/) {
                $id = $1;
            } else {
                die "BUG: id='$id'";
            }
            if ($path eq '-' || $path eq '.') {
                $path = $name;
                $path =~ s{ \(deleted\)$}{};
            }
            if (defined $deleted) {
                push(@out_of_date_files, $path);
            }
            $ids{$id} = [$path, $name];
        } else {
            warn "W: Cannot parse eu-unstrip output: '$line'\n";
        }
    }
    return (%ids);
}

sub get_files_from_elf
{
    my ($filename) = @_;
    my @libs = ($filename);
    my $output = capturex(qw(ldd --), $filename);

    foreach my $line (split(/\n/, $output)) {
        chomp $line;
        my ($name, $path);
        if ($line =~ /^\t.+ => (.+) \(0x[0-9a-f]+\)$/) {
            push @libs, $1;
        } elsif ($line =~ /^\t(.+) \(0x[0-9a-f]+\)$/) {
            push @libs, $1;
        } else {
            warn "W: Cannot parse ldd output: '$line'\n";
        }
    }

    return @libs;
}

sub get_build_ids_from_file
{
    my ($filename) = @_;
    if ($filename !~ m(/) and not -f $filename) {
        my $oldfilename = $filename;
        $filename = which($filename);
        if (defined($filename)) {
            warn "I: ./$oldfilename not found, using $filename instead\n";
        } else {
            warn "W: ./$oldfilename not found ".
                "and no '$oldfilename' found in path either, skipping\n";
            return qw();
        }
    }

    unless (-f $filename) {
            warn "W: $filename not found, skipping\n";
            return qw();
    }

    if (is_core_file($filename)) {
        return get_build_ids_from_core($filename);
    } else {
        my @filenames = get_files_from_elf($filename);
        my %build_ids;
        foreach my $filename (@filenames) {
            next if $filename =~ $vdso_regexp;
            %build_ids = (%build_ids, get_build_ids_from_elf($filename));
        }
        return %build_ids;
    }
}

sub get_build_ids_from_elf
{
    my ($filename) = @_;
    my $output = capturex(qw(eu-unstrip --list-only --executable), $filename);

    return parse_eu_unstrip($output);
}

sub get_build_ids_from_core
{
    my ($filename) = @_;
    my $output = capturex(qw(eu-unstrip --list-only --core), $filename);

    return parse_eu_unstrip($output);
}

sub get_build_ids_from_pid
{
    my ($pid) = @_;
    my $output = capturex(qw(eu-unstrip --list-only --pid), $pid);
    chomp $output;

    return parse_eu_unstrip($output);
}

sub get_debs_from_id
{
    my ($id) = @_;

    my $output;
    $output = capturex([0, 1], qw(grep-aptavail --no-field-names --show-field Package --field Build-IDs --pattern), $id);

    my %pkgs = map { $_ => 1 } split(/\n/, $output);
    return sort keys %pkgs;
}

sub get_debs_from_path
{
    my ($path) = @_;

    my $output;
    eval {
        ($output, undef) = capturex(qw(dpkg-query --search --), $path);
    };
    if ($@) {
        return;
    }

    my %pkgs = ();
    foreach my $line (split(/\n/, $output)) {
        if ($line =~ /^(.*): /) {
            $pkgs{$1} = 1;
        } else {
            warn "W: Cannot parse dpkg-query output: '$line'\n";
        }
    }
    my @pkgs = sort keys %pkgs;
    my @strip_pkgs = map { s{:.*}{}; s{\d.*$}{}r } @pkgs;

    eval {
        ($output, undef) = capturex(qw(dpkg-query --showformat ${source:Package}\n --show --), @pkgs);
    };
    if ($@) {
        return;
    }

    my %dbg_pkgs = ();
    foreach my $src_pkg (split(/\n/, $output)) {
        my $output;
        $output = capturex([0, 1], qw(grep-aptavail --no-field-names --show-field Package --field Package --pattern -dbg --and --whole-pkg --field Source:Package --pattern), $src_pkg);
        if ($EXITVAL) {
            warn "W: No dbg package for source '$src_pkg'\n";
            next;
        }
        my %src_dbg_pkgs = map { $_ => 1 } split(/\n/, $output);
        my @src_dbg_pkgs = keys %src_dbg_pkgs;
        my @src_strip_pkgs = map { my $pkg = $_; grep { /^$pkg-dbg/ } @src_dbg_pkgs } @pkgs;
        @src_strip_pkgs = map { my $pkg = $_; grep { /^$pkg.*-dbg/ } @src_dbg_pkgs } @pkgs unless @src_strip_pkgs;
        @src_strip_pkgs = map { my $pkg = $_; grep { /^$pkg-dbg/ } @src_dbg_pkgs } @strip_pkgs unless @src_strip_pkgs;
        @src_strip_pkgs = map { my $pkg = $_; grep { /^$pkg.*-dbg/ } @src_dbg_pkgs } @strip_pkgs unless @src_strip_pkgs;
        @src_dbg_pkgs = @src_strip_pkgs if @src_strip_pkgs;
        map { $dbg_pkgs{$_} = 1; } @src_dbg_pkgs;
    };

    return sort keys %dbg_pkgs;
}

sub is_core_file
{
    my ($filename) = (@_);
    my $output = capturex(qw(eu-readelf --file-header --), $filename);
    if ($output =~ /^\s*Type:\s*CORE/m) {
        return 1;
    }
    return;
}

sub usage
{
    print << "EOF";
usage:
  $0 <core file or PID> [ ... ]

  You must already have the correct debug lines in your sources.list and have
  executed 'apt-get update'.

  $0 requires the elfutils and dctrl-tools packages to be installed.
EOF

    exit 1;
}

# vim: syntax=perl sw=4 sts=4 sr et