diff --git a/debian/changelog b/debian/changelog index 2f1b006..bff04b7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,9 @@ + Add some more comments to the logic of the main routine. + Add a --all option which outputs all related dbgsym packages, not just those still missing. + + Add a --deb option which generates a metapackage with the dbgsym as + dependencies instead of listing them. Recommend equivs and + libfile-slurper-perl for that. (Closes: #935567) -- Axel Beckert Sat, 18 Apr 2020 23:54:38 +0200 diff --git a/debian/control b/debian/control index 3491644..79dc336 100644 --- a/debian/control +++ b/debian/control @@ -18,7 +18,9 @@ curl, dctrl-tools, elfutils, + equivs, libipc-system-simple-perl, + libfile-slurper-perl, libfile-which-perl, man-db, perl, @@ -71,9 +73,11 @@ dpigs - Show which installed packages occupy the most space [dctrl-tools] find-dbgsym-packages - - Get list of dbgsym packages from core dump or PID [dctrl-tools, - elfutils, libfile-which-perl, libipc-system-simple-perl] + - Get list of dbgsym packages from core dump or PID. [dctrl-tools, + elfutils, libfile-which-perl, libipc-system-simple-perl, + libfile-slurper-perl] Usage of the --ssh option requires openssh-client. + Usage of the --deb option requires equivs. popbugs - Display a customized release-critical bug list based on packages you use (using popularity-contest data) [python3, popularity-contest] diff --git a/find-dbgsym-packages b/find-dbgsym-packages index f0e9019..9c2544d 100755 --- a/find-dbgsym-packages +++ b/find-dbgsym-packages @@ -28,6 +28,11 @@ use v5.14; use IPC::System::Simple qw(capturex $EXITVAL); use File::Which; +use File::Temp qw(tempdir); +use File::Slurper qw(read_text write_text); +use POSIX qw(strftime); +use File::Copy qw(move); +use File::Basename qw(fileparse); $ENV{LC_ALL} = 'C'; @@ -39,15 +44,25 @@ my $call_apt = 0; my $use_ssh = 0; my $show_all = 0; +my $gen_deb = 0; my %pkgs; +my @programs = (); my @out_of_date_files; foreach my $arg (@ARGV) { if ($arg eq '--install') { $call_apt = 1; next; } + if ($arg eq '--deb') { + die "Package equivs needs to be installed to use the option '--deb'.\n" + unless which('equivs-build'); + $gen_deb = 1; + next; + } if ($arg eq '--ssh') { + die "Package openssh-client needs to be installed to use the option '--ssh'.\n" + unless which('ssh'); $use_ssh = 1; next; } @@ -59,6 +74,9 @@ my %build_ids; if ($arg =~ /^\d+$/) { %build_ids = get_build_ids_from_pid($arg); + + # Document which file was looked for + push(@programs, readlink("/proc/$arg/exe")); } else { %build_ids = get_build_ids_from_file($arg); } @@ -100,6 +118,12 @@ if ($call_apt) { my @cmd = (qw(apt install --no-install-recommends), @pkgs); + # Shall we generate a metapackage and install that one? + if ($gen_deb) { + my $pkg = gen_pkg(@pkgs); + @cmd = (qw(apt install), $pkg); + } + # Are we root? unless ($> == 0) { @@ -121,6 +145,17 @@ # Finally execute the command constructed above exec(@cmd); + + # Shall we just generate a .deb, but not install it? + } elsif ($gen_deb) { + my $pkg = gen_pkg(@pkgs); + my $target = $ENV{TMPDIR} // '/tmp'; + move($pkg, $target); + my $filename = $target.'/'.fileparse($pkg); + say "Metapackage has been generated at $filename."; + say "Install it like this with root privileges:"; + say ""; + say "apt install $filename"; # No options, so just display the list of still needed packages. } else { @@ -241,6 +276,9 @@ if (is_core_file($filename)) { return get_build_ids_from_core($filename); } else { + # Document which file was looked for + push(@programs, $filename); + my @filenames = get_files_from_elf($filename); my %build_ids; foreach my $filename (@filenames) { @@ -263,6 +301,10 @@ { my ($filename) = @_; my $output = capturex(qw(eu-unstrip --list-only --core), $filename); + + # Document which file was looked for (fifth field in first line) + my $program = (split(' ', (split(/\n/, $output))[0]))[4]; + push(@programs, $program); return parse_eu_unstrip($output); } @@ -348,11 +390,93 @@ return; } +sub gen_pkg { + my @pkgs = @_; + my $tempdir = tempdir( ( $ENV{TMPDIR} ? $ENV{TMPDIR} : '/tmp' ). + '/find-dbgsym-packages-equivs_XXXXX', + CLEANUP => 1 ); + + # Generating the necessary strings for generating the metapackage + my %replacements = (); + + $replacements{CALL} = "$0 ".join(' ', @ARGV); + $replacements{DATE} = strftime('%a, %d %b %Y %T %z', localtime()); + $replacements{DEPENDS} = join(', ', @pkgs); + $replacements{USER} = getlogin(); + $replacements{HOST} = `hostname`; + $replacements{AOM} = $show_all ? 'all' : 'currently missing'; + + chomp($replacements{USER}); + chomp($replacements{HOST}); + + my $dg_version = `dpkg-query -f '\${Version}' -W debian-goodies`; + $replacements{DGVERSION} = $dg_version; + + my @now = localtime; + my $pkg_version = strftime( + '%Y.%m.%dT%H.%M.%S+dg'.$dg_version, + localtime() + ); + $replacements{PKGVERSION} = $pkg_version; + + my %programs = map { $_ => 1 } @programs; + $replacements{PROGRAMS} = ' * ' . + join("\n * ", sort keys %programs); + + $replacements{PACKAGE} = 'dbgsym-pkgs-for-' . + join('-', + map { + s(^.*/)(); + s/\W//g; + s/[-_]//g; + lc($_); + } + sort keys %programs + ); + + # Replace placeholders with actual data + foreach my $file (qw(changelog control readme)) { + gen_file_from_template( + ( -d './find-dbgsym-packages-templates/' ? + './find-dbgsym-packages-templates/' : + '/usr/share/debian-goodies/find-dbgsym-packages-templates/' ) + . $file, + "$tempdir/$file", + \%replacements + ); + } + + # Generate the .deb + chdir($tempdir); + #system("head -100 *"); + my $pkgbuild = capturex(qw(equivs-build control)); + #system("dpkg-deb --info *.deb"); + + my @debs = glob('*.deb'); + # Sanity check + die "$0: BUG: Not exactly one .deb file generated" unless $#debs == 0; + + return $tempdir.'/'.$debs[0]; +} + +sub gen_file_from_template { + my ($input, $output, $replacements) = @_; + + my $text = read_text($input); + + foreach my $key (%$replacements) { + $text =~ s/__${key}__/$replacements->{$key}/g; + } + + write_text($output, $text); +} + sub usage { print << "EOF"; usage: - $0 [--install] [--ssh] [--all] [ ... ] + $0 [--install] [--ssh] [--deb] [--all] \ + [ ... ] You must already have the correct debug lines in your sources.list and have executed 'apt-get update'. diff --git a/find-dbgsym-packages-templates/changelog b/find-dbgsym-packages-templates/changelog new file mode 100644 index 0000000..e5523bd --- /dev/null +++ b/find-dbgsym-packages-templates/changelog @@ -0,0 +1,6 @@ +find-dbgsym-packages (__PKGVERSION__) local; urgency=low + + * Generated by "__CALL__". + + -- find-dbgsym-packages called by <__USER__@__HOST__> __DATE__ + diff --git a/find-dbgsym-packages-templates/control b/find-dbgsym-packages-templates/control new file mode 100644 index 0000000..12db32f --- /dev/null +++ b/find-dbgsym-packages-templates/control @@ -0,0 +1,18 @@ +Source: find-dbgsym-packages +Section: metapackages +Priority: optional +Standards-Version: 4.5.0 +Maintainer: find-dbgsym-packages called by <__USER__@__HOST__> + +Package: __PACKAGE__ +Version: __PKGVERSION__ +Depends: __DEPENDS__ +Architecture: all +Changelog: changelog +Readme: readme +Description: Dependency package for dbgsym packages + This package is generated by find-dbgsym-packages from the Debian + package debian-goodies (version __DGVERSION__) and depends on __AOM__ + dbgsym packages required to properly debug the following programms: + . +__PROGRAMS__ diff --git a/find-dbgsym-packages-templates/readme b/find-dbgsym-packages-templates/readme new file mode 100644 index 0000000..d9702d0 --- /dev/null +++ b/find-dbgsym-packages-templates/readme @@ -0,0 +1,5 @@ +This is a local metapackage generated by "__CALL__" +called by __USER__ on __HOST__ on __DATE__. + +The version of find-dbgsym-packages is the one from the debian-goodies +Debian package at version __DGVERSION__. diff --git a/find-dbgsym-packages.pod b/find-dbgsym-packages.pod index b06595b..26006c7 100644 --- a/find-dbgsym-packages.pod +++ b/find-dbgsym-packages.pod @@ -6,7 +6,9 @@ =head1 SYNOPSIS -B [I] I [I …] +B [B<--install>] [B<--ssh>] [B<--deb>] +[B<--all>] I [I …] =head1 DESCRIPTION @@ -42,9 +44,18 @@ Use C instead of C or C. to gain administrative privileges. +=item C<--deb> + +Generate a metapackage which depends on all the still needed debug symbol packages. + +This requires the package C to be installed. + +If C<--install> is also given, automatically install the package and +all its (missing) dependencies. + =item C<--all> -Show or install I relevant debug symbol packages, not just those +Show or include I relevant debug symbol packages, not just those still missing. =back