diff --git a/rpm/precheckin.sh b/precheckin.sh old mode 100644 new mode 100755 similarity index 76% rename from rpm/precheckin.sh rename to precheckin.sh index 47b3b74..da2885e --- a/rpm/precheckin.sh +++ b/precheckin.sh @@ -21,5 +21,5 @@ for i in ${ARCHES} ; do else CROSSTARGET=${i}-${VENDOR}-linux-gnu fi - cat ./${SPECNAME} | sed -e "s#Name: .*#Name: cross-${i}-${NAME}\n%define crosstarget ${CROSSTARGET}#" > ./cross-${i}-${NAME}.spec + cat ./rpm/${SPECNAME} | sed -e "s#Name: .*#Name: cross-${i}-${NAME}\n%define crosstarget ${CROSSTARGET}#" > ./rpm/cross-${i}-${NAME}.spec done diff --git a/rpm/cross-aarch64-gdb.spec b/rpm/cross-aarch64-gdb.spec index 3f6d83d..eb6e1ec 100644 --- a/rpm/cross-aarch64-gdb.spec +++ b/rpm/cross-aarch64-gdb.spec @@ -1,5 +1,3 @@ -%global __python %{__python3} - %global ctarch %{crosstarget}__%{_arch} Name: cross-aarch64-gdb @@ -10,35 +8,50 @@ Name: cross-aarch64-gdb %endif Summary: A GNU source-level debugger for C, C++, Java and other languages -Version: 12.1.0 +Version: 16.3.0 Release: 1 License: GPLv3+ -URL: http://gnu.org/software/gdb/ +URL: https://github.com/sailfishos/gdb Source0: %{name}-%{version}.tar.bz2 Source1: gdb-rpmlintrc -Source2: precheckin.sh - -# New locating of the matching binaries from the pure core file (build-id). -Patch1: gdb-6.6-buildid-locate.patch -# Fix loading of core files without build-ids but with build-ids in executables. -Patch2: gdb-6.6-buildid-locate-solib-missing-ids.patch -Patch3: gdb-6.6-buildid-locate-rpm.patch -# Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -Patch4: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch -Patch5: gdb-6.6-buildid-locate-rpm-suse.patch -Patch6: system-gdbinit-missing-parentheses.patch -BuildRequires: pkgconfig(ncurses) -BuildRequires: texinfo -BuildRequires: gettext -BuildRequires: flex +# Update gdb-add-index.sh such that, when the GDB environment +# variable is not set, the script is smarter than just looking for +# 'gdb' in the $PATH. +# +# The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +# $PATH), then /usr/libexec/gdb. +# +# For the rationale of looking for gdb.minimal see: +# +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +# +#=fedora +Patch002: gdb-add-index.patch + +# Not a backport. Add a new script which hooks into GDB and suggests +# RPMs to install when GDB finds an objfile with no debug info. +Patch003: gdb-rpm-suggestion-script.patch + +# Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" +Patch004: gdb-fix-bg-execution-repeat.patch + +# Sailfish OS modifications to rpm suggestion script +Patch005: gdb-rpm-suggestion-script-sailfishos.patch + BuildRequires: bison -BuildRequires: expat-devel -BuildRequires: gmp-devel -BuildRequires: python3-devel +BuildRequires: flex +BuildRequires: gettext BuildRequires: libstdc++ -BuildRequires: zlib-devel +BuildRequires: texinfo +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(gmp) +BuildRequires: pkgconfig(mpfr) +BuildRequires: pkgconfig(ncurses) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(zlib) Requires: python3-base +Recommends: rpm-python %description GDB, the GNU debugger, allows you to debug programs written in C, C++, @@ -47,16 +60,10 @@ and printing their data. %prep -%setup -q -n %{name}-%{version}/upstream -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +%autosetup -p1 -n %{name}-%{version}/upstream cat > gdb/version.in << _FOO -Mer (%{version}) +Sailfish OS (%{version}) _FOO # Remove the info and other generated files added by the FSF release @@ -94,7 +101,7 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-rpath \ --with-expat \ --enable-tui \ - --with-python=%{__python} \ + --with-python=%{__python3} \ --without-libunwind \ --enable-64-bit-bfd \ --enable-static \ @@ -109,8 +116,8 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-gprofng \ %{_target_platform} -make %{?_smp_mflags} -make %{?_smp_mflags} info +%make_build +%make_build info %install @@ -128,6 +135,7 @@ mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}" install -m 0644 -t "%{buildroot}%{_docdir}/%{name}-%{version}" README gdb/NEWS rm "%{buildroot}%{_infodir}"/bfd* rm -f "%{buildroot}%{_infodir}"/ctf-spec* +rm -f "%{buildroot}%{_infodir}"/sframe-spec* %else rm -r "%{buildroot}%{_infodir}/" rm -r "%{buildroot}%{_mandir}/" @@ -137,18 +145,6 @@ rm -r "%{buildroot}%{_mandir}/" %if "%{?crosstarget}" == "" #### NON-CROSS PACS -%files -%defattr(-,root,root,-) -%license COPYING COPYING.LIB -%{_bindir}/gcore -%{_bindir}/gdb -%{_bindir}/gdb-add-index -%{_datadir}/gdb -%if "%{_arch}" == "aarch64" -%{_libdir}/libinproctrace.so -%endif - - %package gdbserver Summary: A standalone server for GDB (the GNU source-level debugger) %ifarch %{ix86} x86_64 @@ -164,19 +160,6 @@ and printing their data. This package provides a program that allows you to run GDB on a different machine than the one which is running the program being debugged. -%ifarch %{ix86} x86_64 -%post gdbserver -p /sbin/ldconfig -%postun gdbserver -p /sbin/ldconfig -%endif - -%files gdbserver -%defattr(-,root,root,-) -%{_bindir}/gdbserver -%ifarch %{ix86} x86_64 -%{_libdir}/libinproctrace.so -%endif - - %package doc Summary: Documentation for %{name} Requires: %{name} = %{version}-%{release} @@ -186,6 +169,11 @@ Requires(postun): /sbin/install-info %description doc Man and info pages for %{name}. +%ifarch %{ix86} x86_64 +%post gdbserver -p /sbin/ldconfig +%postun gdbserver -p /sbin/ldconfig +%endif + %post doc %install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz %install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz @@ -201,12 +189,30 @@ then %install_info_delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz fi + +%files +%license COPYING3 COPYING3.LIB +%{_bindir}/gcore +%{_bindir}/gdb +%{_bindir}/gdb-add-index +%{_bindir}/gstack +%{_datadir}/gdb +%if "%{_arch}" == "aarch64" +%{_libdir}/libinproctrace.so +%endif + +%files gdbserver +%{_bindir}/gdbserver +%ifarch %{ix86} x86_64 +%{_libdir}/libinproctrace.so +%endif + %files doc -%defattr(-,root,root,-) %{_mandir}/*/gdb.1* %{_mandir}/*/gdbserver.1* %{_mandir}/man1/gcore.1.gz %{_mandir}/man1/gdb-add-index.1.gz +%{_mandir}/man1/gstack.1.gz %{_mandir}/man5/gdbinit.5.gz %{_infodir}/annotate.info.gz %{_infodir}/gdb.info.gz @@ -214,24 +220,27 @@ fi %{_docdir}/%{name}-%{version} -%else # crosstarget +%else +# crosstarget #### CROSS PACS %files -%defattr(-,root,root,-) /opt/cross/share/%{crosstarget}-gdb -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/bin/gcore /opt/cross/bin/gdb /opt/cross/bin/gdb-add-index /opt/cross/bin/gdbserver +/opt/cross/bin/gstack %else /opt/cross/bin/%{crosstarget}-gdb /opt/cross/bin/%{crosstarget}-gdb-add-index +/opt/cross/bin/%{crosstarget}-gstack %endif -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/%{_lib}/libinproctrace.so %endif -%endif # crosstarget +# crosstarget +%endif diff --git a/rpm/cross-armv7hl-gdb.spec b/rpm/cross-armv7hl-gdb.spec index 2e9d142..cc1fe7d 100644 --- a/rpm/cross-armv7hl-gdb.spec +++ b/rpm/cross-armv7hl-gdb.spec @@ -1,5 +1,3 @@ -%global __python %{__python3} - %global ctarch %{crosstarget}__%{_arch} Name: cross-armv7hl-gdb @@ -10,35 +8,50 @@ Name: cross-armv7hl-gdb %endif Summary: A GNU source-level debugger for C, C++, Java and other languages -Version: 12.1.0 +Version: 16.3.0 Release: 1 License: GPLv3+ -URL: http://gnu.org/software/gdb/ +URL: https://github.com/sailfishos/gdb Source0: %{name}-%{version}.tar.bz2 Source1: gdb-rpmlintrc -Source2: precheckin.sh - -# New locating of the matching binaries from the pure core file (build-id). -Patch1: gdb-6.6-buildid-locate.patch -# Fix loading of core files without build-ids but with build-ids in executables. -Patch2: gdb-6.6-buildid-locate-solib-missing-ids.patch -Patch3: gdb-6.6-buildid-locate-rpm.patch -# Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -Patch4: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch -Patch5: gdb-6.6-buildid-locate-rpm-suse.patch -Patch6: system-gdbinit-missing-parentheses.patch -BuildRequires: pkgconfig(ncurses) -BuildRequires: texinfo -BuildRequires: gettext -BuildRequires: flex +# Update gdb-add-index.sh such that, when the GDB environment +# variable is not set, the script is smarter than just looking for +# 'gdb' in the $PATH. +# +# The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +# $PATH), then /usr/libexec/gdb. +# +# For the rationale of looking for gdb.minimal see: +# +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +# +#=fedora +Patch002: gdb-add-index.patch + +# Not a backport. Add a new script which hooks into GDB and suggests +# RPMs to install when GDB finds an objfile with no debug info. +Patch003: gdb-rpm-suggestion-script.patch + +# Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" +Patch004: gdb-fix-bg-execution-repeat.patch + +# Sailfish OS modifications to rpm suggestion script +Patch005: gdb-rpm-suggestion-script-sailfishos.patch + BuildRequires: bison -BuildRequires: expat-devel -BuildRequires: gmp-devel -BuildRequires: python3-devel +BuildRequires: flex +BuildRequires: gettext BuildRequires: libstdc++ -BuildRequires: zlib-devel +BuildRequires: texinfo +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(gmp) +BuildRequires: pkgconfig(mpfr) +BuildRequires: pkgconfig(ncurses) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(zlib) Requires: python3-base +Recommends: rpm-python %description GDB, the GNU debugger, allows you to debug programs written in C, C++, @@ -47,16 +60,10 @@ and printing their data. %prep -%setup -q -n %{name}-%{version}/upstream -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +%autosetup -p1 -n %{name}-%{version}/upstream cat > gdb/version.in << _FOO -Mer (%{version}) +Sailfish OS (%{version}) _FOO # Remove the info and other generated files added by the FSF release @@ -94,7 +101,7 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-rpath \ --with-expat \ --enable-tui \ - --with-python=%{__python} \ + --with-python=%{__python3} \ --without-libunwind \ --enable-64-bit-bfd \ --enable-static \ @@ -109,8 +116,8 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-gprofng \ %{_target_platform} -make %{?_smp_mflags} -make %{?_smp_mflags} info +%make_build +%make_build info %install @@ -128,6 +135,7 @@ mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}" install -m 0644 -t "%{buildroot}%{_docdir}/%{name}-%{version}" README gdb/NEWS rm "%{buildroot}%{_infodir}"/bfd* rm -f "%{buildroot}%{_infodir}"/ctf-spec* +rm -f "%{buildroot}%{_infodir}"/sframe-spec* %else rm -r "%{buildroot}%{_infodir}/" rm -r "%{buildroot}%{_mandir}/" @@ -137,18 +145,6 @@ rm -r "%{buildroot}%{_mandir}/" %if "%{?crosstarget}" == "" #### NON-CROSS PACS -%files -%defattr(-,root,root,-) -%license COPYING COPYING.LIB -%{_bindir}/gcore -%{_bindir}/gdb -%{_bindir}/gdb-add-index -%{_datadir}/gdb -%if "%{_arch}" == "aarch64" -%{_libdir}/libinproctrace.so -%endif - - %package gdbserver Summary: A standalone server for GDB (the GNU source-level debugger) %ifarch %{ix86} x86_64 @@ -164,19 +160,6 @@ and printing their data. This package provides a program that allows you to run GDB on a different machine than the one which is running the program being debugged. -%ifarch %{ix86} x86_64 -%post gdbserver -p /sbin/ldconfig -%postun gdbserver -p /sbin/ldconfig -%endif - -%files gdbserver -%defattr(-,root,root,-) -%{_bindir}/gdbserver -%ifarch %{ix86} x86_64 -%{_libdir}/libinproctrace.so -%endif - - %package doc Summary: Documentation for %{name} Requires: %{name} = %{version}-%{release} @@ -186,6 +169,11 @@ Requires(postun): /sbin/install-info %description doc Man and info pages for %{name}. +%ifarch %{ix86} x86_64 +%post gdbserver -p /sbin/ldconfig +%postun gdbserver -p /sbin/ldconfig +%endif + %post doc %install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz %install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz @@ -201,12 +189,30 @@ then %install_info_delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz fi + +%files +%license COPYING3 COPYING3.LIB +%{_bindir}/gcore +%{_bindir}/gdb +%{_bindir}/gdb-add-index +%{_bindir}/gstack +%{_datadir}/gdb +%if "%{_arch}" == "aarch64" +%{_libdir}/libinproctrace.so +%endif + +%files gdbserver +%{_bindir}/gdbserver +%ifarch %{ix86} x86_64 +%{_libdir}/libinproctrace.so +%endif + %files doc -%defattr(-,root,root,-) %{_mandir}/*/gdb.1* %{_mandir}/*/gdbserver.1* %{_mandir}/man1/gcore.1.gz %{_mandir}/man1/gdb-add-index.1.gz +%{_mandir}/man1/gstack.1.gz %{_mandir}/man5/gdbinit.5.gz %{_infodir}/annotate.info.gz %{_infodir}/gdb.info.gz @@ -214,24 +220,27 @@ fi %{_docdir}/%{name}-%{version} -%else # crosstarget +%else +# crosstarget #### CROSS PACS %files -%defattr(-,root,root,-) /opt/cross/share/%{crosstarget}-gdb -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/bin/gcore /opt/cross/bin/gdb /opt/cross/bin/gdb-add-index /opt/cross/bin/gdbserver +/opt/cross/bin/gstack %else /opt/cross/bin/%{crosstarget}-gdb /opt/cross/bin/%{crosstarget}-gdb-add-index +/opt/cross/bin/%{crosstarget}-gstack %endif -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/%{_lib}/libinproctrace.so %endif -%endif # crosstarget +# crosstarget +%endif diff --git a/rpm/cross-i486-gdb.spec b/rpm/cross-i486-gdb.spec index 12796b9..9b27fc8 100644 --- a/rpm/cross-i486-gdb.spec +++ b/rpm/cross-i486-gdb.spec @@ -1,5 +1,3 @@ -%global __python %{__python3} - %global ctarch %{crosstarget}__%{_arch} Name: cross-i486-gdb @@ -10,35 +8,50 @@ Name: cross-i486-gdb %endif Summary: A GNU source-level debugger for C, C++, Java and other languages -Version: 12.1.0 +Version: 16.3.0 Release: 1 License: GPLv3+ -URL: http://gnu.org/software/gdb/ +URL: https://github.com/sailfishos/gdb Source0: %{name}-%{version}.tar.bz2 Source1: gdb-rpmlintrc -Source2: precheckin.sh - -# New locating of the matching binaries from the pure core file (build-id). -Patch1: gdb-6.6-buildid-locate.patch -# Fix loading of core files without build-ids but with build-ids in executables. -Patch2: gdb-6.6-buildid-locate-solib-missing-ids.patch -Patch3: gdb-6.6-buildid-locate-rpm.patch -# Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -Patch4: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch -Patch5: gdb-6.6-buildid-locate-rpm-suse.patch -Patch6: system-gdbinit-missing-parentheses.patch -BuildRequires: pkgconfig(ncurses) -BuildRequires: texinfo -BuildRequires: gettext -BuildRequires: flex +# Update gdb-add-index.sh such that, when the GDB environment +# variable is not set, the script is smarter than just looking for +# 'gdb' in the $PATH. +# +# The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +# $PATH), then /usr/libexec/gdb. +# +# For the rationale of looking for gdb.minimal see: +# +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +# +#=fedora +Patch002: gdb-add-index.patch + +# Not a backport. Add a new script which hooks into GDB and suggests +# RPMs to install when GDB finds an objfile with no debug info. +Patch003: gdb-rpm-suggestion-script.patch + +# Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" +Patch004: gdb-fix-bg-execution-repeat.patch + +# Sailfish OS modifications to rpm suggestion script +Patch005: gdb-rpm-suggestion-script-sailfishos.patch + BuildRequires: bison -BuildRequires: expat-devel -BuildRequires: gmp-devel -BuildRequires: python3-devel +BuildRequires: flex +BuildRequires: gettext BuildRequires: libstdc++ -BuildRequires: zlib-devel +BuildRequires: texinfo +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(gmp) +BuildRequires: pkgconfig(mpfr) +BuildRequires: pkgconfig(ncurses) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(zlib) Requires: python3-base +Recommends: rpm-python %description GDB, the GNU debugger, allows you to debug programs written in C, C++, @@ -47,16 +60,10 @@ and printing their data. %prep -%setup -q -n %{name}-%{version}/upstream -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +%autosetup -p1 -n %{name}-%{version}/upstream cat > gdb/version.in << _FOO -Mer (%{version}) +Sailfish OS (%{version}) _FOO # Remove the info and other generated files added by the FSF release @@ -94,7 +101,7 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-rpath \ --with-expat \ --enable-tui \ - --with-python=%{__python} \ + --with-python=%{__python3} \ --without-libunwind \ --enable-64-bit-bfd \ --enable-static \ @@ -109,8 +116,8 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-gprofng \ %{_target_platform} -make %{?_smp_mflags} -make %{?_smp_mflags} info +%make_build +%make_build info %install @@ -128,6 +135,7 @@ mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}" install -m 0644 -t "%{buildroot}%{_docdir}/%{name}-%{version}" README gdb/NEWS rm "%{buildroot}%{_infodir}"/bfd* rm -f "%{buildroot}%{_infodir}"/ctf-spec* +rm -f "%{buildroot}%{_infodir}"/sframe-spec* %else rm -r "%{buildroot}%{_infodir}/" rm -r "%{buildroot}%{_mandir}/" @@ -137,18 +145,6 @@ rm -r "%{buildroot}%{_mandir}/" %if "%{?crosstarget}" == "" #### NON-CROSS PACS -%files -%defattr(-,root,root,-) -%license COPYING COPYING.LIB -%{_bindir}/gcore -%{_bindir}/gdb -%{_bindir}/gdb-add-index -%{_datadir}/gdb -%if "%{_arch}" == "aarch64" -%{_libdir}/libinproctrace.so -%endif - - %package gdbserver Summary: A standalone server for GDB (the GNU source-level debugger) %ifarch %{ix86} x86_64 @@ -164,19 +160,6 @@ and printing their data. This package provides a program that allows you to run GDB on a different machine than the one which is running the program being debugged. -%ifarch %{ix86} x86_64 -%post gdbserver -p /sbin/ldconfig -%postun gdbserver -p /sbin/ldconfig -%endif - -%files gdbserver -%defattr(-,root,root,-) -%{_bindir}/gdbserver -%ifarch %{ix86} x86_64 -%{_libdir}/libinproctrace.so -%endif - - %package doc Summary: Documentation for %{name} Requires: %{name} = %{version}-%{release} @@ -186,6 +169,11 @@ Requires(postun): /sbin/install-info %description doc Man and info pages for %{name}. +%ifarch %{ix86} x86_64 +%post gdbserver -p /sbin/ldconfig +%postun gdbserver -p /sbin/ldconfig +%endif + %post doc %install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz %install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz @@ -201,12 +189,30 @@ then %install_info_delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz fi + +%files +%license COPYING3 COPYING3.LIB +%{_bindir}/gcore +%{_bindir}/gdb +%{_bindir}/gdb-add-index +%{_bindir}/gstack +%{_datadir}/gdb +%if "%{_arch}" == "aarch64" +%{_libdir}/libinproctrace.so +%endif + +%files gdbserver +%{_bindir}/gdbserver +%ifarch %{ix86} x86_64 +%{_libdir}/libinproctrace.so +%endif + %files doc -%defattr(-,root,root,-) %{_mandir}/*/gdb.1* %{_mandir}/*/gdbserver.1* %{_mandir}/man1/gcore.1.gz %{_mandir}/man1/gdb-add-index.1.gz +%{_mandir}/man1/gstack.1.gz %{_mandir}/man5/gdbinit.5.gz %{_infodir}/annotate.info.gz %{_infodir}/gdb.info.gz @@ -214,24 +220,27 @@ fi %{_docdir}/%{name}-%{version} -%else # crosstarget +%else +# crosstarget #### CROSS PACS %files -%defattr(-,root,root,-) /opt/cross/share/%{crosstarget}-gdb -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/bin/gcore /opt/cross/bin/gdb /opt/cross/bin/gdb-add-index /opt/cross/bin/gdbserver +/opt/cross/bin/gstack %else /opt/cross/bin/%{crosstarget}-gdb /opt/cross/bin/%{crosstarget}-gdb-add-index +/opt/cross/bin/%{crosstarget}-gstack %endif -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/%{_lib}/libinproctrace.so %endif -%endif # crosstarget +# crosstarget +%endif diff --git a/rpm/cross-x86_64-gdb.spec b/rpm/cross-x86_64-gdb.spec index 69de023..c7ee14f 100644 --- a/rpm/cross-x86_64-gdb.spec +++ b/rpm/cross-x86_64-gdb.spec @@ -1,5 +1,3 @@ -%global __python %{__python3} - %global ctarch %{crosstarget}__%{_arch} Name: cross-x86_64-gdb @@ -10,35 +8,50 @@ Name: cross-x86_64-gdb %endif Summary: A GNU source-level debugger for C, C++, Java and other languages -Version: 12.1.0 +Version: 16.3.0 Release: 1 License: GPLv3+ -URL: http://gnu.org/software/gdb/ +URL: https://github.com/sailfishos/gdb Source0: %{name}-%{version}.tar.bz2 Source1: gdb-rpmlintrc -Source2: precheckin.sh - -# New locating of the matching binaries from the pure core file (build-id). -Patch1: gdb-6.6-buildid-locate.patch -# Fix loading of core files without build-ids but with build-ids in executables. -Patch2: gdb-6.6-buildid-locate-solib-missing-ids.patch -Patch3: gdb-6.6-buildid-locate-rpm.patch -# Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -Patch4: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch -Patch5: gdb-6.6-buildid-locate-rpm-suse.patch -Patch6: system-gdbinit-missing-parentheses.patch -BuildRequires: pkgconfig(ncurses) -BuildRequires: texinfo -BuildRequires: gettext -BuildRequires: flex +# Update gdb-add-index.sh such that, when the GDB environment +# variable is not set, the script is smarter than just looking for +# 'gdb' in the $PATH. +# +# The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +# $PATH), then /usr/libexec/gdb. +# +# For the rationale of looking for gdb.minimal see: +# +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +# +#=fedora +Patch002: gdb-add-index.patch + +# Not a backport. Add a new script which hooks into GDB and suggests +# RPMs to install when GDB finds an objfile with no debug info. +Patch003: gdb-rpm-suggestion-script.patch + +# Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" +Patch004: gdb-fix-bg-execution-repeat.patch + +# Sailfish OS modifications to rpm suggestion script +Patch005: gdb-rpm-suggestion-script-sailfishos.patch + BuildRequires: bison -BuildRequires: expat-devel -BuildRequires: gmp-devel -BuildRequires: python3-devel +BuildRequires: flex +BuildRequires: gettext BuildRequires: libstdc++ -BuildRequires: zlib-devel +BuildRequires: texinfo +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(gmp) +BuildRequires: pkgconfig(mpfr) +BuildRequires: pkgconfig(ncurses) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(zlib) Requires: python3-base +Recommends: rpm-python %description GDB, the GNU debugger, allows you to debug programs written in C, C++, @@ -47,16 +60,10 @@ and printing their data. %prep -%setup -q -n %{name}-%{version}/upstream -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +%autosetup -p1 -n %{name}-%{version}/upstream cat > gdb/version.in << _FOO -Mer (%{version}) +Sailfish OS (%{version}) _FOO # Remove the info and other generated files added by the FSF release @@ -94,7 +101,7 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-rpath \ --with-expat \ --enable-tui \ - --with-python=%{__python} \ + --with-python=%{__python3} \ --without-libunwind \ --enable-64-bit-bfd \ --enable-static \ @@ -109,8 +116,8 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-gprofng \ %{_target_platform} -make %{?_smp_mflags} -make %{?_smp_mflags} info +%make_build +%make_build info %install @@ -128,6 +135,7 @@ mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}" install -m 0644 -t "%{buildroot}%{_docdir}/%{name}-%{version}" README gdb/NEWS rm "%{buildroot}%{_infodir}"/bfd* rm -f "%{buildroot}%{_infodir}"/ctf-spec* +rm -f "%{buildroot}%{_infodir}"/sframe-spec* %else rm -r "%{buildroot}%{_infodir}/" rm -r "%{buildroot}%{_mandir}/" @@ -137,18 +145,6 @@ rm -r "%{buildroot}%{_mandir}/" %if "%{?crosstarget}" == "" #### NON-CROSS PACS -%files -%defattr(-,root,root,-) -%license COPYING COPYING.LIB -%{_bindir}/gcore -%{_bindir}/gdb -%{_bindir}/gdb-add-index -%{_datadir}/gdb -%if "%{_arch}" == "aarch64" -%{_libdir}/libinproctrace.so -%endif - - %package gdbserver Summary: A standalone server for GDB (the GNU source-level debugger) %ifarch %{ix86} x86_64 @@ -164,19 +160,6 @@ and printing their data. This package provides a program that allows you to run GDB on a different machine than the one which is running the program being debugged. -%ifarch %{ix86} x86_64 -%post gdbserver -p /sbin/ldconfig -%postun gdbserver -p /sbin/ldconfig -%endif - -%files gdbserver -%defattr(-,root,root,-) -%{_bindir}/gdbserver -%ifarch %{ix86} x86_64 -%{_libdir}/libinproctrace.so -%endif - - %package doc Summary: Documentation for %{name} Requires: %{name} = %{version}-%{release} @@ -186,6 +169,11 @@ Requires(postun): /sbin/install-info %description doc Man and info pages for %{name}. +%ifarch %{ix86} x86_64 +%post gdbserver -p /sbin/ldconfig +%postun gdbserver -p /sbin/ldconfig +%endif + %post doc %install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz %install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz @@ -201,12 +189,30 @@ then %install_info_delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz fi + +%files +%license COPYING3 COPYING3.LIB +%{_bindir}/gcore +%{_bindir}/gdb +%{_bindir}/gdb-add-index +%{_bindir}/gstack +%{_datadir}/gdb +%if "%{_arch}" == "aarch64" +%{_libdir}/libinproctrace.so +%endif + +%files gdbserver +%{_bindir}/gdbserver +%ifarch %{ix86} x86_64 +%{_libdir}/libinproctrace.so +%endif + %files doc -%defattr(-,root,root,-) %{_mandir}/*/gdb.1* %{_mandir}/*/gdbserver.1* %{_mandir}/man1/gcore.1.gz %{_mandir}/man1/gdb-add-index.1.gz +%{_mandir}/man1/gstack.1.gz %{_mandir}/man5/gdbinit.5.gz %{_infodir}/annotate.info.gz %{_infodir}/gdb.info.gz @@ -214,24 +220,27 @@ fi %{_docdir}/%{name}-%{version} -%else # crosstarget +%else +# crosstarget #### CROSS PACS %files -%defattr(-,root,root,-) /opt/cross/share/%{crosstarget}-gdb -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/bin/gcore /opt/cross/bin/gdb /opt/cross/bin/gdb-add-index /opt/cross/bin/gdbserver +/opt/cross/bin/gstack %else /opt/cross/bin/%{crosstarget}-gdb /opt/cross/bin/%{crosstarget}-gdb-add-index +/opt/cross/bin/%{crosstarget}-gstack %endif -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/%{_lib}/libinproctrace.so %endif -%endif # crosstarget +# crosstarget +%endif diff --git a/rpm/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch b/rpm/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch deleted file mode 100644 index 2b862a0..0000000 --- a/rpm/gdb-6.6-buildid-locate-rpm-librpm-workaround.patch +++ /dev/null @@ -1,19 +0,0 @@ -From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 -From: Fedora GDB patches -Date: Fri, 27 Oct 2017 21:07:50 +0200 -Subject: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch - -;; Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -;;=push+jan - -diff --git a/gdb/proc-service.list b/gdb/proc-service.list ---- a/gdb/proc-service.list -+++ b/gdb/proc-service.list -@@ -37,4 +37,7 @@ - ps_pstop; - ps_ptread; - ps_ptwrite; -+ -+ /* gdb-6.6-buildid-locate-rpm.patch */ -+ rpmsqEnable; - }; diff --git a/rpm/gdb-6.6-buildid-locate-rpm-suse.patch b/rpm/gdb-6.6-buildid-locate-rpm-suse.patch deleted file mode 100644 index b695cd0..0000000 --- a/rpm/gdb-6.6-buildid-locate-rpm-suse.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 36cfc0f772461e9efeeb6a528651c0f494d65934 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Aapi=20H=C3=A4m=C3=A4l=C3=A4inen?= - -Date: Wed, 27 Mar 2019 11:51:23 +0200 -Subject: [PATCH 5/5] gdb-6.6-buildid-locate-rpm-suse - ---- - gdb/build-id.c | 68 +++++++++++++------------------------------------- - 1 file changed, 17 insertions(+), 51 deletions(-) - -diff --git a/gdb/build-id.c b/gdb/build-id.c -index 4e1477e950..7bc8eddf58 100644 ---- gdb-9.1.orig/gdb/build-id.c -+++ gdb-9.1/gdb/build-id.c -@@ -861,19 +861,17 @@ missing_rpm_enlist_1 (const char *filena - #endif - { - Header h; -- char *debuginfo, **slot, *s, *s2; -+ char *debuginfo, **slot; - errmsg_t err; -- size_t srcrpmlen = sizeof (".src.rpm") - 1; -- size_t debuginfolen = sizeof ("-debuginfo") - 1; - rpmdbMatchIterator mi_debuginfo; - - h = rpmdbNextIterator_p (mi); - if (h == NULL) - break; - -- /* Verify the debuginfo file is not already installed. */ -- -- debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}", -+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */ -+ debuginfo = headerFormat_p (h, -+ "%{name}-debuginfo-%{version}-%{release}.%{arch}", - &err); - if (!debuginfo) - { -@@ -881,60 +879,19 @@ missing_rpm_enlist_1 (const char *filena - err); - continue; - } -- /* s = `.src.rpm-debuginfo.%{arch}' */ -- s = strrchr (debuginfo, '-') - srcrpmlen; -- s2 = NULL; -- if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0) -- { -- /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */ -- s2 = (char *) memrchr (debuginfo, '-', s - debuginfo); -- } -- if (s2) -- { -- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ -- s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo); -- } -- if (!s2) -- { -- warning (_("Error querying the rpm file `%s': %s"), filename, -- debuginfo); -- xfree (debuginfo); -- continue; -- } -- /* s = `.src.rpm-debuginfo.%{arch}' */ -- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ -- memmove (s2 + debuginfolen, s2, s - s2); -- memcpy (s2, "-debuginfo", debuginfolen); -- /* s = `XXXX.%{arch}' */ -- /* strlen ("XXXX") == srcrpmlen + debuginfolen */ -- /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */ -- /* strlen ("XX") == srcrpmlen */ -- memmove (s + debuginfolen, s + srcrpmlen + debuginfolen, -- strlen (s + srcrpmlen + debuginfolen) + 1); -- /* s = `-debuginfo-%{version}-%{release}.%{arch}' */ - -+ /* Verify the debuginfo file is not already installed. */ - /* RPMDBI_PACKAGES requires keylen == sizeof (int). */ - /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */ - mi_debuginfo = rpmtsInitIterator_p (ts, (rpmTag) RPMDBI_LABEL, debuginfo, 0); -- xfree (debuginfo); - if (mi_debuginfo) - { -+ xfree (debuginfo); - rpmdbFreeIterator_p (mi_debuginfo); - count = 0; - break; - } - -- /* The allocated memory gets utilized below for MISSING_RPM_HASH. */ -- debuginfo = headerFormat_p (h, -- "%{name}-%{version}-%{release}.%{arch}", -- &err); -- if (!debuginfo) -- { -- warning (_("Error querying the rpm file `%s': %s"), filename, -- err); -- continue; -- } -- - /* Base package name for `debuginfo-install'. We do not use the - `yum' command directly as the line - yum --enablerepo='*debug*' install NAME-debuginfo.ARCH -@@ -1076,10 +1033,7 @@ missing_rpm_list_print (void) - missing_rpm_list_entries = 0; - - printf_unfiltered (_("Missing separate debuginfos, use: %s"), --#ifdef DNF_DEBUGINFO_INSTALL -- "dnf " --#endif -- "debuginfo-install"); -+ "zypper install"); - for (const char *el : array) - { - puts_unfiltered (" "); -@@ -1287,13 +1241,12 @@ debug_print_missing (const char *binary, - fprintf_unfiltered (gdb_stdlog, - _("Missing separate debuginfo for %s\n"), binary); - if (debug != NULL) -- fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"), --#ifdef DNF_DEBUGINFO_INSTALL -- "dnf" --#else -- "yum" --#endif -- " --enablerepo='*debug*' install", debug); -+ { -+ const char *p = strrchr (debug, '/'); -+ fprintf_unfiltered (gdb_stdlog, _("Try: %s%.2s%.38s\"\n"), -+ "zypper install -C \"debuginfo(build-id)=", -+ p - 2, p + 1); -+ } - } - } - diff --git a/rpm/gdb-6.6-buildid-locate-rpm.patch b/rpm/gdb-6.6-buildid-locate-rpm.patch deleted file mode 100644 index efaf989..0000000 --- a/rpm/gdb-6.6-buildid-locate-rpm.patch +++ /dev/null @@ -1,1048 +0,0 @@ -From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 -From: Fedora GDB patches -Date: Fri, 27 Oct 2017 21:07:50 +0200 -Subject: gdb-6.6-buildid-locate-rpm.patch - -;;=push+jan - -diff --git a/gdb/aclocal.m4 b/gdb/aclocal.m4 ---- a/gdb/aclocal.m4 -+++ b/gdb/aclocal.m4 -@@ -11,7 +11,223 @@ - # even the implied warranty of MERCHANTABILITY or FITNESS FOR A - # PARTICULAR PURPOSE. - -+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -+# serial 1 (pkg-config-0.24) -+# -+# Copyright © 2004 Scott James Remnant . -+# -+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+# -+# As a special exception to the GNU General Public License, if you -+# distribute this file as part of a program that contains a -+# configuration script generated by Autoconf, you may include it under -+# the same distribution terms that you use for the rest of that program. -+ -+# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -+# ---------------------------------- -+AC_DEFUN([PKG_PROG_PKG_CONFIG], -+[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) -+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) -+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) -+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) -+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) -+ -+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then -+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -+fi -+if test -n "$PKG_CONFIG"; then -+ _pkg_min_version=m4_default([$1], [0.9.0]) -+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) -+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then -+ AC_MSG_RESULT([yes]) -+ else -+ AC_MSG_RESULT([no]) -+ PKG_CONFIG="" -+ fi -+fi[]dnl -+])# PKG_PROG_PKG_CONFIG -+ -+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -+# -+# Check to see whether a particular set of modules exists. Similar -+# to PKG_CHECK_MODULES(), but does not set variables or print errors. -+# -+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -+# only at the first occurence in configure.ac, so if the first place -+# it's called might be skipped (such as if it is within an "if", you -+# have to call PKG_CHECK_EXISTS manually -+# -------------------------------------------------------------- -+AC_DEFUN([PKG_CHECK_EXISTS], -+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -+if test -n "$PKG_CONFIG" && \ -+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then -+ m4_default([$2], [:]) -+m4_ifvaln([$3], [else -+ $3])dnl -+fi]) -+ -+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -+# --------------------------------------------- -+m4_define([_PKG_CONFIG], -+[if test -n "$$1"; then -+ pkg_cv_[]$1="$$1" -+ elif test -n "$PKG_CONFIG"; then -+ PKG_CHECK_EXISTS([$3], -+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` -+ test "x$?" != "x0" && pkg_failed=yes ], -+ [pkg_failed=yes]) -+ else -+ pkg_failed=untried -+fi[]dnl -+])# _PKG_CONFIG -+ -+# _PKG_SHORT_ERRORS_SUPPORTED -+# ----------------------------- -+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], -+[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then -+ _pkg_short_errors_supported=yes -+else -+ _pkg_short_errors_supported=no -+fi[]dnl -+])# _PKG_SHORT_ERRORS_SUPPORTED -+ -+ -+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -+# [ACTION-IF-NOT-FOUND]) -+# -+# -+# Note that if there is a possibility the first call to -+# PKG_CHECK_MODULES might not happen, you should be sure to include an -+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -+# -+# -+# -------------------------------------------------------------- -+AC_DEFUN([PKG_CHECK_MODULES], -+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl -+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl -+ -+pkg_failed=no -+AC_MSG_CHECKING([for $1]) -+ -+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) -+_PKG_CONFIG([$1][_LIBS], [libs], [$2]) -+ -+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS -+and $1[]_LIBS to avoid the need to call pkg-config. -+See the pkg-config man page for more details.]) -+ -+if test $pkg_failed = yes; then -+ AC_MSG_RESULT([no]) -+ _PKG_SHORT_ERRORS_SUPPORTED -+ if test $_pkg_short_errors_supported = yes; then -+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` -+ else -+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` -+ fi -+ # Put the nasty error message in config.log where it belongs -+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD -+ -+ m4_default([$4], [AC_MSG_ERROR( -+[Package requirements ($2) were not met: -+ -+$$1_PKG_ERRORS -+ -+Consider adjusting the PKG_CONFIG_PATH environment variable if you -+installed software in a non-standard prefix. -+ -+_PKG_TEXT])[]dnl -+ ]) -+elif test $pkg_failed = untried; then -+ AC_MSG_RESULT([no]) -+ m4_default([$4], [AC_MSG_FAILURE( -+[The pkg-config script could not be found or is too old. Make sure it -+is in your PATH or set the PKG_CONFIG environment variable to the full -+path to pkg-config. -+ -+_PKG_TEXT -+ -+To get pkg-config, see .])[]dnl -+ ]) -+else -+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS -+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS -+ AC_MSG_RESULT([yes]) -+ $3 -+fi[]dnl -+])# PKG_CHECK_MODULES -+ -+ -+# PKG_INSTALLDIR(DIRECTORY) -+# ------------------------- -+# Substitutes the variable pkgconfigdir as the location where a module -+# should install pkg-config .pc files. By default the directory is -+# $libdir/pkgconfig, but the default can be changed by passing -+# DIRECTORY. The user can override through the --with-pkgconfigdir -+# parameter. -+AC_DEFUN([PKG_INSTALLDIR], -+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) -+m4_pushdef([pkg_description], -+ [pkg-config installation directory @<:@]pkg_default[@:>@]) -+AC_ARG_WITH([pkgconfigdir], -+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, -+ [with_pkgconfigdir=]pkg_default) -+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) -+m4_popdef([pkg_default]) -+m4_popdef([pkg_description]) -+]) dnl PKG_INSTALLDIR -+ -+ -+# PKG_NOARCH_INSTALLDIR(DIRECTORY) -+# ------------------------- -+# Substitutes the variable noarch_pkgconfigdir as the location where a -+# module should install arch-independent pkg-config .pc files. By -+# default the directory is $datadir/pkgconfig, but the default can be -+# changed by passing DIRECTORY. The user can override through the -+# --with-noarch-pkgconfigdir parameter. -+AC_DEFUN([PKG_NOARCH_INSTALLDIR], -+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) -+m4_pushdef([pkg_description], -+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) -+AC_ARG_WITH([noarch-pkgconfigdir], -+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, -+ [with_noarch_pkgconfigdir=]pkg_default) -+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) -+m4_popdef([pkg_default]) -+m4_popdef([pkg_description]) -+]) dnl PKG_NOARCH_INSTALLDIR -+ -+ -+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -+# ------------------------------------------- -+# Retrieves the value of the pkg-config variable for the given module. -+AC_DEFUN([PKG_CHECK_VAR], -+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl -+ -+_PKG_CONFIG([$1], [variable="][$3]["], [$2]) -+AS_VAR_COPY([$1], [pkg_cv_][$1]) -+ -+AS_VAR_IF([$1], [""], [$5], [$4])dnl -+])# PKG_CHECK_VAR -+ - m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -+ - # AM_AUX_DIR_EXPAND -*- Autoconf -*- - - # Copyright (C) 2001-2017 Free Software Foundation, Inc. -diff --git a/gdb/config.in b/gdb/config.in ---- a/gdb/config.in -+++ b/gdb/config.in -@@ -39,6 +39,9 @@ - /* Handle .ctf type-info sections */ - #undef ENABLE_LIBCTF - -+/* librpm version specific library name to dlopen. */ -+#undef DLOPEN_LIBRPM -+ - /* Define to 1 if translation of program messages to the user's native - language is requested. */ - #undef ENABLE_NLS -@@ -259,6 +262,9 @@ - /* Define if you have the mpfr library. */ - #undef HAVE_LIBMPFR - -+/* Define if librpm library is being used. */ -+#undef HAVE_LIBRPM -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LIBUNWIND_IA64_H - -diff --git a/gdb/configure b/gdb/configure ---- a/gdb/configure -+++ b/gdb/configure -@@ -775,6 +775,11 @@ TARGET_OBS - ENABLE_BFD_64_BIT_FALSE - ENABLE_BFD_64_BIT_TRUE - subdirs -+RPM_LIBS -+RPM_CFLAGS -+PKG_CONFIG_LIBDIR -+PKG_CONFIG_PATH -+PKG_CONFIG - GDB_DATADIR - DEBUGDIR - MAKEINFO_EXTRA_FLAGS -@@ -880,6 +885,7 @@ with_gdb_datadir - with_relocated_sources - with_auto_load_dir - with_auto_load_safe_path -+with_rpm - enable_targets - enable_64_bit_bfd - enable_gdbmi -@@ -959,6 +965,8 @@ PKG_CONFIG_PATH - PKG_CONFIG_LIBDIR - DEBUGINFOD_CFLAGS - DEBUGINFOD_LIBS -+RPM_CFLAGS -+RPM_LIBS - YACC - YFLAGS - XMKMF' -@@ -1635,6 +1643,8 @@ Optional Packages: - do not restrict auto-loaded files locations - --with-debuginfod Enable debuginfo lookups with debuginfod - (auto/yes/no) -+ --with-rpm query rpm database for missing debuginfos (yes/no, -+ def. auto=librpm.so) - --with-libunwind-ia64 use libunwind frame unwinding for ia64 targets - --with-curses use the curses library instead of the termcap - library -@@ -1715,6 +1725,8 @@ Some influential environment variables: - C compiler flags for DEBUGINFOD, overriding pkg-config - DEBUGINFOD_LIBS - linker flags for DEBUGINFOD, overriding pkg-config -+ RPM_CFLAGS C compiler flags for RPM, overriding pkg-config -+ RPM_LIBS linker flags for RPM, overriding pkg-config - YACC The `Yet Another Compiler Compiler' implementation to use. - Defaults to the first program found out of: `bison -y', `byacc', - `yacc'. -@@ -6634,6 +6646,494 @@ _ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_auto_load_safe_path" >&5 - $as_echo "$with_auto_load_safe_path" >&6; } - -+# Integration with rpm library to support missing debuginfo suggestions. -+# --without-rpm: Disable any rpm support. -+# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime. -+# Even with runtime missing `libname.so' GDB will still other run correctly. -+# Missing `libname.so' during ./configure will abort the configuration. -+# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific -+# minor version first such as `librpm-4.6.so' as minor version differences -+# mean API+ABI incompatibility. If the specific match versioned library name -+# could not be found still open dynamically at least `librpm.so'. -+# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try -+# to find librpm for compilation-time linking by pkg-config. GDB binary will -+# be probably linked with the version specific library (as `librpm-4.6.so'). -+# Failure to find librpm by pkg-config will abort the configuration. -+# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config -+# cannot find librpm use to the rpmless compilation (like `--without-rpm'). -+ -+ -+# Check whether --with-rpm was given. -+if test "${with_rpm+set}" = set; then : -+ withval=$with_rpm; -+else -+ with_rpm="auto" -+fi -+ -+ -+ -+ -+if test "x$with_rpm" != "xno"; then -+ if test "x$with_rpm" = "xyes"; then -+ LIBRPM="librpm.so" -+ RPM_REQUIRE=true -+ DLOPEN_REQUIRE=false -+ elif test "x$with_rpm" = "xauto"; then -+ LIBRPM="librpm.so" -+ RPM_REQUIRE=false -+ DLOPEN_REQUIRE=false -+ else -+ LIBRPM="$with_rpm" -+ RPM_REQUIRE=true -+ DLOPEN_REQUIRE=true -+ fi -+ LIBRPM_STRING='"'"$LIBRPM"'"' -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking specific librpm version" >&5 -+$as_echo_n "checking specific librpm version... " >&6; } -+ HAVE_DLOPEN_LIBRPM=false -+ save_LIBS="$LIBS" -+ LIBS="$LIBS -ldl" -+ if test "$cross_compiling" = yes; then : -+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -+as_fn_error "cannot run test program while cross compiling -+See \`config.log' for more details." "$LINENO" 5; } -+else -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+#include -+#include -+#include -+ -+int -+main () -+{ -+ -+ void *h; -+ const char *const *rpmverp; -+ FILE *f; -+ -+ f = fopen ("conftest.out", "w"); -+ if (!f) -+ { -+ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out", -+ strerror (errno)); -+ return 1; -+ } -+ h = dlopen ($LIBRPM_STRING, RTLD_LAZY); -+ if (!h) -+ { -+ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ()); -+ return 1; -+ } -+ rpmverp = dlsym (h, "RPMVERSION"); -+ if (!rpmverp) -+ { -+ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ()); -+ return 1; -+ } -+ fprintf (stderr, "RPMVERSION is: \""); -+ fprintf (stderr, "%s\"\n", *rpmverp); -+ -+ /* Try to find the specific librpm version only for "librpm.so" as we do -+ not know how to assemble the version string otherwise. */ -+ -+ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0) -+ { -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ else -+ { -+ char *h2_name; -+ void *h2; -+ int major, minor; -+ -+ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2) -+ { -+ fprintf (stderr, "Unable to parse RPMVERSION.\n"); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ /* Avoid the square brackets by malloc. */ -+ h2_name = malloc (64); -+ sprintf (h2_name, "librpm-%d.%d.so", major, minor); -+ h2 = dlopen (h2_name, RTLD_LAZY); -+ if (!h2) -+ { -+ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ()); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ if (h2 != h) -+ { -+ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n", -+ $LIBRPM_STRING, h2_name); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ /* Found the valid .so name with a specific version. */ -+ fprintf (f, "%s\n", h2_name); -+ return 0; -+ } -+ -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_run "$LINENO"; then : -+ -+ DLOPEN_LIBRPM="`cat conftest.out`" -+ if test "x$DLOPEN_LIBRPM" != "x"; then -+ HAVE_DLOPEN_LIBRPM=true -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLOPEN_LIBRPM" >&5 -+$as_echo "$DLOPEN_LIBRPM" >&6; } -+ fi -+ -+fi -+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ -+ conftest.$ac_objext conftest.beam conftest.$ac_ext -+fi -+ -+ rm -f conftest.out -+ -+ -+ -+ if $HAVE_DLOPEN_LIBRPM; then -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking rpm library API compatibility" >&5 -+$as_echo_n "checking rpm library API compatibility... " >&6; } -+ # The compilation requires -Werror to verify anything. -+ save_CFLAGS="$CFLAGS" -+ CFLAGS="$CFLAGS -Werror" -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Duplicate here the declarations to verify they match "elfread.c". */ -+#include -+#include -+#include -+#include -+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); -+extern int rpmReadConfigFiles(const char * file, const char * target); -+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); -+extern Header rpmdbNextIterator(rpmdbMatchIterator mi); -+extern rpmts rpmtsCreate(void); -+extern rpmts rpmtsFree(rpmts ts); -+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, -+ const void * keyp, size_t keylen); -+ -+int -+main () -+{ -+ -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ -+ LIBRPM_COMPAT=true -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -+$as_echo "yes" >&6; } -+ -+else -+ -+ LIBRPM_COMPAT=false -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ CFLAGS="$save_CFLAGS" -+ -+ if ! $LIBRPM_COMPAT; then -+ HAVE_DLOPEN_LIBRPM=false -+ fi -+ fi -+ -+ if $HAVE_DLOPEN_LIBRPM; then -+ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"' -+ -+cat >>confdefs.h <<_ACEOF -+#define DLOPEN_LIBRPM $DLOPEN_LIBRPM_STRING -+_ACEOF -+ -+ -+$as_echo "#define HAVE_LIBRPM 1" >>confdefs.h -+ -+ else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ LIBS="$save_LIBS" -+ if $DLOPEN_REQUIRE; then -+ as_fn_error "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5 -+ fi -+ -+ -+ -+ -+ -+ -+ -+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then -+ if test -n "$ac_tool_prefix"; then -+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -+$as_echo_n "checking for $ac_word... " >&6; } -+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then : -+ $as_echo_n "(cached) " >&6 -+else -+ case $PKG_CONFIG in -+ [\\/]* | ?:[\\/]*) -+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. -+ ;; -+ *) -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -+ break 2 -+ fi -+done -+ done -+IFS=$as_save_IFS -+ -+ ;; -+esac -+fi -+PKG_CONFIG=$ac_cv_path_PKG_CONFIG -+if test -n "$PKG_CONFIG"; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -+$as_echo "$PKG_CONFIG" >&6; } -+else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+fi -+ -+ -+fi -+if test -z "$ac_cv_path_PKG_CONFIG"; then -+ ac_pt_PKG_CONFIG=$PKG_CONFIG -+ # Extract the first word of "pkg-config", so it can be a program name with args. -+set dummy pkg-config; ac_word=$2 -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -+$as_echo_n "checking for $ac_word... " >&6; } -+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then : -+ $as_echo_n "(cached) " >&6 -+else -+ case $ac_pt_PKG_CONFIG in -+ [\\/]* | ?:[\\/]*) -+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. -+ ;; -+ *) -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -+ break 2 -+ fi -+done -+ done -+IFS=$as_save_IFS -+ -+ ;; -+esac -+fi -+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -+if test -n "$ac_pt_PKG_CONFIG"; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -+$as_echo "$ac_pt_PKG_CONFIG" >&6; } -+else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+fi -+ -+ if test "x$ac_pt_PKG_CONFIG" = x; then -+ PKG_CONFIG="" -+ else -+ case $cross_compiling:$ac_tool_warned in -+yes:) -+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -+ac_tool_warned=yes ;; -+esac -+ PKG_CONFIG=$ac_pt_PKG_CONFIG -+ fi -+else -+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -+fi -+ -+fi -+if test -n "$PKG_CONFIG"; then -+ _pkg_min_version=0.9.0 -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } -+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -+$as_echo "yes" >&6; } -+ else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ PKG_CONFIG="" -+ fi -+fi -+ -+pkg_failed=no -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RPM" >&5 -+$as_echo_n "checking for RPM... " >&6; } -+ -+if test -n "$RPM_CFLAGS"; then -+ pkg_cv_RPM_CFLAGS="$RPM_CFLAGS" -+ elif test -n "$PKG_CONFIG"; then -+ if test -n "$PKG_CONFIG" && \ -+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5 -+ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5 -+ ac_status=$? -+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 -+ test $ac_status = 0; }; then -+ pkg_cv_RPM_CFLAGS=`$PKG_CONFIG --cflags "rpm" 2>/dev/null` -+ test "x$?" != "x0" && pkg_failed=yes -+else -+ pkg_failed=yes -+fi -+ else -+ pkg_failed=untried -+fi -+if test -n "$RPM_LIBS"; then -+ pkg_cv_RPM_LIBS="$RPM_LIBS" -+ elif test -n "$PKG_CONFIG"; then -+ if test -n "$PKG_CONFIG" && \ -+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5 -+ ($PKG_CONFIG --exists --print-errors "rpm") 2>&5 -+ ac_status=$? -+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 -+ test $ac_status = 0; }; then -+ pkg_cv_RPM_LIBS=`$PKG_CONFIG --libs "rpm" 2>/dev/null` -+ test "x$?" != "x0" && pkg_failed=yes -+else -+ pkg_failed=yes -+fi -+ else -+ pkg_failed=untried -+fi -+ -+ -+ -+if test $pkg_failed = yes; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ -+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then -+ _pkg_short_errors_supported=yes -+else -+ _pkg_short_errors_supported=no -+fi -+ if test $_pkg_short_errors_supported = yes; then -+ RPM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "rpm" 2>&1` -+ else -+ RPM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "rpm" 2>&1` -+ fi -+ # Put the nasty error message in config.log where it belongs -+ echo "$RPM_PKG_ERRORS" >&5 -+ -+ HAVE_LIBRPM=false -+elif test $pkg_failed = untried; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ HAVE_LIBRPM=false -+else -+ RPM_CFLAGS=$pkg_cv_RPM_CFLAGS -+ RPM_LIBS=$pkg_cv_RPM_LIBS -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -+$as_echo "yes" >&6; } -+ HAVE_LIBRPM=true -+fi -+ -+ if $HAVE_LIBRPM; then -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking rpm library API compatibility" >&5 -+$as_echo_n "checking rpm library API compatibility... " >&6; } -+ # The compilation requires -Werror to verify anything. -+ save_CFLAGS="$CFLAGS" -+ CFLAGS="$CFLAGS -Werror" -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Duplicate here the declarations to verify they match "elfread.c". */ -+#include -+#include -+#include -+#include -+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); -+extern int rpmReadConfigFiles(const char * file, const char * target); -+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); -+extern Header rpmdbNextIterator(rpmdbMatchIterator mi); -+extern rpmts rpmtsCreate(void); -+extern rpmts rpmtsFree(rpmts ts); -+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, -+ const void * keyp, size_t keylen); -+ -+int -+main () -+{ -+ -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ -+ LIBRPM_COMPAT=true -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -+$as_echo "yes" >&6; } -+ -+else -+ -+ LIBRPM_COMPAT=false -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ CFLAGS="$save_CFLAGS" -+ -+ if ! $LIBRPM_COMPAT; then -+ HAVE_LIBRPM=false -+ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB" -+ fi -+ fi -+ -+ if $HAVE_LIBRPM; then -+ -+$as_echo "#define HAVE_LIBRPM 1" >>confdefs.h -+ -+ CFLAGS="$CFLAGS $RPM_CFLAGS" -+ LIBS="$LIBS $RPM_LIBS" -+ else -+ if $RPM_REQUIRE; then -+ as_fn_error "$RPM_PKG_ERRORS" "$LINENO" 5 -+ else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $RPM_PKG_ERRORS" >&5 -+$as_echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;} -+ fi -+ fi -+ fi -+fi -+ - - - subdirs="$subdirs testsuite" -diff --git a/gdb/configure.ac b/gdb/configure.ac ---- a/gdb/configure.ac -+++ b/gdb/configure.ac -@@ -153,6 +153,199 @@ AC_DEFINE_DIR(AUTO_LOAD_SAFE_PATH, escape_dir, - [Directories safe to hold auto-loaded files.]) - AC_MSG_RESULT([$with_auto_load_safe_path]) - -+# Integration with rpm library to support missing debuginfo suggestions. -+# --without-rpm: Disable any rpm support. -+# --with-rpm=libname.so: Try to dynamically open `libname.so' during runtime. -+# Even with runtime missing `libname.so' GDB will still other run correctly. -+# Missing `libname.so' during ./configure will abort the configuration. -+# --with-rpm=librpm.so: Like `--with-rpm=libname.so' but try to find specific -+# minor version first such as `librpm-4.6.so' as minor version differences -+# mean API+ABI incompatibility. If the specific match versioned library name -+# could not be found still open dynamically at least `librpm.so'. -+# --with-rpm: Like `--with-rpm=librpm.so' but if any of its detection fails try -+# to find librpm for compilation-time linking by pkg-config. GDB binary will -+# be probably linked with the version specific library (as `librpm-4.6.so'). -+# Failure to find librpm by pkg-config will abort the configuration. -+# (default) --with-rpm=auto: Like `--with-rpm=librpm.so' but if even pkg-config -+# cannot find librpm use to the rpmless compilation (like `--without-rpm'). -+ -+AC_ARG_WITH([rpm], -+ [AS_HELP_STRING([--with-rpm], -+ [query rpm database for missing debuginfos (yes/no, def. auto=librpm.so)])], [], [with_rpm="auto"]) -+ -+m4_pattern_allow([^AC_MSG_ERROR$]) -+m4_pattern_allow([^AC_MSG_WARN$]) -+if test "x$with_rpm" != "xno"; then -+ if test "x$with_rpm" = "xyes"; then -+ LIBRPM="librpm.so" -+ RPM_REQUIRE=true -+ DLOPEN_REQUIRE=false -+ elif test "x$with_rpm" = "xauto"; then -+ LIBRPM="librpm.so" -+ RPM_REQUIRE=false -+ DLOPEN_REQUIRE=false -+ else -+ LIBRPM="$with_rpm" -+ RPM_REQUIRE=true -+ DLOPEN_REQUIRE=true -+ fi -+ LIBRPM_STRING='"'"$LIBRPM"'"' -+ -+ AC_MSG_CHECKING([specific librpm version]) -+ HAVE_DLOPEN_LIBRPM=false -+ save_LIBS="$LIBS" -+ LIBS="$LIBS -ldl" -+ AC_RUN_IFELSE(AC_LANG_PROGRAM([[ -+#include -+#include -+#include -+ ]], [[ -+ void *h; -+ const char *const *rpmverp; -+ FILE *f; -+ -+ f = fopen ("conftest.out", "w"); -+ if (!f) -+ { -+ fprintf (stderr, "Cannot write \"%s\": %s\n", "conftest.out", -+ strerror (errno)); -+ return 1; -+ } -+ h = dlopen ($LIBRPM_STRING, RTLD_LAZY); -+ if (!h) -+ { -+ fprintf (stderr, "dlopen (\"%s\"): %s\n", $LIBRPM_STRING, dlerror ()); -+ return 1; -+ } -+ rpmverp = dlsym (h, "RPMVERSION"); -+ if (!rpmverp) -+ { -+ fprintf (stderr, "dlsym (\"RPMVERSION\"): %s\n", dlerror ()); -+ return 1; -+ } -+ fprintf (stderr, "RPMVERSION is: \""); -+ fprintf (stderr, "%s\"\n", *rpmverp); -+ -+ /* Try to find the specific librpm version only for "librpm.so" as we do -+ not know how to assemble the version string otherwise. */ -+ -+ if (strcmp ("librpm.so", $LIBRPM_STRING) != 0) -+ { -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ else -+ { -+ char *h2_name; -+ void *h2; -+ int major, minor; -+ -+ if (sscanf (*rpmverp, "%d.%d", &major, &minor) != 2) -+ { -+ fprintf (stderr, "Unable to parse RPMVERSION.\n"); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ /* Avoid the square brackets by malloc. */ -+ h2_name = malloc (64); -+ sprintf (h2_name, "librpm-%d.%d.so", major, minor); -+ h2 = dlopen (h2_name, RTLD_LAZY); -+ if (!h2) -+ { -+ fprintf (stderr, "dlopen (\"%s\"): %s\n", h2_name, dlerror ()); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ if (h2 != h) -+ { -+ fprintf (stderr, "dlopen of \"%s\" and \"%s\" are different.\n", -+ $LIBRPM_STRING, h2_name); -+ fprintf (f, "%s\n", $LIBRPM_STRING); -+ return 0; -+ } -+ /* Found the valid .so name with a specific version. */ -+ fprintf (f, "%s\n", h2_name); -+ return 0; -+ } -+ ]]), [ -+ DLOPEN_LIBRPM="`cat conftest.out`" -+ if test "x$DLOPEN_LIBRPM" != "x"; then -+ HAVE_DLOPEN_LIBRPM=true -+ AC_MSG_RESULT($DLOPEN_LIBRPM) -+ fi -+ ]) -+ rm -f conftest.out -+ -+ m4_define([CHECK_LIBRPM_COMPAT], [ -+ AC_MSG_CHECKING([rpm library API compatibility]) -+ # The compilation requires -Werror to verify anything. -+ save_CFLAGS="$CFLAGS" -+ CFLAGS="$CFLAGS -Werror" -+ AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[ -+/* Duplicate here the declarations to verify they match "elfread.c". */ -+#include -+#include -+#include -+#include -+extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); -+extern int rpmReadConfigFiles(const char * file, const char * target); -+extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); -+extern Header rpmdbNextIterator(rpmdbMatchIterator mi); -+extern rpmts rpmtsCreate(void); -+extern rpmts rpmtsFree(rpmts ts); -+extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, -+ const void * keyp, size_t keylen); -+ ]]), [ -+ LIBRPM_COMPAT=true -+ AC_MSG_RESULT(yes) -+ ], [ -+ LIBRPM_COMPAT=false -+ AC_MSG_RESULT(no) -+ ]) -+ CFLAGS="$save_CFLAGS" -+ ]) -+ -+ if $HAVE_DLOPEN_LIBRPM; then -+ CHECK_LIBRPM_COMPAT -+ if ! $LIBRPM_COMPAT; then -+ HAVE_DLOPEN_LIBRPM=false -+ fi -+ fi -+ -+ if $HAVE_DLOPEN_LIBRPM; then -+ DLOPEN_LIBRPM_STRING='"'"$DLOPEN_LIBRPM"'"' -+ AC_DEFINE_UNQUOTED(DLOPEN_LIBRPM, $DLOPEN_LIBRPM_STRING, [librpm version specific library name to dlopen.]) -+ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.]) -+ else -+ AC_MSG_RESULT(no) -+ LIBS="$save_LIBS" -+ if $DLOPEN_REQUIRE; then -+ AC_MSG_ERROR([Specific name $LIBRPM was requested but it could not be opened.]) -+ fi -+ PKG_CHECK_MODULES(RPM, rpm, [HAVE_LIBRPM=true], [HAVE_LIBRPM=false]) -+ -+ if $HAVE_LIBRPM; then -+ CHECK_LIBRPM_COMPAT -+ if ! $LIBRPM_COMPAT; then -+ HAVE_LIBRPM=false -+ RPM_PKG_ERRORS="Found $LIBRPM API is incompatibile with this GDB" -+ fi -+ fi -+ -+ if $HAVE_LIBRPM; then -+ AC_DEFINE(HAVE_LIBRPM, 1, [Define if librpm library is being used.]) -+ CFLAGS="$CFLAGS $RPM_CFLAGS" -+ LIBS="$LIBS $RPM_LIBS" -+ else -+ if $RPM_REQUIRE; then -+ AC_MSG_ERROR($RPM_PKG_ERRORS) -+ else -+ AC_MSG_WARN($RPM_PKG_ERRORS) -+ fi -+ fi -+ fi -+fi -+ - AC_CONFIG_SUBDIRS(testsuite) - - # Check whether to support alternative target configurations -diff --git a/gdb/event-top.c b/gdb/event-top.c ---- a/gdb/event-top.c -+++ b/gdb/event-top.c -@@ -42,6 +42,7 @@ - #include "gdbsupport/gdb-sigmask.h" - #include "async-event.h" - #include "bt-utils.h" -+#include "symfile.h" - - /* readline include files. */ - #include "readline/readline.h" -@@ -374,6 +375,8 @@ display_gdb_prompt (const char *new_prompt) - /* Reset the nesting depth used when trace-commands is set. */ - reset_command_nest_depth (); - -+ debug_flush_missing (); -+ - /* Do not call the python hook on an explicit prompt change as - passed to this function, as this forms a secondary/local prompt, - IE, displayed but not set. */ -@@ -800,7 +803,10 @@ command_line_handler (gdb::unique_xmalloc_ptr &&rl) - command_handler (cmd); - - if (ui->prompt_state != PROMPTED) -- display_gdb_prompt (0); -+ { -+ debug_flush_missing (); -+ display_gdb_prompt (0); -+ } - } - } - -diff --git a/gdb/symfile.h b/gdb/symfile.h ---- a/gdb/symfile.h -+++ b/gdb/symfile.h -@@ -342,6 +342,7 @@ extern void generic_load (const char *args, int from_tty); - /* build-id support. */ - extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr); - extern void debug_print_missing (const char *binary, const char *debug); -+extern void debug_flush_missing (void); - #define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file") - - /* From minidebug.c. */ diff --git a/rpm/gdb-6.6-buildid-locate-solib-missing-ids.patch b/rpm/gdb-6.6-buildid-locate-solib-missing-ids.patch deleted file mode 100644 index df45319..0000000 --- a/rpm/gdb-6.6-buildid-locate-solib-missing-ids.patch +++ /dev/null @@ -1,238 +0,0 @@ -From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 -From: Fedora GDB patches -Date: Fri, 27 Oct 2017 21:07:50 +0200 -Subject: gdb-6.6-buildid-locate-solib-missing-ids.patch - -;; Fix loading of core files without build-ids but with build-ids in executables. -;; Load strictly build-id-checked core files only if no executable is specified -;; (Jan Kratochvil, RH BZ 1339862). -;;=push+jan - -gdb returns an incorrect back trace when applying a debuginfo -https://bugzilla.redhat.com/show_bug.cgi?id=1339862 - -diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c ---- a/gdb/solib-svr4.c -+++ b/gdb/solib-svr4.c -@@ -1250,14 +1250,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, - } - - { -- struct bfd_build_id *build_id; -+ struct bfd_build_id *build_id = NULL; - - strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1); - newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - /* May get overwritten below. */ - strcpy (newobj->so_name, newobj->so_original_name); - -- build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld); -+ /* In the case the main executable was found according to its build-id -+ (from a core file) prevent loading a different build of a library -+ with accidentally the same SO_NAME. -+ -+ It suppresses bogus backtraces (and prints "??" there instead) if -+ the on-disk files no longer match the running program version. -+ -+ If the main executable was not loaded according to its build-id do -+ not do any build-id checking of the libraries. There may be missing -+ build-ids dumped in the core file and we would map all the libraries -+ to the only existing file loaded that time - the executable. */ -+ if (current_program_space->symfile_object_file != NULL -+ && (current_program_space->symfile_object_file->flags -+ & OBJF_BUILD_ID_CORE_LOADED) != 0) -+ build_id = build_id_addr_get (li->l_ld); - if (build_id != NULL) - { - char *name, *build_id_filename; -@@ -1272,23 +1286,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, - xfree (name); - } - else -- { -- debug_print_missing (newobj->so_name, build_id_filename); -- -- /* In the case the main executable was found according to -- its build-id (from a core file) prevent loading -- a different build of a library with accidentally the -- same SO_NAME. -- -- It suppresses bogus backtraces (and prints "??" there -- instead) if the on-disk files no longer match the -- running program version. */ -- -- if (current_program_space->symfile_object_file != NULL -- && (current_program_space->symfile_object_file->flags -- & OBJF_BUILD_ID_CORE_LOADED) != 0) -- newobj->so_name[0] = 0; -- } -+ debug_print_missing (newobj->so_name, build_id_filename); - - xfree (build_id_filename); - xfree (build_id); -diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c -new file mode 100644 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c -@@ -0,0 +1,21 @@ -+/* Copyright 2010 Free Software Foundation, Inc. -+ -+ This file is part of GDB. -+ -+ 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 3 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, see . */ -+ -+void -+lib (void) -+{ -+} -diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c -new file mode 100644 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c -@@ -0,0 +1,25 @@ -+/* Copyright 2010 Free Software Foundation, Inc. -+ -+ This file is part of GDB. -+ -+ 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 3 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, see . */ -+ -+extern void lib (void); -+ -+int -+main (void) -+{ -+ lib (); -+ return 0; -+} -diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp -new file mode 100644 ---- /dev/null -+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp -@@ -0,0 +1,105 @@ -+# Copyright 2016 Free Software Foundation, Inc. -+ -+# 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 3 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, see . -+ -+if {[skip_shlib_tests]} { -+ return 0 -+} -+ -+set testfile "gcore-buildid-exec-but-not-solib" -+set srcmainfile ${testfile}-main.c -+set srclibfile ${testfile}-lib.c -+set libfile [standard_output_file ${testfile}-lib.so] -+set objfile [standard_output_file ${testfile}-main.o] -+set executable ${testfile}-main -+set binfile [standard_output_file ${executable}] -+set gcorefile [standard_output_file ${executable}.gcore] -+set outdir [file dirname $binfile] -+ -+if { [gdb_compile_shlib ${srcdir}/${subdir}/${srclibfile} ${libfile} "debug additional_flags=-Wl,--build-id"] != "" -+ || [gdb_compile ${srcdir}/${subdir}/${srcmainfile} ${objfile} object {debug}] != "" } { -+ unsupported "-Wl,--build-id compilation failed" -+ return -1 -+} -+set opts [list debug shlib=${libfile} "additional_flags=-Wl,--build-id"] -+if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } { -+ unsupported "-Wl,--build-id compilation failed" -+ return -1 -+} -+ -+clean_restart $executable -+gdb_load_shlib $libfile -+ -+# Does this gdb support gcore? -+set test "help gcore" -+gdb_test_multiple $test $test { -+ -re "Undefined command: .gcore.*\r\n$gdb_prompt $" { -+ # gcore command not supported -- nothing to test here. -+ unsupported "gdb does not support gcore on this target" -+ return -1; -+ } -+ -re "Save a core file .*\r\n$gdb_prompt $" { -+ pass $test -+ } -+} -+ -+if { ![runto lib] } then { -+ return -1 -+} -+ -+set escapedfilename [string_to_regexp ${gcorefile}] -+ -+set test "save a corefile" -+gdb_test_multiple "gcore ${gcorefile}" $test { -+ -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" { -+ pass $test -+ } -+ -re "Can't create a corefile\r\n$gdb_prompt $" { -+ unsupported $test -+ return -1 -+ } -+} -+ -+# Now restart gdb and load the corefile. -+ -+clean_restart $executable -+gdb_load_shlib $libfile -+ -+set buildid [build_id_debug_filename_get $libfile] -+ -+regsub {\.debug$} $buildid {} buildid -+ -+set debugdir [standard_output_file ${testfile}-debugdir] -+file delete -force -- $debugdir -+ -+file mkdir $debugdir/[file dirname $libfile] -+file copy $libfile $debugdir/${libfile} -+ -+file mkdir $debugdir/[file dirname $buildid] -+file copy $libfile $debugdir/${buildid} -+ -+remote_exec build "ln -s /lib ${debugdir}/" -+remote_exec build "ln -s /lib64 ${debugdir}/" -+# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2 -+ -+gdb_test "set solib-absolute-prefix $debugdir" -+ -+gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory" -+ -+gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile" -+ -+gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded" -+ -+gdb_test "bt" -+gdb_test "info shared" diff --git a/rpm/gdb-6.6-buildid-locate.patch b/rpm/gdb-6.6-buildid-locate.patch deleted file mode 100644 index 6229244..0000000 --- a/rpm/gdb-6.6-buildid-locate.patch +++ /dev/null @@ -1,1908 +0,0 @@ -From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 -From: Fedora GDB patches -Date: Fri, 27 Oct 2017 21:07:50 +0200 -Subject: gdb-6.6-buildid-locate.patch - -;; New locating of the matching binaries from the pure core file (build-id). -;;=push+jan - -diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h ---- a/bfd/libbfd-in.h -+++ b/bfd/libbfd-in.h -@@ -115,7 +115,7 @@ static inline char * - bfd_strdup (const char *str) - { - size_t len = strlen (str) + 1; -- char *buf = bfd_malloc (len); -+ char *buf = (char *) bfd_malloc (len); - if (buf != NULL) - memcpy (buf, str, len); - return buf; -diff --git a/bfd/libbfd.h b/bfd/libbfd.h ---- a/bfd/libbfd.h -+++ b/bfd/libbfd.h -@@ -120,7 +120,7 @@ static inline char * - bfd_strdup (const char *str) - { - size_t len = strlen (str) + 1; -- char *buf = bfd_malloc (len); -+ char *buf = (char *) bfd_malloc (len); - if (buf != NULL) - memcpy (buf, str, len); - return buf; -diff --git a/gdb/build-id.c b/gdb/build-id.c ---- a/gdb/build-id.c -+++ b/gdb/build-id.c -@@ -24,13 +24,71 @@ - #include "gdbsupport/gdb_vecs.h" - #include "symfile.h" - #include "objfiles.h" -+#include -+#include "elf-bfd.h" -+#include "elf/common.h" -+#include "elf/external.h" -+#include "elf/internal.h" - #include "filenames.h" -+#include "gdb_bfd.h" -+#include "gdbcmd.h" - #include "gdbcore.h" -+#include "inferior.h" -+#include "objfiles.h" -+#include "observable.h" -+#include "symfile.h" -+ -+#define BUILD_ID_VERBOSE_NONE 0 -+#define BUILD_ID_VERBOSE_FILENAMES 1 -+#define BUILD_ID_VERBOSE_BINARY_PARSE 2 -+static int build_id_verbose = BUILD_ID_VERBOSE_FILENAMES; -+static void -+show_build_id_verbose (struct ui_file *file, int from_tty, -+ struct cmd_list_element *c, const char *value) -+{ -+ fprintf_filtered (file, _("Verbosity level of the build-id locator is %s.\n"), -+ value); -+} -+/* Locate NT_GNU_BUILD_ID and return its matching debug filename. -+ FIXME: NOTE decoding should be unified with the BFD core notes decoding. */ -+ -+static struct bfd_build_id * -+build_id_buf_get (bfd *templ, gdb_byte *buf, bfd_size_type size) -+{ -+ bfd_byte *p; -+ -+ p = buf; -+ while (p < buf + size) -+ { -+ /* FIXME: bad alignment assumption. */ -+ Elf_External_Note *xnp = (Elf_External_Note *) p; -+ size_t namesz = H_GET_32 (templ, xnp->namesz); -+ size_t descsz = H_GET_32 (templ, xnp->descsz); -+ bfd_byte *descdata = (gdb_byte *) xnp->name + BFD_ALIGN (namesz, 4); -+ -+ if (H_GET_32 (templ, xnp->type) == NT_GNU_BUILD_ID -+ && namesz == sizeof "GNU" -+ && memcmp (xnp->name, "GNU", sizeof "GNU") == 0) -+ { -+ size_t sz = descsz; -+ gdb_byte *data = (gdb_byte *) descdata; -+ struct bfd_build_id *retval; -+ -+ retval = (struct bfd_build_id *) xmalloc (sizeof *retval - 1 + sz); -+ retval->size = sz; -+ memcpy (retval->data, data, sz); -+ -+ return retval; -+ } -+ p = descdata + BFD_ALIGN (descsz, 4); -+ } -+ return NULL; -+} - - /* See build-id.h. */ - - const struct bfd_build_id * --build_id_bfd_get (bfd *abfd) -+build_id_bfd_shdr_get (bfd *abfd) - { - if (!bfd_check_format (abfd, bfd_object) - && !bfd_check_format (abfd, bfd_core)) -@@ -43,6 +101,348 @@ build_id_bfd_get (bfd *abfd) - return NULL; - } - -+/* Core files may have missing (corrupt) SHDR but PDHR is correct there. -+ bfd_elf_bfd_from_remote_memory () has too much overhead by -+ allocating/reading all the available ELF PT_LOADs. */ -+ -+static struct bfd_build_id * -+build_id_phdr_get (bfd *templ, bfd_vma loadbase, unsigned e_phnum, -+ Elf_Internal_Phdr *i_phdr) -+{ -+ int i; -+ struct bfd_build_id *retval = NULL; -+ -+ for (i = 0; i < e_phnum; i++) -+ if (i_phdr[i].p_type == PT_NOTE && i_phdr[i].p_filesz > 0) -+ { -+ Elf_Internal_Phdr *hdr = &i_phdr[i]; -+ gdb_byte *buf; -+ int err; -+ -+ buf = (gdb_byte *) xmalloc (hdr->p_filesz); -+ err = target_read_memory (loadbase + i_phdr[i].p_vaddr, buf, -+ hdr->p_filesz); -+ if (err == 0) -+ retval = build_id_buf_get (templ, buf, hdr->p_filesz); -+ else -+ retval = NULL; -+ xfree (buf); -+ if (retval != NULL) -+ break; -+ } -+ return retval; -+} -+ -+/* First we validate the file by reading in the ELF header and checking -+ the magic number. */ -+ -+static inline bfd_boolean -+elf_file_p (Elf64_External_Ehdr *x_ehdrp64) -+{ -+ gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)); -+ gdb_assert (offsetof (Elf64_External_Ehdr, e_ident) -+ == offsetof (Elf32_External_Ehdr, e_ident)); -+ gdb_assert (sizeof (((Elf64_External_Ehdr *) 0)->e_ident) -+ == sizeof (((Elf32_External_Ehdr *) 0)->e_ident)); -+ -+ return ((x_ehdrp64->e_ident[EI_MAG0] == ELFMAG0) -+ && (x_ehdrp64->e_ident[EI_MAG1] == ELFMAG1) -+ && (x_ehdrp64->e_ident[EI_MAG2] == ELFMAG2) -+ && (x_ehdrp64->e_ident[EI_MAG3] == ELFMAG3)); -+} -+ -+/* Translate an ELF file header in external format into an ELF file header in -+ internal format. */ -+ -+#define H_GET_WORD(bfd, ptr) (is64 ? H_GET_64 (bfd, (ptr)) \ -+ : H_GET_32 (bfd, (ptr))) -+#define H_GET_SIGNED_WORD(bfd, ptr) (is64 ? H_GET_S64 (bfd, (ptr)) \ -+ : H_GET_S32 (bfd, (ptr))) -+ -+static void -+elf_swap_ehdr_in (bfd *abfd, -+ const Elf64_External_Ehdr *src64, -+ Elf_Internal_Ehdr *dst) -+{ -+ int is64 = bfd_get_arch_size (abfd) == 64; -+#define SRC(field) (is64 ? src64->field \ -+ : ((const Elf32_External_Ehdr *) src64)->field) -+ -+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; -+ memcpy (dst->e_ident, SRC (e_ident), EI_NIDENT); -+ dst->e_type = H_GET_16 (abfd, SRC (e_type)); -+ dst->e_machine = H_GET_16 (abfd, SRC (e_machine)); -+ dst->e_version = H_GET_32 (abfd, SRC (e_version)); -+ if (signed_vma) -+ dst->e_entry = H_GET_SIGNED_WORD (abfd, SRC (e_entry)); -+ else -+ dst->e_entry = H_GET_WORD (abfd, SRC (e_entry)); -+ dst->e_phoff = H_GET_WORD (abfd, SRC (e_phoff)); -+ dst->e_shoff = H_GET_WORD (abfd, SRC (e_shoff)); -+ dst->e_flags = H_GET_32 (abfd, SRC (e_flags)); -+ dst->e_ehsize = H_GET_16 (abfd, SRC (e_ehsize)); -+ dst->e_phentsize = H_GET_16 (abfd, SRC (e_phentsize)); -+ dst->e_phnum = H_GET_16 (abfd, SRC (e_phnum)); -+ dst->e_shentsize = H_GET_16 (abfd, SRC (e_shentsize)); -+ dst->e_shnum = H_GET_16 (abfd, SRC (e_shnum)); -+ dst->e_shstrndx = H_GET_16 (abfd, SRC (e_shstrndx)); -+ -+#undef SRC -+} -+ -+/* Translate an ELF program header table entry in external format into an -+ ELF program header table entry in internal format. */ -+ -+static void -+elf_swap_phdr_in (bfd *abfd, -+ const Elf64_External_Phdr *src64, -+ Elf_Internal_Phdr *dst) -+{ -+ int is64 = bfd_get_arch_size (abfd) == 64; -+#define SRC(field) (is64 ? src64->field \ -+ : ((const Elf32_External_Phdr *) src64)->field) -+ -+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma; -+ -+ dst->p_type = H_GET_32 (abfd, SRC (p_type)); -+ dst->p_flags = H_GET_32 (abfd, SRC (p_flags)); -+ dst->p_offset = H_GET_WORD (abfd, SRC (p_offset)); -+ if (signed_vma) -+ { -+ dst->p_vaddr = H_GET_SIGNED_WORD (abfd, SRC (p_vaddr)); -+ dst->p_paddr = H_GET_SIGNED_WORD (abfd, SRC (p_paddr)); -+ } -+ else -+ { -+ dst->p_vaddr = H_GET_WORD (abfd, SRC (p_vaddr)); -+ dst->p_paddr = H_GET_WORD (abfd, SRC (p_paddr)); -+ } -+ dst->p_filesz = H_GET_WORD (abfd, SRC (p_filesz)); -+ dst->p_memsz = H_GET_WORD (abfd, SRC (p_memsz)); -+ dst->p_align = H_GET_WORD (abfd, SRC (p_align)); -+ -+#undef SRC -+} -+ -+#undef H_GET_SIGNED_WORD -+#undef H_GET_WORD -+ -+static Elf_Internal_Phdr * -+elf_get_phdr (bfd *templ, bfd_vma ehdr_vma, unsigned *e_phnum_pointer, -+ bfd_vma *loadbase_pointer) -+{ -+ /* sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr) */ -+ Elf64_External_Ehdr x_ehdr64; /* Elf file header, external form */ -+ Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ -+ bfd_size_type x_phdrs_size; -+ gdb_byte *x_phdrs_ptr; -+ Elf_Internal_Phdr *i_phdrs; -+ int err; -+ unsigned int i; -+ bfd_vma loadbase; -+ int loadbase_set; -+ -+ gdb_assert (templ != NULL); -+ gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)); -+ -+ /* Read in the ELF header in external format. */ -+ err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr64, sizeof x_ehdr64); -+ if (err) -+ { -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Error reading ELF header at address 0x%lx"), -+ (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ -+ /* Now check to see if we have a valid ELF file, and one that BFD can -+ make use of. The magic number must match, the address size ('class') -+ and byte-swapping must match our XVEC entry. */ -+ -+ if (! elf_file_p (&x_ehdr64) -+ || x_ehdr64.e_ident[EI_VERSION] != EV_CURRENT -+ || !((bfd_get_arch_size (templ) == 64 -+ && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS64) -+ || (bfd_get_arch_size (templ) == 32 -+ && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS32))) -+ { -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Unrecognized ELF header at address 0x%lx"), -+ (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ -+ /* Check that file's byte order matches xvec's */ -+ switch (x_ehdr64.e_ident[EI_DATA]) -+ { -+ case ELFDATA2MSB: /* Big-endian */ -+ if (! bfd_header_big_endian (templ)) -+ { -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Unrecognized " -+ "big-endian ELF header at address 0x%lx"), -+ (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ break; -+ case ELFDATA2LSB: /* Little-endian */ -+ if (! bfd_header_little_endian (templ)) -+ { -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Unrecognized " -+ "little-endian ELF header at address 0x%lx"), -+ (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ break; -+ case ELFDATANONE: /* No data encoding specified */ -+ default: /* Unknown data encoding specified */ -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Unrecognized " -+ "ELF header endianity at address 0x%lx"), -+ (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ -+ elf_swap_ehdr_in (templ, &x_ehdr64, &i_ehdr); -+ -+ /* The file header tells where to find the program headers. -+ These are what we use to actually choose what to read. */ -+ -+ if (i_ehdr.e_phentsize != (bfd_get_arch_size (templ) == 64 -+ ? sizeof (Elf64_External_Phdr) -+ : sizeof (Elf32_External_Phdr)) -+ || i_ehdr.e_phnum == 0) -+ { -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Invalid ELF program headers from the ELF header " -+ "at address 0x%lx"), (unsigned long) ehdr_vma); -+ return NULL; -+ } -+ -+ x_phdrs_size = (bfd_get_arch_size (templ) == 64 ? sizeof (Elf64_External_Phdr) -+ : sizeof (Elf32_External_Phdr)); -+ -+ i_phdrs = (Elf_Internal_Phdr *) xmalloc (i_ehdr.e_phnum * (sizeof *i_phdrs + x_phdrs_size)); -+ x_phdrs_ptr = (gdb_byte *) &i_phdrs[i_ehdr.e_phnum]; -+ err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs_ptr, -+ i_ehdr.e_phnum * x_phdrs_size); -+ if (err) -+ { -+ free (i_phdrs); -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Error reading " -+ "ELF program headers at address 0x%lx"), -+ (unsigned long) (ehdr_vma + i_ehdr.e_phoff)); -+ return NULL; -+ } -+ -+ loadbase = ehdr_vma; -+ loadbase_set = 0; -+ for (i = 0; i < i_ehdr.e_phnum; ++i) -+ { -+ elf_swap_phdr_in (templ, (Elf64_External_Phdr *) -+ (x_phdrs_ptr + i * x_phdrs_size), &i_phdrs[i]); -+ /* IA-64 vDSO may have two mappings for one segment, where one mapping -+ is executable only, and one is read only. We must not use the -+ executable one (PF_R is the first one, PF_X the second one). */ -+ if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R)) -+ { -+ /* Only the first PT_LOAD segment indicates the file bias. -+ Next segments may have P_VADDR arbitrarily higher. -+ If the first segment has P_VADDR zero any next segment must not -+ confuse us, the first one sets LOADBASE certainly enough. */ -+ if (!loadbase_set && i_phdrs[i].p_offset == 0) -+ { -+ loadbase = ehdr_vma - i_phdrs[i].p_vaddr; -+ loadbase_set = 1; -+ } -+ } -+ } -+ -+ if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE) -+ warning (_("build-id: Found ELF header at address 0x%lx, loadbase 0x%lx"), -+ (unsigned long) ehdr_vma, (unsigned long) loadbase); -+ -+ *e_phnum_pointer = i_ehdr.e_phnum; -+ *loadbase_pointer = loadbase; -+ return i_phdrs; -+} -+ -+/* BUILD_ID_ADDR_GET gets ADDR located somewhere in the object. -+ Find the first section before ADDR containing an ELF header. -+ We rely on the fact the sections from multiple files do not mix. -+ FIXME: We should check ADDR is contained _inside_ the section with possibly -+ missing content (P_FILESZ < P_MEMSZ). These omitted sections are currently -+ hidden by _BFD_ELF_MAKE_SECTION_FROM_PHDR. */ -+ -+static CORE_ADDR build_id_addr; -+struct build_id_addr_sect -+ { -+ struct build_id_addr_sect *next; -+ asection *sect; -+ }; -+static struct build_id_addr_sect *build_id_addr_sect; -+ -+static void build_id_addr_candidate (bfd *abfd, asection *sect, void *obj) -+{ -+ if (build_id_addr >= bfd_section_vma (sect)) -+ { -+ struct build_id_addr_sect *candidate; -+ -+ candidate = (struct build_id_addr_sect *) xmalloc (sizeof *candidate); -+ candidate->next = build_id_addr_sect; -+ build_id_addr_sect = candidate; -+ candidate->sect = sect; -+ } -+} -+ -+struct bfd_build_id * -+build_id_addr_get (CORE_ADDR addr) -+{ -+ struct build_id_addr_sect *candidate; -+ struct bfd_build_id *retval = NULL; -+ Elf_Internal_Phdr *i_phdr = NULL; -+ bfd_vma loadbase = 0; -+ unsigned e_phnum = 0; -+ -+ if (core_bfd == NULL) -+ return NULL; -+ -+ build_id_addr = addr; -+ gdb_assert (build_id_addr_sect == NULL); -+ bfd_map_over_sections (core_bfd, build_id_addr_candidate, NULL); -+ -+ /* Sections are sorted in the high-to-low VMAs order. -+ Stop the search on the first ELF header we find. -+ Do not continue the search even if it does not contain NT_GNU_BUILD_ID. */ -+ -+ for (candidate = build_id_addr_sect; candidate != NULL; -+ candidate = candidate->next) -+ { -+ i_phdr = elf_get_phdr (core_bfd, -+ bfd_section_vma (candidate->sect), -+ &e_phnum, &loadbase); -+ if (i_phdr != NULL) -+ break; -+ } -+ -+ if (i_phdr != NULL) -+ { -+ retval = build_id_phdr_get (core_bfd, loadbase, e_phnum, i_phdr); -+ xfree (i_phdr); -+ } -+ -+ while (build_id_addr_sect != NULL) -+ { -+ candidate = build_id_addr_sect; -+ build_id_addr_sect = candidate->next; -+ xfree (candidate); -+ } -+ -+ return retval; -+} -+ - /* See build-id.h. */ - - int -@@ -51,7 +451,7 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check) - const struct bfd_build_id *found; - int retval = 0; - -- found = build_id_bfd_get (abfd); -+ found = build_id_bfd_shdr_get (abfd); - - if (found == NULL) - warning (_("File \"%s\" has no build-id, file skipped"), -@@ -66,63 +466,166 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check) - return retval; - } - -+static char * -+link_resolve (const char *symlink, int level) -+{ -+ char buf[PATH_MAX + 1], *retval; -+ gdb::unique_xmalloc_ptr target; -+ ssize_t got; -+ -+ if (level > 10) -+ return xstrdup (symlink); -+ -+ got = readlink (symlink, buf, sizeof (buf)); -+ if (got < 0 || got >= sizeof (buf)) -+ return xstrdup (symlink); -+ buf[got] = '\0'; -+ -+ if (IS_ABSOLUTE_PATH (buf)) -+ target = make_unique_xstrdup (buf); -+ else -+ { -+ const std::string dir (ldirname (symlink)); -+ -+ target = xstrprintf ("%s" -+#ifndef HAVE_DOS_BASED_FILE_SYSTEM -+ "/" -+#else /* HAVE_DOS_BASED_FILE_SYSTEM */ -+ "\\" -+#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ -+ "%s", dir.c_str(), buf); -+ } -+ -+ retval = link_resolve (target.get (), level + 1); -+ return retval; -+} -+ - /* Helper for build_id_to_debug_bfd. LINK is a path to a potential - build-id-based separate debug file, potentially a symlink to the real file. - If the file exists and matches BUILD_ID, return a BFD reference to it. */ - - static gdb_bfd_ref_ptr --build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len, -- const bfd_byte *build_id) -+build_id_to_debug_bfd_1 (const std::string &orig_link, size_t build_id_len, -+ const bfd_byte *build_id, char **link_return) - { -+ gdb_bfd_ref_ptr ret_bfd = {}; -+ std::string ret_link; -+ - if (separate_debug_file_debug) - { -- fprintf_unfiltered (gdb_stdlog, _(" Trying %s..."), link.c_str ()); -- gdb_flush (gdb_stdlog); -+ fprintf_unfiltered (gdb_stdlog, _(" Trying %s..."), orig_link.c_str ()); -+ gdb_flush (gdb_stdout); - } - -- /* lrealpath() is expensive even for the usually non-existent files. */ -- gdb::unique_xmalloc_ptr filename_holder; -- const char *filename = nullptr; -- if (startswith (link, TARGET_SYSROOT_PREFIX)) -- filename = link.c_str (); -- else if (access (link.c_str (), F_OK) == 0) -+ for (unsigned seqno = 0;; seqno++) - { -- filename_holder.reset (lrealpath (link.c_str ())); -- filename = filename_holder.get (); -- } -+ std::string link = orig_link; - -- if (filename == NULL) -- { -- if (separate_debug_file_debug) -- fprintf_unfiltered (gdb_stdlog, -- _(" no, unable to compute real path\n")); -+ if (seqno > 0) -+ { -+ /* There can be multiple build-id symlinks pointing to real files -+ with the same build-id (such as hard links). Some of the real -+ files may not be installed. */ - -- return {}; -- } -+ string_appendf (link, ".%u", seqno); -+ } - -- /* We expect to be silent on the non-existing files. */ -- gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget); -+ ret_link = link; - -- if (debug_bfd == NULL) -- { -- if (separate_debug_file_debug) -- fprintf_unfiltered (gdb_stdlog, _(" no, unable to open.\n")); -+ struct stat statbuf_trash; -+ -+ /* `access' automatically dereferences LINK. */ -+ if (lstat (link.c_str (), &statbuf_trash) != 0) -+ { -+ /* Stop increasing SEQNO. */ -+ break; -+ } -+ -+ /* lrealpath() is expensive even for the usually non-existent files. */ -+ gdb::unique_xmalloc_ptr filename_holder; -+ const char *filename = nullptr; -+ if (startswith (link, TARGET_SYSROOT_PREFIX)) -+ filename = link.c_str (); -+ else if (access (link.c_str (), F_OK) == 0) -+ { -+ filename_holder.reset (lrealpath (link.c_str ())); -+ filename = filename_holder.get (); -+ } -+ -+ if (filename == NULL) -+ { -+ if (separate_debug_file_debug) -+ fprintf_unfiltered (gdb_stdlog, -+ _(" no, unable to compute real path\n")); -+ -+ continue; -+ } -+ -+ /* We expect to be silent on the non-existing files. */ -+ gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget); -+ -+ if (debug_bfd == NULL) -+ { -+ if (separate_debug_file_debug) -+ fprintf_unfiltered (gdb_stdlog, _(" no, unable to open.\n")); - -- return {}; -+ continue; -+ } -+ -+ if (!build_id_verify (debug_bfd.get(), build_id_len, build_id)) -+ { -+ if (separate_debug_file_debug) -+ fprintf_unfiltered (gdb_stdlog, -+ _(" no, build-id does not match.\n")); -+ -+ continue; -+ } -+ -+ ret_bfd = debug_bfd; -+ break; - } - -- if (!build_id_verify (debug_bfd.get(), build_id_len, build_id)) -+ std::string link_all; -+ -+ if (ret_bfd != NULL) - { - if (separate_debug_file_debug) -- fprintf_unfiltered (gdb_stdlog, _(" no, build-id does not match.\n")); -+ fprintf_unfiltered (gdb_stdlog, _(" yes!\n")); -+ } -+ else -+ { -+ /* If none of the real files is found report as missing file -+ always the non-.%u-suffixed file. */ -+ std::string link0 = orig_link; - -- return {}; -+ /* If the symlink has target request to install the target. -+ BASE-debuginfo.rpm contains the symlink but BASE.rpm may be missing. -+ https://bugzilla.redhat.com/show_bug.cgi?id=981154 */ -+ std::string link0_resolved (link_resolve (link0.c_str (), 0)); -+ -+ if (link_all.empty ()) -+ link_all = link0_resolved; -+ else -+ { -+ /* Use whitespace instead of DIRNAME_SEPARATOR to be compatible with -+ its possible use as an argument for installation command. */ -+ link_all += " " + link0_resolved; -+ } - } - -- if (separate_debug_file_debug) -- fprintf_unfiltered (gdb_stdlog, _(" yes!\n")); -+ if (link_return != NULL) -+ { -+ if (ret_bfd != NULL) -+ { -+ *link_return = xstrdup (ret_link.c_str ()); -+ } -+ else -+ { -+ *link_return = xstrdup (link_all.c_str ()); -+ } -+ } - -- return debug_bfd; -+ return ret_bfd; - } - - /* Common code for finding BFDs of a given build-id. This function -@@ -131,7 +634,7 @@ build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len, - - static gdb_bfd_ref_ptr - build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, -- const char *suffix) -+ const char *suffix, char **link_return) - { - /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will - cause "/.build-id/..." lookups. */ -@@ -154,16 +657,17 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, - if (size > 0) - { - size--; -- string_appendf (link, "%02x/", (unsigned) *data++); -+ string_appendf (link, "%02x", (unsigned) *data++); - } -- -+ if (size > 0) -+ link += "/"; - while (size-- > 0) - string_appendf (link, "%02x", (unsigned) *data++); - - link += suffix; - - gdb_bfd_ref_ptr debug_bfd -- = build_id_to_debug_bfd_1 (link, build_id_len, build_id); -+ = build_id_to_debug_bfd_1 (link, build_id_len, build_id, link_return); - if (debug_bfd != NULL) - return debug_bfd; - -@@ -174,7 +678,8 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, - if (!gdb_sysroot.empty ()) - { - link = gdb_sysroot + link; -- debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id); -+ debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id, -+ link_return); - if (debug_bfd != NULL) - return debug_bfd; - } -@@ -183,30 +688,649 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, - return {}; - } - -+char * -+build_id_to_filename (const struct bfd_build_id *build_id, char **link_return) -+{ -+ gdb_bfd_ref_ptr abfd; -+ char *result; -+ -+ abfd = build_id_to_exec_bfd (build_id->size, build_id->data, link_return); -+ if (abfd == NULL) -+ return NULL; -+ -+ result = xstrdup (bfd_get_filename (abfd.get ())); -+ return result; -+} -+ -+#ifdef HAVE_LIBRPM -+ -+#include -+#include -+#include -+#include -+#ifdef DLOPEN_LIBRPM -+#include -+#endif -+ -+/* Workarodun https://bugzilla.redhat.com/show_bug.cgi?id=643031 -+ librpm must not exit() an application on SIGINT -+ -+ Enable or disable a signal handler. SIGNUM: signal to enable (or disable -+ if negative). HANDLER: sa_sigaction handler (or NULL to use -+ rpmsqHandler()). Returns: no. of refs, -1 on error. */ -+extern int rpmsqEnable (int signum, /* rpmsqAction_t handler */ void *handler); -+int -+rpmsqEnable (int signum, /* rpmsqAction_t handler */ void *handler) -+{ -+ return 0; -+} -+ -+/* This MISSING_RPM_HASH tracker is used to collect all the missing rpm files -+ and avoid their duplicities during a single inferior run. */ -+ -+static struct htab *missing_rpm_hash; -+ -+/* This MISSING_RPM_LIST tracker is used to collect and print as a single line -+ all the rpms right before the nearest GDB prompt. It gets cleared after -+ each such print (it is questionable if we should clear it after the print). -+ */ -+ -+struct missing_rpm -+ { -+ struct missing_rpm *next; -+ char rpm[1]; -+ }; -+static struct missing_rpm *missing_rpm_list; -+static int missing_rpm_list_entries; -+ -+/* Returns the count of newly added rpms. */ -+ -+static int -+#ifndef GDB_INDEX_VERIFY_VENDOR -+missing_rpm_enlist (const char *filename) -+#else -+missing_rpm_enlist_1 (const char *filename, int verify_vendor) -+#endif -+{ -+ static int rpm_init_done = 0; -+ rpmts ts; -+ rpmdbMatchIterator mi; -+ int count = 0; -+ -+#ifdef DLOPEN_LIBRPM -+ /* Duplicate here the declarations to verify they match. The same sanity -+ check is present also in `configure.ac'. */ -+ extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg); -+ static char *(*headerFormat_p) (Header h, const char * fmt, errmsg_t *errmsg); -+ extern int rpmReadConfigFiles(const char * file, const char * target); -+ static int (*rpmReadConfigFiles_p) (const char * file, const char * target); -+ extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi); -+ static rpmdbMatchIterator (*rpmdbFreeIterator_p) (rpmdbMatchIterator mi); -+ extern Header rpmdbNextIterator(rpmdbMatchIterator mi); -+ static Header (*rpmdbNextIterator_p) (rpmdbMatchIterator mi); -+ extern rpmts rpmtsCreate(void); -+ static rpmts (*rpmtsCreate_p) (void); -+ extern rpmts rpmtsFree(rpmts ts); -+ static rpmts (*rpmtsFree_p) (rpmts ts); -+ extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, -+ const void * keyp, size_t keylen); -+ static rpmdbMatchIterator (*rpmtsInitIterator_p) (const rpmts ts, -+ rpmTag rpmtag, -+ const void *keyp, -+ size_t keylen); -+#else /* !DLOPEN_LIBRPM */ -+# define headerFormat_p headerFormat -+# define rpmReadConfigFiles_p rpmReadConfigFiles -+# define rpmdbFreeIterator_p rpmdbFreeIterator -+# define rpmdbNextIterator_p rpmdbNextIterator -+# define rpmtsCreate_p rpmtsCreate -+# define rpmtsFree_p rpmtsFree -+# define rpmtsInitIterator_p rpmtsInitIterator -+#endif /* !DLOPEN_LIBRPM */ -+ -+ gdb_assert (filename != NULL); -+ -+ if (strcmp (filename, BUILD_ID_MAIN_EXECUTABLE_FILENAME) == 0) -+ return 0; -+ -+ if (is_target_filename (filename)) -+ return 0; -+ -+ if (filename[0] != '/') -+ { -+ warning (_("Ignoring non-absolute filename: <%s>"), filename); -+ return 0; -+ } -+ -+ if (!rpm_init_done) -+ { -+ static int init_tried; -+ -+ /* Already failed the initialization before? */ -+ if (init_tried) -+ return 0; -+ init_tried = 1; -+ -+#ifdef DLOPEN_LIBRPM -+ { -+ void *h; -+ -+ h = dlopen (DLOPEN_LIBRPM, RTLD_LAZY); -+ if (!h) -+ { -+ warning (_("Unable to open \"%s\" (%s), " -+ "missing debuginfos notifications will not be displayed"), -+ DLOPEN_LIBRPM, dlerror ()); -+ return 0; -+ } -+ -+ if (!((headerFormat_p = (char *(*) (Header h, const char * fmt, errmsg_t *errmsg)) dlsym (h, "headerFormat")) -+ && (rpmReadConfigFiles_p = (int (*) (const char * file, const char * target)) dlsym (h, "rpmReadConfigFiles")) -+ && (rpmdbFreeIterator_p = (rpmdbMatchIterator (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbFreeIterator")) -+ && (rpmdbNextIterator_p = (Header (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbNextIterator")) -+ && (rpmtsCreate_p = (rpmts (*) (void)) dlsym (h, "rpmtsCreate")) -+ && (rpmtsFree_p = (rpmts (*) (rpmts ts)) dlsym (h, "rpmtsFree")) -+ && (rpmtsInitIterator_p = (rpmdbMatchIterator (*) (const rpmts ts, rpmTag rpmtag, const void *keyp, size_t keylen)) dlsym (h, "rpmtsInitIterator")))) -+ { -+ warning (_("Opened library \"%s\" is incompatible (%s), " -+ "missing debuginfos notifications will not be displayed"), -+ DLOPEN_LIBRPM, dlerror ()); -+ if (dlclose (h)) -+ warning (_("Error closing library \"%s\": %s\n"), DLOPEN_LIBRPM, -+ dlerror ()); -+ return 0; -+ } -+ } -+#endif /* DLOPEN_LIBRPM */ -+ -+ if (rpmReadConfigFiles_p (NULL, NULL) != 0) -+ { -+ warning (_("Error reading the rpm configuration files")); -+ return 0; -+ } -+ -+ rpm_init_done = 1; -+ } -+ -+ ts = rpmtsCreate_p (); -+ -+ mi = rpmtsInitIterator_p (ts, RPMTAG_BASENAMES, filename, 0); -+ if (mi != NULL) -+ { -+#ifndef GDB_INDEX_VERIFY_VENDOR -+ for (;;) -+#else -+ if (!verify_vendor) for (;;) -+#endif -+ { -+ Header h; -+ char *debuginfo, **slot, *s, *s2; -+ errmsg_t err; -+ size_t srcrpmlen = sizeof (".src.rpm") - 1; -+ size_t debuginfolen = sizeof ("-debuginfo") - 1; -+ rpmdbMatchIterator mi_debuginfo; -+ -+ h = rpmdbNextIterator_p (mi); -+ if (h == NULL) -+ break; -+ -+ /* Verify the debuginfo file is not already installed. */ -+ -+ debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}", -+ &err); -+ if (!debuginfo) -+ { -+ warning (_("Error querying the rpm file `%s': %s"), filename, -+ err); -+ continue; -+ } -+ /* s = `.src.rpm-debuginfo.%{arch}' */ -+ s = strrchr (debuginfo, '-') - srcrpmlen; -+ s2 = NULL; -+ if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0) -+ { -+ /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */ -+ s2 = (char *) memrchr (debuginfo, '-', s - debuginfo); -+ } -+ if (s2) -+ { -+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ -+ s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo); -+ } -+ if (!s2) -+ { -+ warning (_("Error querying the rpm file `%s': %s"), filename, -+ debuginfo); -+ xfree (debuginfo); -+ continue; -+ } -+ /* s = `.src.rpm-debuginfo.%{arch}' */ -+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */ -+ memmove (s2 + debuginfolen, s2, s - s2); -+ memcpy (s2, "-debuginfo", debuginfolen); -+ /* s = `XXXX.%{arch}' */ -+ /* strlen ("XXXX") == srcrpmlen + debuginfolen */ -+ /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */ -+ /* strlen ("XX") == srcrpmlen */ -+ memmove (s + debuginfolen, s + srcrpmlen + debuginfolen, -+ strlen (s + srcrpmlen + debuginfolen) + 1); -+ /* s = `-debuginfo-%{version}-%{release}.%{arch}' */ -+ -+ /* RPMDBI_PACKAGES requires keylen == sizeof (int). */ -+ /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */ -+ mi_debuginfo = rpmtsInitIterator_p (ts, (rpmTag) RPMDBI_LABEL, debuginfo, 0); -+ xfree (debuginfo); -+ if (mi_debuginfo) -+ { -+ rpmdbFreeIterator_p (mi_debuginfo); -+ count = 0; -+ break; -+ } -+ -+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */ -+ debuginfo = headerFormat_p (h, -+ "%{name}-%{version}-%{release}.%{arch}", -+ &err); -+ if (!debuginfo) -+ { -+ warning (_("Error querying the rpm file `%s': %s"), filename, -+ err); -+ continue; -+ } -+ -+ /* Base package name for `debuginfo-install'. We do not use the -+ `yum' command directly as the line -+ yum --enablerepo='*debug*' install NAME-debuginfo.ARCH -+ would be more complicated than just: -+ debuginfo-install NAME-VERSION-RELEASE.ARCH -+ Do not supply the rpm base name (derived from .src.rpm name) as -+ debuginfo-install is unable to install the debuginfo package if -+ the base name PKG binary rpm is not installed while for example -+ PKG-libs would be installed (RH Bug 467901). -+ FUTURE: After multiple debuginfo versions simultaneously installed -+ get supported the support for the VERSION-RELEASE tags handling -+ may need an update. */ -+ -+ if (missing_rpm_hash == NULL) -+ { -+ /* DEL_F is passed NULL as MISSING_RPM_LIST's HTAB_DELETE -+ should not deallocate the entries. */ -+ -+ missing_rpm_hash = htab_create_alloc (64, htab_hash_string, -+ (int (*) (const void *, const void *)) streq, -+ NULL, xcalloc, xfree); -+ } -+ slot = (char **) htab_find_slot (missing_rpm_hash, debuginfo, INSERT); -+ /* XCALLOC never returns NULL. */ -+ gdb_assert (slot != NULL); -+ if (*slot == NULL) -+ { -+ struct missing_rpm *missing_rpm; -+ -+ *slot = debuginfo; -+ -+ missing_rpm = (struct missing_rpm *) xmalloc (sizeof (*missing_rpm) + strlen (debuginfo)); -+ strcpy (missing_rpm->rpm, debuginfo); -+ missing_rpm->next = missing_rpm_list; -+ missing_rpm_list = missing_rpm; -+ missing_rpm_list_entries++; -+ } -+ else -+ xfree (debuginfo); -+ count++; -+ } -+#ifdef GDB_INDEX_VERIFY_VENDOR -+ else /* verify_vendor */ -+ { -+ int vendor_pass = 0, vendor_fail = 0; -+ -+ for (;;) -+ { -+ Header h; -+ errmsg_t err; -+ char *vendor; -+ -+ h = rpmdbNextIterator_p (mi); -+ if (h == NULL) -+ break; -+ -+ vendor = headerFormat_p (h, "%{vendor}", &err); -+ if (!vendor) -+ { -+ warning (_("Error querying the rpm file `%s': %s"), filename, -+ err); -+ continue; -+ } -+ if (strcmp (vendor, "Red Hat, Inc.") == 0) -+ vendor_pass = 1; -+ else -+ vendor_fail = 1; -+ xfree (vendor); -+ } -+ count = vendor_pass != 0 && vendor_fail == 0; -+ } -+#endif -+ -+ rpmdbFreeIterator_p (mi); -+ } -+ -+ rpmtsFree_p (ts); -+ -+ return count; -+} -+ -+#ifdef GDB_INDEX_VERIFY_VENDOR -+missing_rpm_enlist (const char *filename) -+{ -+ return missing_rpm_enlist_1 (filename, 0); -+} -+ -+extern int rpm_verify_vendor (const char *filename); -+int -+rpm_verify_vendor (const char *filename) -+{ -+ return missing_rpm_enlist_1 (filename, 1); -+} -+#endif -+ -+static bool -+missing_rpm_list_compar (const char *ap, const char *bp) -+{ -+ return strcoll (ap, bp) < 0; -+} -+ -+/* It returns a NULL-terminated array of strings needing to be FREEd. It may -+ also return only NULL. */ -+ -+static void -+missing_rpm_list_print (void) -+{ -+ struct missing_rpm *list_iter; -+ -+ if (missing_rpm_list_entries == 0) -+ return; -+ -+ std::vector array (missing_rpm_list_entries); -+ size_t idx = 0; -+ -+ for (list_iter = missing_rpm_list; list_iter != NULL; -+ list_iter = list_iter->next) -+ { -+ array[idx++] = list_iter->rpm; -+ } -+ gdb_assert (idx == missing_rpm_list_entries); -+ -+ std::sort (array.begin (), array.end (), missing_rpm_list_compar); -+ -+ /* We zero out the number of missing RPMs here because of a nasty -+ bug (see RHBZ 1801974). -+ -+ When we call 'puts_unfiltered' below, if pagination is on and if -+ the number of missing RPMs is big enough to trigger pagination, -+ we will end up in an infinite recursion. The call chain looks -+ like this: -+ -+ missing_rpm_list_print -> puts_unfiltered -> fputs_maybe_filtered -+ -> prompt_for_continue -> display_gdb_prompt -> -+ debug_flush_missing -> missing_rpm_list_print ... -+ -+ For this reason, we make sure MISSING_RPM_LIST_ENTRIES is zero -+ *before* calling any print function. */ -+ missing_rpm_list_entries = 0; -+ -+ printf_unfiltered (_("Missing separate debuginfos, use: %s"), -+#ifdef DNF_DEBUGINFO_INSTALL -+ "dnf " -+#endif -+ "debuginfo-install"); -+ for (const char *el : array) -+ { -+ puts_unfiltered (" "); -+ puts_unfiltered (el); -+ } -+ puts_unfiltered ("\n"); -+ -+ while (missing_rpm_list != NULL) -+ { -+ list_iter = missing_rpm_list; -+ missing_rpm_list = list_iter->next; -+ xfree (list_iter); -+ } -+} -+ -+static void -+missing_rpm_change (void) -+{ -+ debug_flush_missing (); -+ -+ gdb_assert (missing_rpm_list == NULL); -+ if (missing_rpm_hash != NULL) -+ { -+ htab_delete (missing_rpm_hash); -+ missing_rpm_hash = NULL; -+ } -+} -+ -+enum missing_exec -+ { -+ /* Init state. EXEC_BFD also still could be NULL. */ -+ MISSING_EXEC_NOT_TRIED, -+ /* We saw a non-NULL EXEC_BFD but RPM has no info about it. */ -+ MISSING_EXEC_NOT_FOUND, -+ /* We found EXEC_BFD by RPM and we either have its symbols (either embedded -+ or separate) or the main executable's RPM is now contained in -+ MISSING_RPM_HASH. */ -+ MISSING_EXEC_ENLISTED -+ }; -+static enum missing_exec missing_exec = MISSING_EXEC_NOT_TRIED; -+ -+#endif /* HAVE_LIBRPM */ -+ -+void -+debug_flush_missing (void) -+{ -+#ifdef HAVE_LIBRPM -+ missing_rpm_list_print (); -+#endif -+} -+ -+/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages -+ yum --enablerepo='*debug*' install ... -+ avoidance. */ -+ -+struct missing_filepair -+ { -+ char *binary; -+ char *debug; -+ char data[1]; -+ }; -+ -+static struct htab *missing_filepair_hash; -+static struct obstack missing_filepair_obstack; -+ -+static void * -+missing_filepair_xcalloc (size_t nmemb, size_t nmemb_size) -+{ -+ void *retval; -+ size_t size = nmemb * nmemb_size; -+ -+ retval = obstack_alloc (&missing_filepair_obstack, size); -+ memset (retval, 0, size); -+ return retval; -+} -+ -+static hashval_t -+missing_filepair_hash_func (const struct missing_filepair *elem) -+{ -+ hashval_t retval = 0; -+ -+ retval ^= htab_hash_string (elem->binary); -+ if (elem->debug != NULL) -+ retval ^= htab_hash_string (elem->debug); -+ -+ return retval; -+} -+ -+static int -+missing_filepair_eq (const struct missing_filepair *elem1, -+ const struct missing_filepair *elem2) -+{ -+ return strcmp (elem1->binary, elem2->binary) == 0 -+ && ((elem1->debug == NULL) == (elem2->debug == NULL)) -+ && (elem1->debug == NULL || strcmp (elem1->debug, elem2->debug) == 0); -+} -+ -+static void -+missing_filepair_change (void) -+{ -+ if (missing_filepair_hash != NULL) -+ { -+ obstack_free (&missing_filepair_obstack, NULL); -+ /* All their memory came just from missing_filepair_OBSTACK. */ -+ missing_filepair_hash = NULL; -+ } -+#ifdef HAVE_LIBRPM -+ missing_exec = MISSING_EXEC_NOT_TRIED; -+#endif -+} -+ -+static void -+debug_print_executable_changed (void) -+{ -+#ifdef HAVE_LIBRPM -+ missing_rpm_change (); -+#endif -+ missing_filepair_change (); -+} -+ -+/* Notify user the file BINARY with (possibly NULL) associated separate debug -+ information file DEBUG is missing. DEBUG may or may not be the build-id -+ file such as would be: -+ /usr/lib/debug/.build-id/dd/b1d2ce632721c47bb9e8679f369e2295ce71be.debug -+ */ -+ -+void -+debug_print_missing (const char *binary, const char *debug) -+{ -+ size_t binary_len0 = strlen (binary) + 1; -+ size_t debug_len0 = debug ? strlen (debug) + 1 : 0; -+ struct missing_filepair missing_filepair_find; -+ struct missing_filepair *missing_filepair; -+ struct missing_filepair **slot; -+ -+ if (build_id_verbose < BUILD_ID_VERBOSE_FILENAMES) -+ return; -+ -+ if (missing_filepair_hash == NULL) -+ { -+ obstack_init (&missing_filepair_obstack); -+ missing_filepair_hash = htab_create_alloc (64, -+ (hashval_t (*) (const void *)) missing_filepair_hash_func, -+ (int (*) (const void *, const void *)) missing_filepair_eq, NULL, -+ missing_filepair_xcalloc, NULL); -+ } -+ -+ /* Use MISSING_FILEPAIR_FIND first instead of calling obstack_alloc with -+ obstack_free in the case of a (rare) match. The problem is ALLOC_F for -+ MISSING_FILEPAIR_HASH allocates from MISSING_FILEPAIR_OBSTACK maintenance -+ structures for MISSING_FILEPAIR_HASH. Calling obstack_free would possibly -+ not to free only MISSING_FILEPAIR but also some such structures (allocated -+ during the htab_find_slot call). */ -+ -+ missing_filepair_find.binary = (char *) binary; -+ missing_filepair_find.debug = (char *) debug; -+ slot = (struct missing_filepair **) htab_find_slot (missing_filepair_hash, -+ &missing_filepair_find, -+ INSERT); -+ -+ /* While it may be still printed duplicitely with the missing debuginfo file -+ * it is due to once printing about the binary file build-id link and once -+ * about the .debug file build-id link as both the build-id symlinks are -+ * located in the debuginfo package. */ -+ -+ if (*slot != NULL) -+ return; -+ -+ missing_filepair = (struct missing_filepair *) obstack_alloc (&missing_filepair_obstack, -+ sizeof (*missing_filepair) - 1 -+ + binary_len0 + debug_len0); -+ missing_filepair->binary = missing_filepair->data; -+ memcpy (missing_filepair->binary, binary, binary_len0); -+ if (debug != NULL) -+ { -+ missing_filepair->debug = missing_filepair->binary + binary_len0; -+ memcpy (missing_filepair->debug, debug, debug_len0); -+ } -+ else -+ missing_filepair->debug = NULL; -+ -+ *slot = missing_filepair; -+ -+#ifdef HAVE_LIBRPM -+ if (missing_exec == MISSING_EXEC_NOT_TRIED) -+ { -+ const char *execfilename = get_exec_file (0); -+ -+ if (execfilename != NULL) -+ { -+ if (missing_rpm_enlist (execfilename) == 0) -+ missing_exec = MISSING_EXEC_NOT_FOUND; -+ else -+ missing_exec = MISSING_EXEC_ENLISTED; -+ } -+ } -+ if (missing_exec != MISSING_EXEC_ENLISTED) -+ if ((binary[0] == 0 || missing_rpm_enlist (binary) == 0) -+ && (debug == NULL || missing_rpm_enlist (debug) == 0)) -+#endif /* HAVE_LIBRPM */ -+ { -+ /* We do not collect and flush these messages as each such message -+ already requires its own separate lines. */ -+ -+ fprintf_unfiltered (gdb_stdlog, -+ _("Missing separate debuginfo for %s\n"), binary); -+ if (debug != NULL) -+ fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"), -+#ifdef DNF_DEBUGINFO_INSTALL -+ "dnf" -+#else -+ "yum" -+#endif -+ " --enablerepo='*debug*' install", debug); -+ } -+} -+ - /* See build-id.h. */ - - gdb_bfd_ref_ptr --build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id) -+build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id, -+ char **link_return) - { -- return build_id_to_bfd_suffix (build_id_len, build_id, ".debug"); -+ return build_id_to_bfd_suffix (build_id_len, build_id, ".debug", -+ link_return); - } - - /* See build-id.h. */ - - gdb_bfd_ref_ptr --build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id) -+build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id, -+ char **link_return) - { -- return build_id_to_bfd_suffix (build_id_len, build_id, ""); -+ return build_id_to_bfd_suffix (build_id_len, build_id, "", link_return); - } - - /* See build-id.h. */ - - std::string --find_separate_debug_file_by_buildid (struct objfile *objfile) -+find_separate_debug_file_by_buildid (struct objfile *objfile, -+ gdb::unique_xmalloc_ptr *build_id_filename_return) - { - const struct bfd_build_id *build_id; - -- build_id = build_id_bfd_get (objfile->obfd); -+ if (build_id_filename_return) -+ *build_id_filename_return = NULL; -+ -+ build_id = build_id_bfd_shdr_get (objfile->obfd); - if (build_id != NULL) - { - if (separate_debug_file_debug) -@@ -214,8 +1338,21 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) - _("\nLooking for separate debug info (build-id) for " - "%s\n"), objfile_name (objfile)); - -+ char *build_id_filename_cstr = NULL; - gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size, -- build_id->data)); -+ build_id->data, -+ (!build_id_filename_return ? NULL : &build_id_filename_cstr))); -+ if (build_id_filename_return) -+ { -+ if (!build_id_filename_cstr) -+ gdb_assert (!*build_id_filename_return); -+ else -+ { -+ *build_id_filename_return = gdb::unique_xmalloc_ptr (build_id_filename_cstr); -+ build_id_filename_cstr = NULL; -+ } -+ } -+ - /* Prevent looping on a stripped .debug file. */ - if (abfd != NULL - && filename_cmp (bfd_get_filename (abfd.get ()), -@@ -228,3 +1365,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) - - return std::string (); - } -+ -+void _initialize_build_id (); -+ -+void -+_initialize_build_id () -+{ -+ add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose, -+ _("\ -+Set debugging level of the build-id locator."), _("\ -+Show debugging level of the build-id locator."), _("\ -+Level 1 (default) enables printing the missing debug filenames,\n\ -+level 2 also prints the parsing of binaries to find the identificators."), -+ NULL, -+ show_build_id_verbose, -+ &setlist, &showlist); -+ -+ gdb::observers::executable_changed.attach (debug_print_executable_changed, -+ "build-id"); -+} -diff --git a/gdb/build-id.h b/gdb/build-id.h ---- a/gdb/build-id.h -+++ b/gdb/build-id.h -@@ -23,9 +23,10 @@ - #include "gdb_bfd.h" - #include "gdbsupport/rsp-low.h" - --/* Locate NT_GNU_BUILD_ID from ABFD and return its content. */ -+/* Separate debuginfo files have corrupted PHDR but SHDR is correct there. -+ Locate NT_GNU_BUILD_ID from ABFD and return its content. */ - --extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd); -+extern const struct bfd_build_id *build_id_bfd_shdr_get (bfd *abfd); - - /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value. - Otherwise, issue a warning and return false. */ -@@ -38,21 +39,26 @@ extern int build_id_verify (bfd *abfd, - can be found, return NULL. */ - - extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len, -- const bfd_byte *build_id); -+ const bfd_byte *build_id, -+ char **link_return = NULL); -+ -+extern char *build_id_to_filename (const struct bfd_build_id *build_id, -+ char **link_return); - - /* Find and open a BFD for an executable file given a build-id. If no BFD - can be found, return NULL. The returned reference to the BFD must be - released by the caller. */ - - extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len, -- const bfd_byte *build_id); -+ const bfd_byte *build_id, -+ char **link_return); - - /* Find the separate debug file for OBJFILE, by using the build-id - associated with OBJFILE's BFD. If successful, returns the file name for the - separate debug file, otherwise, return an empty string. */ - --extern std::string find_separate_debug_file_by_buildid -- (struct objfile *objfile); -+extern std::string find_separate_debug_file_by_buildid (struct objfile *objfile, -+ gdb::unique_xmalloc_ptr *build_id_filename_return); - - /* Return an hex-string representation of BUILD_ID. */ - -diff --git a/gdb/coffread.c b/gdb/coffread.c ---- a/gdb/coffread.c -+++ b/gdb/coffread.c -@@ -710,7 +710,8 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) - /* Try to add separate debug file if no symbols table found. */ - if (!objfile->has_partial_symbols ()) - { -- std::string debugfile = find_separate_debug_file_by_buildid (objfile); -+ std::string debugfile = find_separate_debug_file_by_buildid (objfile, -+ NULL); - - if (debugfile.empty ()) - debugfile = find_separate_debug_file_by_debuglink (objfile); -diff --git a/gdb/corelow.c b/gdb/corelow.c ---- a/gdb/corelow.c -+++ b/gdb/corelow.c -@@ -22,6 +22,10 @@ - #include - #include - #include "frame.h" /* required by inferior.h */ -+#include "auxv.h" -+#include "build-id.h" -+#include "elf/common.h" -+#include "gdbcmd.h" - #include "inferior.h" - #include "infrun.h" - #include "symtab.h" -@@ -356,6 +360,8 @@ add_to_thread_list (asection *asect, asection *reg_sect) - switch_to_thread (thr); /* Yes, make it current. */ - } - -+static bool build_id_core_loads = true; -+ - /* Issue a message saying we have no core to debug, if FROM_TTY. */ - - static void -@@ -392,19 +398,26 @@ core_file_command (const char *filename, int from_tty) - static void - locate_exec_from_corefile_build_id (bfd *abfd, int from_tty) - { -- const bfd_build_id *build_id = build_id_bfd_get (abfd); -+ const bfd_build_id *build_id = build_id_bfd_shdr_get (abfd); - if (build_id == nullptr) - return; - -+ char *build_id_filename; - gdb_bfd_ref_ptr execbfd -- = build_id_to_exec_bfd (build_id->size, build_id->data); -+ = build_id_to_exec_bfd (build_id->size, build_id->data, -+ &build_id_filename); - - if (execbfd != nullptr) - { - exec_file_attach (bfd_get_filename (execbfd.get ()), from_tty); - symbol_file_add_main (bfd_get_filename (execbfd.get ()), - symfile_add_flag (from_tty ? SYMFILE_VERBOSE : 0)); -+ if (current_program_space->symfile_object_file != NULL) -+ current_program_space->symfile_object_file->flags |= -+ OBJF_BUILD_ID_CORE_LOADED; - } -+ else -+ debug_print_missing (BUILD_ID_MAIN_EXECUTABLE_FILENAME, build_id_filename); - } - - /* See gdbcore.h. */ -@@ -1209,4 +1222,11 @@ _initialize_corelow () - maintenance_print_core_file_backed_mappings, - _("Print core file's file-backed mappings."), - &maintenanceprintlist); -+ -+ add_setshow_boolean_cmd ("build-id-core-loads", class_files, -+ &build_id_core_loads, _("\ -+Set whether CORE-FILE loads the build-id associated files automatically."), _("\ -+Show whether CORE-FILE loads the build-id associated files automatically."), -+ NULL, NULL, NULL, -+ &setlist, &showlist); - } -diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo ---- a/gdb/doc/gdb.texinfo -+++ b/gdb/doc/gdb.texinfo -@@ -21524,6 +21524,27 @@ information files. - - @end table - -+You can also adjust the current verbosity of the @dfn{build id} locating. -+ -+@table @code -+ -+@kindex set build-id-verbose -+@item set build-id-verbose 0 -+No additional messages are printed. -+ -+@item set build-id-verbose 1 -+Missing separate debug filenames are printed. -+ -+@item set build-id-verbose 2 -+Missing separate debug filenames are printed and also all the parsing of the -+binaries to find their @dfn{build id} content is printed. -+ -+@kindex show build-id-verbose -+@item show build-id-verbose -+Show the current verbosity value for the @dfn{build id} content locating. -+ -+@end table -+ - @cindex @code{.gnu_debuglink} sections - @cindex debug link sections - A debug link is a special section of the executable file named -diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c ---- a/gdb/dwarf2/index-cache.c -+++ b/gdb/dwarf2/index-cache.c -@@ -97,7 +97,7 @@ index_cache::store (dwarf2_per_objfile *per_objfile) - return; - - /* Get build id of objfile. */ -- const bfd_build_id *build_id = build_id_bfd_get (obj->obfd); -+ const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd); - if (build_id == nullptr) - { - index_cache_debug ("objfile %s has no build id", -@@ -114,7 +114,8 @@ index_cache::store (dwarf2_per_objfile *per_objfile) - - if (dwz != nullptr) - { -- const bfd_build_id *dwz_build_id = build_id_bfd_get (dwz->dwz_bfd.get ()); -+ const bfd_build_id *dwz_build_id -+ = build_id_bfd_shdr_get (dwz->dwz_bfd.get ()); - - if (dwz_build_id == nullptr) - { -diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c ---- a/gdb/dwarf2/read.c -+++ b/gdb/dwarf2/read.c -@@ -5476,7 +5476,7 @@ get_gdb_index_contents_from_section (objfile *obj, T *section_owner) - static gdb::array_view - get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd) - { -- const bfd_build_id *build_id = build_id_bfd_get (obj->obfd); -+ const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd); - if (build_id == nullptr) - return {}; - -@@ -5489,7 +5489,7 @@ get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd) - static gdb::array_view - get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz) - { -- const bfd_build_id *build_id = build_id_bfd_get (dwz->dwz_bfd.get ()); -+ const bfd_build_id *build_id = build_id_bfd_shdr_get (dwz->dwz_bfd.get ()); - if (build_id == nullptr) - return {}; - -diff --git a/gdb/elfread.c b/gdb/elfread.c ---- a/gdb/elfread.c -+++ b/gdb/elfread.c -@@ -1270,7 +1270,9 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) - && objfile->separate_debug_objfile == NULL - && objfile->separate_debug_objfile_backlink == NULL) - { -- std::string debugfile = find_separate_debug_file_by_buildid (objfile); -+ gdb::unique_xmalloc_ptr build_id_filename; -+ std::string debugfile -+ = find_separate_debug_file_by_buildid (objfile, &build_id_filename); - - if (debugfile.empty ()) - debugfile = find_separate_debug_file_by_debuglink (objfile); -@@ -1285,7 +1287,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) - else - { - has_dwarf2 = false; -- const struct bfd_build_id *build_id = build_id_bfd_get (objfile->obfd); -+ const struct bfd_build_id *build_id = build_id_bfd_shdr_get (objfile->obfd); - - if (build_id != nullptr) - { -@@ -1310,6 +1312,10 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) - has_dwarf2 = true; - } - } -+ /* Check if any separate debug info has been extracted out. */ -+ else if (bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink") -+ != NULL) -+ debug_print_missing (objfile_name (objfile), build_id_filename.get ()); - } - } - } -diff --git a/gdb/exec.c b/gdb/exec.c ---- a/gdb/exec.c -+++ b/gdb/exec.c -@@ -238,7 +238,7 @@ validate_exec_file (int from_tty) - current_exec_file = get_exec_file (0); - - const bfd_build_id *exec_file_build_id -- = build_id_bfd_get (current_program_space->exec_bfd ()); -+ = build_id_bfd_shdr_get (current_program_space->exec_bfd ()); - if (exec_file_build_id != nullptr) - { - /* Prepend the target prefix, to force gdb_bfd_open to open the -@@ -251,7 +251,7 @@ validate_exec_file (int from_tty) - if (abfd != nullptr) - { - const bfd_build_id *target_exec_file_build_id -- = build_id_bfd_get (abfd.get ()); -+ = build_id_bfd_shdr_get (abfd.get ()); - - if (target_exec_file_build_id != nullptr) - { -diff --git a/gdb/objfiles.h b/gdb/objfiles.h ---- a/gdb/objfiles.h -+++ b/gdb/objfiles.h -@@ -769,6 +769,10 @@ struct objfile - bool skip_jit_symbol_lookup = false; - }; - -+/* This file was loaded according to the BUILD_ID_CORE_LOADS rules. */ -+ -+#define OBJF_BUILD_ID_CORE_LOADED static_cast(1 << 12) -+ - /* A deleter for objfile. */ - - struct objfile_deleter -diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c ---- a/gdb/python/py-objfile.c -+++ b/gdb/python/py-objfile.c -@@ -132,7 +132,7 @@ objfpy_get_build_id (PyObject *self, void *closure) - - try - { -- build_id = build_id_bfd_get (objfile->obfd); -+ build_id = build_id_bfd_shdr_get (objfile->obfd); - } - catch (const gdb_exception &except) - { -@@ -600,7 +600,7 @@ objfpy_lookup_objfile_by_build_id (const char *build_id) - /* Don't return separate debug files. */ - if (objfile->separate_debug_objfile_backlink != NULL) - continue; -- obfd_build_id = build_id_bfd_get (objfile->obfd); -+ obfd_build_id = build_id_bfd_shdr_get (objfile->obfd); - if (obfd_build_id == NULL) - continue; - if (objfpy_build_id_matches (obfd_build_id, build_id)) -diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c ---- a/gdb/solib-svr4.c -+++ b/gdb/solib-svr4.c -@@ -45,6 +45,7 @@ - #include "auxv.h" - #include "gdb_bfd.h" - #include "probe.h" -+#include "build-id.h" - - static struct link_map_offsets *svr4_fetch_link_map_offsets (void); - static int svr4_have_link_map_offsets (void); -@@ -1248,9 +1249,51 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, - continue; - } - -- strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1); -- newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; -- strcpy (newobj->so_original_name, newobj->so_name); -+ { -+ struct bfd_build_id *build_id; -+ -+ strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1); -+ newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; -+ /* May get overwritten below. */ -+ strcpy (newobj->so_name, newobj->so_original_name); -+ -+ build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld); -+ if (build_id != NULL) -+ { -+ char *name, *build_id_filename; -+ -+ /* Missing the build-id matching separate debug info file -+ would be handled while SO_NAME gets loaded. */ -+ name = build_id_to_filename (build_id, &build_id_filename); -+ if (name != NULL) -+ { -+ strncpy (newobj->so_name, name, SO_NAME_MAX_PATH_SIZE - 1); -+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; -+ xfree (name); -+ } -+ else -+ { -+ debug_print_missing (newobj->so_name, build_id_filename); -+ -+ /* In the case the main executable was found according to -+ its build-id (from a core file) prevent loading -+ a different build of a library with accidentally the -+ same SO_NAME. -+ -+ It suppresses bogus backtraces (and prints "??" there -+ instead) if the on-disk files no longer match the -+ running program version. */ -+ -+ if (current_program_space->symfile_object_file != NULL -+ && (current_program_space->symfile_object_file->flags -+ & OBJF_BUILD_ID_CORE_LOADED) != 0) -+ newobj->so_name[0] = 0; -+ } -+ -+ xfree (build_id_filename); -+ xfree (build_id); -+ } -+ } - - /* If this entry has no name, or its name matches the name - for the main executable, don't include it in the list. */ -diff --git a/gdb/source.c b/gdb/source.c ---- a/gdb/source.c -+++ b/gdb/source.c -@@ -1199,7 +1199,7 @@ open_source_file (struct symtab *s) - srcpath += s->filename; - } - -- const struct bfd_build_id *build_id = build_id_bfd_get (ofp->obfd); -+ const struct bfd_build_id *build_id = build_id_bfd_shdr_get (ofp->obfd); - - /* Query debuginfod for the source file. */ - if (build_id != nullptr && !srcpath.empty ()) -diff --git a/gdb/symfile.h b/gdb/symfile.h ---- a/gdb/symfile.h -+++ b/gdb/symfile.h -@@ -332,12 +332,18 @@ bool expand_symtabs_matching - void map_symbol_filenames (gdb::function_view fun, - bool need_fullname); - -+ - /* Target-agnostic function to load the sections of an executable into memory. - - ARGS should be in the form "EXECUTABLE [OFFSET]", where OFFSET is an - optional offset to apply to each section. */ - extern void generic_load (const char *args, int from_tty); - -+/* build-id support. */ -+extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr); -+extern void debug_print_missing (const char *binary, const char *debug); -+#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file") -+ - /* From minidebug.c. */ - - extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *); -diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp ---- a/gdb/testsuite/gdb.base/corefile.exp -+++ b/gdb/testsuite/gdb.base/corefile.exp -@@ -343,3 +343,33 @@ gdb_test_multiple "core-file $corefile" $test { - pass $test - } - } -+ -+ -+# Test auto-loading of binary files through build-id from the core file. -+set buildid [build_id_debug_filename_get $binfile] -+set wholetest "binfile found by build-id" -+if {$buildid == ""} { -+ untested "$wholetest (binary has no build-id)" -+} else { -+ gdb_exit -+ gdb_start -+ -+ regsub {\.debug$} $buildid {} buildid -+ set debugdir [standard_output_file ${testfile}-debugdir] -+ file delete -force -- $debugdir -+ file mkdir $debugdir/[file dirname $buildid] -+ file copy $binfile $debugdir/$buildid -+ -+ set test "show debug-file-directory" -+ gdb_test_multiple $test $test { -+ -re "The directory where separate debug symbols are searched for is \"(.*)\"\\.\r\n$gdb_prompt $" { -+ set debugdir_orig $expect_out(1,string) -+ pass $test -+ } -+ } -+ gdb_test_no_output "set debug-file-directory $debugdir:$debugdir_orig" "set debug-file-directory" -+ gdb_test "show build-id-core-loads" {Whether CORE-FILE loads the build-id associated files automatically is on\.} -+ gdb_test "core-file $corefile" "\r\nProgram terminated with .*" "core-file without executable" -+ gdb_test "info files" "Local exec file:\r\n\[ \t\]*`[string_to_regexp $debugdir/$buildid]', file type .*" -+ pass $wholetest -+} -diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp ---- a/gdb/testsuite/gdb.base/gdbinit-history.exp -+++ b/gdb/testsuite/gdb.base/gdbinit-history.exp -@@ -185,7 +185,8 @@ proc test_empty_history_filename { } { - global env - global gdb_prompt - -- set common_history [list "set height 0" "set width 0"] -+ set common_history [list "set height 0" "set width 0" \ -+ "set build-id-verbose 0"] - - set test_dir [standard_output_file history_test] - remote_exec host "mkdir -p $test_dir" -diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb.base/new-ui-pending-input.exp ---- a/gdb/testsuite/gdb.base/new-ui-pending-input.exp -+++ b/gdb/testsuite/gdb.base/new-ui-pending-input.exp -@@ -62,6 +62,7 @@ proc test_command_line_new_ui_pending_input {} { - set options "" - append options " -iex \"set height 0\"" - append options " -iex \"set width 0\"" -+ append options " -iex \"set build-id-verbose 0\"" - append options " -iex \"new-ui console $extra_tty_name\"" - append options " -ex \"b $bpline\"" - append options " -ex \"run\"" -diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp ---- a/gdb/testsuite/lib/gdb.exp -+++ b/gdb/testsuite/lib/gdb.exp -@@ -141,7 +141,8 @@ if ![info exists INTERNAL_GDBFLAGS] { - "-nx" \ - "-data-directory $BUILD_DATA_DIRECTORY" \ - {-iex "set height 0"} \ -- {-iex "set width 0"}]] -+ {-iex "set width 0"} \ -+ {-iex "set build-id-verbose 0"}]] - } - - # The variable gdb_prompt is a regexp which matches the gdb prompt. -@@ -2200,6 +2201,17 @@ proc default_gdb_start { } { - } - } - -+ # Turn off the missing warnings as the testsuite does not expect it. -+ send_gdb "set build-id-verbose 0\n" -+ gdb_expect 10 { -+ -re "$gdb_prompt $" { -+ verbose "Disabled the missing debug infos warnings." 2 -+ } -+ timeout { -+ warning "Could not disable the missing debug infos warnings.." -+ } -+ } -+ - gdb_debug_init - return 0 - } -diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp ---- a/gdb/testsuite/lib/mi-support.exp -+++ b/gdb/testsuite/lib/mi-support.exp -@@ -322,6 +322,16 @@ proc default_mi_gdb_start { args } { - warning "Couldn't set the width to 0." - } - } -+ # Turn off the missing warnings as the testsuite does not expect it. -+ send_gdb "190-gdb-set build-id-verbose 0\n" -+ gdb_expect 10 { -+ -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" { -+ verbose "Disabled the missing debug infos warnings." 2 -+ } -+ timeout { -+ warning "Could not disable the missing debug infos warnings.." -+ } -+ } - - if { $separate_inferior_pty } { - mi_create_inferior_pty diff --git a/rpm/gdb-add-index.patch b/rpm/gdb-add-index.patch new file mode 100644 index 0000000..52a3145 --- /dev/null +++ b/rpm/gdb-add-index.patch @@ -0,0 +1,77 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Fedora GDB patches +Date: Fri, 27 Oct 2017 21:07:50 +0200 +Subject: gdb-add-index.patch + +;; Update gdb-add-index.sh such that, when the GDB environment +;; variable is not set, the script is smarter than just looking for +;; 'gdb' in the $PATH. +;; +;; The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +;; $PATH), then /usr/libexec/gdb. +;; +;; For the rationale of looking for gdb.minimal see: +;; +;; https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +;; +;;=fedora + +diff --git a/gdb/contrib/gdb-add-index.sh b/gdb/contrib/gdb-add-index.sh +--- a/gdb/contrib/gdb-add-index.sh ++++ b/gdb/contrib/gdb-add-index.sh +@@ -16,14 +16,52 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# This program assumes gdb and objcopy are in $PATH. +-# If not, or you want others, pass the following in the environment +-GDB=${GDB:=gdb} ++# This program assumes objcopy and readelf are in $PATH. If not, or ++# you want others, pass the following in the environment + OBJCOPY=${OBJCOPY:=objcopy} + READELF=${READELF:=readelf} + + myname="${0##*/}" + ++# For GDB itself we need to be a little smarter. If GDB is set in the ++# environment then we will use that. But if GDB is not set in the ++# environment then we have a couple of options that we need to check ++# through. ++# ++# Our default choice is for /usr/bin/gdb.minimal. For an explanation ++# of why this is chosen, check out: ++# https://bugzilla.redhat.com/show_bug.cgi?id=1695015 ++# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot ++# ++# If gdb.minimal is not found then we look for a 'gdb' executable on ++# the path. ++# ++# And finally, we check for /usr/libexec/gdb. ++# ++# If none of those result in a useable GDB then we give an error and ++# exit. ++if test -z "$GDB"; then ++ for possible_gdb in /usr/bin/gdb.minimal gdb /usr/libexec/gdb; do ++ if ! command -v "$possible_gdb" >/dev/null 2>&1; then ++ continue ++ fi ++ ++ possible_gdb=$(command -v "$possible_gdb") ++ ++ if ! test -x "$possible_gdb"; then ++ continue ++ fi ++ ++ GDB="$possible_gdb" ++ break ++ done ++ ++ if test -z "$GDB"; then ++ echo "$myname: Failed to find a useable GDB binary" 1>&2 ++ exit 1 ++ fi ++fi ++ + dwarf5="" + if [ "$1" = "-dwarf-5" ]; then + dwarf5="$1" diff --git a/rpm/gdb-fix-bg-execution-repeat.patch b/rpm/gdb-fix-bg-execution-repeat.patch new file mode 100644 index 0000000..d255c25 --- /dev/null +++ b/rpm/gdb-fix-bg-execution-repeat.patch @@ -0,0 +1,76 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= +Date: Fri, 25 Apr 2025 10:31:16 +0200 +Subject: gdb-fix-bg-execution-repeat.patch + +;; Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" + +[gdb/testsuite] Fix another timeout in gdb.base/bg-execution-repeat.exp + +With test-case gdb.base/bg-execution-repeat.exp, occasionally I run into a +timeout: +... +(gdb) c 1& +Will stop next time breakpoint 1 is reached. Continuing. +(gdb) PASS: $exp: c 1&: c 1& + +Breakpoint 2, foo () at bg-execution-repeat.c:23 +23 return 0; /* set break here */ +PASS: $exp: c 1&: breakpoint hit 1 + +Will stop next time breakpoint 2 is reached. Continuing. +(gdb) PASS: $exp: c 1&: repeat bg command +print 1 +$1 = 1 +(gdb) PASS: $exp: c 1&: input still accepted +interrupt +(gdb) PASS: $exp: c 1&: interrupt + +Program received signal SIGINT, Interrupt. +foo () at bg-execution-repeat.c:24 +24 } +PASS: $exp: c 1&: interrupt received +set var do_wait=0 +(gdb) PASS: $exp: c 1&: set var do_wait=0 +continue& +Continuing. +(gdb) PASS: $exp: c 1&: continue& +FAIL: $exp: c 1&: breakpoint hit 2 (timeout) +... + +I can reproduce it reliably by adding a "sleep (1)" before the "do_wait = 1" +in the .c file. + +The timeout happens as follows: +- with the inferior stopped at main, gdb continues (command c 1&) +- the inferior hits the breakpoint at foo +- gdb continues (using the repeat command functionality) +- the inferior is interrupted +- inferior variable do_wait gets set to 0. The assumption here is that the + inferior has progressed enough that do_wait is set to 1 at that point, but + that happens not to be the case. Consequently, this has no effect. +- gdb continues +- the inferior sets do_wait to 1 +- the inferior enters the wait function, and wait for do_wait to become 0, + which never happens. + +Fix this by moving the "do_wait = 1" to before the first call to foo. + +Tested on x86_64-linux. + +Reviewed-By: Alexandra Petlanova Hajkova + +diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.c b/gdb/testsuite/gdb.base/bg-execution-repeat.c +--- a/gdb/testsuite/gdb.base/bg-execution-repeat.c ++++ b/gdb/testsuite/gdb.base/bg-execution-repeat.c +@@ -37,9 +37,9 @@ main (void) + { + alarm (60); + ++ do_wait = 1; + foo (); + +- do_wait = 1; + wait (); + /* do_wait set to 0 externally. */ + diff --git a/rpm/gdb-rpm-suggestion-script-sailfishos.patch b/rpm/gdb-rpm-suggestion-script-sailfishos.patch new file mode 100644 index 0000000..5197f4f --- /dev/null +++ b/rpm/gdb-rpm-suggestion-script-sailfishos.patch @@ -0,0 +1,135 @@ +From bc6925b06dce91529b94d7c288b63ed488ed76df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Matti=20Lehtim=C3=A4ki?= +Date: Mon, 17 Nov 2025 19:41:43 +0200 +Subject: [PATCH] Adjust rpm suggestion script for Sailfish OS + +Use zypper instead of dnf and print each suggestion separately with +filename to match the way old patches worked. +--- + gdb/python/lib/gdb/command/rpm-suggestions.py | 43 ++++++++++--------- + 1 file changed, 22 insertions(+), 21 deletions(-) + +diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py +index 9aef76303c1..f585adbaf29 100644 +--- a/gdb/python/lib/gdb/command/rpm-suggestions.py ++++ b/gdb/python/lib/gdb/command/rpm-suggestions.py +@@ -122,22 +122,23 @@ else: + __suggest_build_ids[build_id] = True + __missing_build_ids[build_id] = True + +- # Return true if '/usr/lib' is in the debug-file-directory list. +- # System packages install their debug information into /usr/lib, ++ # Return true if '/usr/lib' or '/home/.system/usr/lib' is in ++ # the debug-file-directory list. System packages install their ++ # debug information into /usr/lib or /home/.system/usr/lib, + # so if GDB isn't looking in that directory, then there's no + # reason to try and figure out a suitable RPM to install. + def using_suitable_debug_file_directory(): + debug_file_directories = gdb.parameter("debug-file-directory") + for d in debug_file_directories.split(os.pathsep): +- if d[:8] == "/usr/lib": ++ if d[:8] == "/usr/lib" or d[:21] == "/home/.system/usr/lib": + return True + return False + + # Return True if rpm-suggestion is disabled for any reason. + def rpm_suggestion_is_disabled(): +- # If /usr/lib/ is not being used to find debug information +- # then there's no point offering any RPMs as GDB would not +- # find the newly installed content. ++ # If /usr/lib/ or /home/.system/usr/lib is not being used to ++ # find debug information then there's no point offering any RPMs ++ # as GDB would not find the newly installed content. + if not using_suitable_debug_file_directory(): + return True + +@@ -170,7 +171,9 @@ else: + if is_rpm_installed(ts, rpm_name): + continue + +- add_rpm_suggestion(rpm_name) ++ print("Missing separate debuginfo for " + filename) ++ print("Try: zypper install " + rpm_name) ++ #add_rpm_suggestion(rpm_name) + + + # Return a string which is the filename of the filename +@@ -193,11 +196,11 @@ else: + + return filename + +- # A regexp object used to match against the output of `dnf`. This ++ # A regexp object used to match against the output of `zypper`. This + # is initialised the first time it is needed. + find_objfile_suggestions_re = None + +- # Given BUILD_ID, a string containing a build-id, run a `dnf` ++ # Given BUILD_ID, a string containing a build-id, run a `zypper` + # command to figure out if any RPMs can provide a file with that + # build-id. + # +@@ -211,9 +214,9 @@ else: + global find_objfile_suggestions_re + + if find_objfile_suggestions_re is None: +- find_objfile_suggestions_re = re.compile("^(.*)-debuginfo-(.*) : Debug information for package (.*)$") ++ find_objfile_suggestions_re = re.compile("^.* \| (.*)-debuginfo \| Debug information for package (.*) \| package$") + +- result = subprocess.run(['dnf', "--enablerepo=*debug*", '--nogpgcheck', '-C', 'provides', ++ result = subprocess.run(['zypper', '--no-gpg-checks', '--no-refresh', 'wp', + build_id_to_usr_lib_filename(build_id, True)], + capture_output=True, timeout=30) + +@@ -224,11 +227,11 @@ else: + m = find_objfile_suggestions_re.match(l) + if not m: + continue +- if m.group(1) != m.group(3): ++ if m.group(1) != m.group(2): + return + +- main_rpm = m.group(1) + '-' + m.group(2) +- dbg_rpm = m.group(1) + '-debuginfo-' + m.group(2) ++ main_rpm = m.group(1) ++ dbg_rpm = m.group(1) + '-debuginfo' + + if not is_rpm_installed(ts, main_rpm): + add_rpm_suggestion(main_rpm) +@@ -351,7 +354,7 @@ else: + # Take a non-empty list of RPM names and print a command line a + # user could run to install these RPMs. + def print_rpm_suggestions(rpm_name_list): +- print("Missing rpms, try: dnf --enablerepo='*debug*' install " + ' '.join(rpm_name_list)) ++ print("Missing rpms, try: zypper install " + ' '.join(rpm_name_list)) + + # Take a non-empty list of build-id strings and print a series of + # lines that a user could run to instll the RPMs that provide +@@ -361,21 +364,19 @@ else: + # packages for the executable with the given build-id. + def print_build_id_suggestions(build_id_list): + for build_id in build_id_list: +- print("Missing file(s), try: dnf --enablerepo='*debug*' install " +- + build_id_to_usr_lib_filename(build_id, False) +- + ' ' +- + build_id_to_usr_lib_filename(build_id, True, ".debug")) ++ print("Missing file(s), try: zypper install " ++ + '-C \"debuginfo(build-id)='+ build_id + '\"') + + # Called before GDB displays its prompt. If the global __SUGGEST_RPMS + # dictionary is not empty, then this hook prints the keys of this + # dictionary as strings which are the names of RPMs. This hook formats +- # each RPM name into a suggested 'dnf install' command and suggests this ++ # each RPM name into a suggested 'zypper install' command and suggests this + # to the user. + # + # Additionally, if the global __SUGGEST_BUILD_IDS dictionary is not + # empty, then this hook uses the keys of this dictionary as build-ids + # that were found to be missing, and formats these into some file based +- # 'dnf install' suggestions to the user. ++ # 'zypper install' suggestions to the user. + def before_prompt(): + global __suggest_rpms + global __suggest_build_ids +-- +2.34.1 + diff --git a/rpm/gdb-rpm-suggestion-script.patch b/rpm/gdb-rpm-suggestion-script.patch new file mode 100644 index 0000000..c7ecf91 --- /dev/null +++ b/rpm/gdb-rpm-suggestion-script.patch @@ -0,0 +1,1011 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Andrew Burgess +Date: Thu, 7 Mar 2024 15:14:23 +0000 +Subject: gdb-rpm-suggestion-script.patch + +;; Not a backport. Add a new script which hooks into GDB and suggests +;; RPMs to install when GDB finds an objfile with no debug info. + +gdb: add script which will suggest debuginfo RPMs to install + +This script hooks into GDB's missing debug info Python API and +suggests debuginfo RPMs to install. + +diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in +--- a/gdb/data-directory/Makefile.in ++++ b/gdb/data-directory/Makefile.in +@@ -92,6 +92,7 @@ PYTHON_FILE_LIST = \ + gdb/command/missing_files.py \ + gdb/command/pretty_printers.py \ + gdb/command/prompt.py \ ++ gdb/command/rpm-suggestions.py \ + gdb/command/type_printers.py \ + gdb/command/unwinders.py \ + gdb/command/xmethods.py \ +diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo +--- a/gdb/doc/gdb.texinfo ++++ b/gdb/doc/gdb.texinfo +@@ -186,6 +186,7 @@ software in general. We will miss him. + * Trace File Format:: @value{GDBN} trace file format + * Index Section Format:: .gdb_index section format + * Debuginfod:: Download debugging resources with @code{debuginfod} ++* RPM Suggestions:: RPM Suggestions from GDB + * Man Pages:: Manual pages + * Copying:: GNU General Public License says + how you can copy and share @value{GDBN} +@@ -50588,6 +50589,111 @@ Show the current verbosity setting. + + @end table + ++@node RPM Suggestions ++@appendix Receiving RPM installation suggestions ++@cindex rpm suggestions ++ ++When @value{GDBN} loads an executable, or shared library, and cannot ++find the corresponding debug information, @value{GDBN} will check to ++see if an RPM is available which could provide the missing debug ++information. If a suitable RPM is found then @value{GDBN} will print ++a hint before the next prompt is displayed: ++ ++@smallexample ++(@value{GDBP}) file /bin/ls ++Reading symbols from /bin/ls... ++Reading symbols from .gnu_debugdata for /usr/bin/ls... ++(No debugging symbols found in .gnu_debugdata for /usr/bin/ls) ++Missing rpms, try: dnf --enablerepo='*debug*' install coreutils-debuginfo-9.3-7.fc39.x86_64 ++(@value{GDBP}) ++@end smallexample ++ ++In this case, installing @file{coreutils-debuginfo-9.3-7.fc39.x86_64} ++will provide the missing debug information for @file{/bin/ls}. It is ++up to you to install the suggested package, if possible, and after ++that reload the executable in @value{GDBN} so that the newly installed ++debug information can be found. ++ ++The RPM suggestion feature can be disabled: ++ ++@table @code ++@kindex set rpm-suggestion enabled ++@kindex show rpm-suggestion enabled ++@cindex rpm suggestions, disabling ++@item set rpm-suggestion enabled @r{[}on@r{|}off@r{]} ++@itemx show rpm-suggestion enabled ++When @samp{on} @value{GDBN} will make RPM suggestions where possible. ++When @samp{off} all RPM suggestion will be disabled. ++@end table ++ ++When opening a core file (@pxref{core-file command}), it may be the ++case that not only is the debug information missing, but the ++corresponding executable itself is missing. For example, if a core ++file is copied from one machine to another in order to debug. ++ ++In this case @value{GDBN} is able to suggest a command which will ++install the missing executable based on the build-id of the ++executable. For example: ++ ++@smallexample ++(@value{GDBP}) core-file /tmp/core.5489 ++warning: Can't open file /usr/bin/sl during file-backed mapping note processing ++[New LWP 5489] ++Core was generated by `sl'. ++Program terminated with signal SIGQUIT, Quit. ++#0 0x00007f1b41ced1a7 in ?? () ++Missing file(s), try: dnf --enablerepo='*debug*' install /usr/lib/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3 /usr/lib/debug/.build-id/33/2f1a8e56693960e3beb2d70cd79ddfec451cc3.debug ++(@value{GDBP}) ++@end smallexample ++ ++The core file was generated from the @file{/usr/bin/sl} binary, which ++is not present on the machine opening the core file. @value{GDBN} has ++suggested a command, based on the build-id of the binary, which was ++extracted from the core file, that would install both the missing ++binary, and the corresponding debug information. ++ ++Unfortunately, @value{GDBN} doesn't know if the suggested command will ++actually find a matching RPM or not. Querying the RPM database to see ++which packages, if any, will provide a file with the given build-id, ++is rather slow. As @file{/usr/bin/sl} is available in an RPM, then ++the above command will succeed. ++ ++It is possible to have @value{GDBN} check to see if there is a package ++available before making the suggestion, but this is significantly ++slower. To enable this mode use the following command: ++ ++@table @code ++@kindex set rpm-suggestion build-id-mode ++@kindex show rpm-suggestion build-id-mode ++@cindex rpm suggestions, build-id-mode ++@item set rpm-suggestion build-id-mode @r{[}fast@r{|}slow@r{]} ++@itemx show rpm-suggestion build-id-mode ++When set to @samp{fast}, which is the default, @value{GDBN} will offer ++suggestions based on the build-id of any missing executables or shared ++libraries while opening a core file. This is fast, but @value{GDBN} ++has not checked if there is a package available that can supply the ++required file, so running the suggested command might not install any ++packages. ++ ++When set to @samp{slow}, each time @value{GDBN} encounters an ++executable, or shared library, that is missing, @value{GDBN} will ++check to see if there is an RPM available that will supply the missing ++binary. If a suitable RPM is found then @value{GDBN} will offer a ++command which will install the missing RPM. If no suitable RPM is ++found then @value{GDBN} will make no suggestions. ++@end table ++ ++It is possible to review all of the previous RPM suggestions that ++@value{GDBN} has made using the following command: ++ ++@table @code ++@kindex info rpm-suggestions ++@cindex rpm suggestions, listing ++@item info rpm-suggestions ++List all of the RPM suggestions @value{GDBN} has made since the ++executable was last changed. ++@end table ++ + @node Man Pages + @appendix Manual pages + @cindex Man pages +diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py +new file mode 100644 +--- /dev/null ++++ b/gdb/python/lib/gdb/command/rpm-suggestions.py +@@ -0,0 +1,527 @@ ++# Copyright 2023 Free Software Foundation, Inc. ++ ++# 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 3 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, see . ++ ++import gdb ++import gdb.missing_debug ++import gdb.missing_objfile ++ ++# These modules are all system modules, and should be available on any ++# correctly setup Python install. ++import sys ++import os ++import subprocess ++import re ++from threading import Thread ++import time ++ ++try: ++ import rpm ++except ModuleNotFoundError: ++ # The "RPM suggestions" mechanism will not work without the (python) ++ # rpm module. Inform the user of this, but wait to do so until ++ # just prior to printing the GDB prompt. If we do it right away, ++ # the message typically appears before the version and copyright ++ # info, which is easily missed by many users. Additionally, it ++ # seems that several other packages which parse GDB version info ++ # are confused by an early error message regarding a missing ++ # python3-rpm package, so waiting to print the error allows those ++ # applications to work as they used to. ++ def before_prompt(): ++ print( ++ ("\nUnable to load the Python 'rpm' module. Lack of this module disables\n" ++ "the RPM suggestions mechanism which recommends shell commands for\n" ++ "installing missing debuginfo packages. To enable this functionality,\n" ++ "please install the python3-rpm package."), ++ file=sys.stderr ++ ) ++ gdb.events.before_prompt.disconnect(before_prompt) ++ ++ gdb.events.before_prompt.connect(before_prompt) ++ ++ # Implement 'info rpm-suggestions' when the 'rpm' module is not ++ # available. Just throws an error. ++ def info_rpm_suggestions(): ++ raise gdb.GdbError("rpm-suggestions are disabled as the Python 'rpm' module is not installed") ++else: ++ # Track all the RPMs suggested during a single debug session so we ++ # don't suggest the same RPM twice. This is only cleared when the ++ # main executable is changed. ++ __missing_rpms = {} ++ ++ # Track any missing RPMs that have been discovered since the last time ++ # the prompt was displayed. RPMs in here are also present in the ++ # __MISSING_RPMS dictionary, but this dictionary is cleared each time ++ # the prompt is shown. ++ __suggest_rpms = {} ++ ++ # Track all the build-ids suggested during a single debug session so we ++ # don't suggest installing using the same build-id twice. This is only ++ # cleared when the main executable is changed. ++ __missing_build_ids = {} ++ ++ # Track any build-ids that have been discovered missing since the last ++ # time the prompt was displayed. Build-ids in here are also present in ++ # the __MISSING_BUILD_IDS dictionary, but this dictionary is cleared ++ # each time the prompt is shown. ++ __suggest_build_ids = {} ++ ++ # The build-id to RPM lookup is very slow. This cache maps ++ # build-ids to the set of RPM we can suggest installing. The key ++ # is the build-id string, and the value is a list of RPM names, or ++ # None if there was an error with the build-id to RPM lookup. ++ # ++ # This cache is never cleared, even when the executable is ++ # changed. The build-ids should be unique, so a build-id lookup ++ # should be good for the lifetime of the session. ++ __build_id_lookup_cache = {} ++ ++ # When searching for an RPM given a build-id, if the search takes ++ # too long, then a message is printed to the user. We only print ++ # the message once between each GDB prompt. This flag is set True ++ # when the message is printed, and reset to False when a prompt is ++ # displayed. ++ __searching_message_printed = False ++ ++ # Add a suggestion to install RPM_NAME (the full name of an RPM) ++ # to the list of suggestions to make the next time a prompt is ++ # displayed. ++ def add_rpm_suggestion(rpm_name): ++ global __missing_rpms ++ global __suggest_rpms ++ ++ if not rpm_name in __missing_rpms: ++ __suggest_rpms[rpm_name] = True ++ __missing_rpms[rpm_name] = True ++ ++ # Return True if RPM_NAME is installed, where RPM_NAME is the full ++ # name of an RPM. ++ def is_rpm_installed(ts, rpm_name): ++ res = ts.dbMatch(rpm.RPMDBI_LABEL, rpm_name) ++ return len(res) > 0 ++ ++ # Add a suggestion to install RPMs based on BUILD_ID, a string ++ # containing a build-id, to the list of suggestions to make the next ++ # time a prompt is displayed. ++ def add_build_id_suggestion(build_id): ++ global __missing_build_ids ++ global __suggest_build_ids ++ ++ if not build_id in __missing_build_ids: ++ __suggest_build_ids[build_id] = True ++ __missing_build_ids[build_id] = True ++ ++ # Return true if '/usr/lib' is in the debug-file-directory list. ++ # System packages install their debug information into /usr/lib, ++ # so if GDB isn't looking in that directory, then there's no ++ # reason to try and figure out a suitable RPM to install. ++ def using_suitable_debug_file_directory(): ++ debug_file_directories = gdb.parameter("debug-file-directory") ++ for d in debug_file_directories.split(os.pathsep): ++ if d[:8] == "/usr/lib": ++ return True ++ return False ++ ++ # Return True if rpm-suggestion is disabled for any reason. ++ def rpm_suggestion_is_disabled(): ++ # If /usr/lib/ is not being used to find debug information ++ # then there's no point offering any RPMs as GDB would not ++ # find the newly installed content. ++ if not using_suitable_debug_file_directory(): ++ return True ++ ++ # Is 'rpm-suggestion enabled' set to 'off'? ++ if not param_rpm_suggestion_enabled.value: ++ return True ++ ++ return False ++ ++ ++ # Lookup RPMs that might provide the debug information for FILENAME, ++ # which is a string containing the path to an object file GDB could ++ # not find any debug information for. ++ # ++ # If a possible RPM is found then this is added to the globals ++ # __MISSING_RPMS and __SUGGEST_RPMS, which are used elsewhere in this ++ # script. ++ def find_debug_suggestions(filename): ++ if rpm_suggestion_is_disabled(): ++ return ++ ++ ts = rpm.TransactionSet() ++ mi = ts.dbMatch(rpm.RPMDBI_BASENAMES, filename) ++ for h in mi: ++ # Build the debuginfo package name. ++ obj = h.format("%{name}-debuginfo-%{version}-%{release}.%{arch}") ++ rpm_name = str(obj) ++ ++ # Check to see if the package is installed. ++ if is_rpm_installed(ts, rpm_name): ++ continue ++ ++ add_rpm_suggestion(rpm_name) ++ ++ ++ # Return a string which is the filename of the filename ++ # corresponding to BUILD_ID in one of the two locations under ++ # /usr/lib. ++ # ++ # When DEBUG_P is True, return a filename within: ++ # /usr/lib/debug/.build-id/ and when DEBUG_P is False, return a ++ # filename within: /usr/lib/.build-id/. ++ # ++ # The SUFFIX string is appended to the generated filename. ++ def build_id_to_usr_lib_filename(build_id, debug_p, suffix = ""): ++ key = build_id[:2] ++ rst = build_id[2:] ++ ++ filename = '/usr/lib' ++ if debug_p: ++ filename += '/debug' ++ filename += '/.build-id/' + key + '/' + rst + suffix ++ ++ return filename ++ ++ # A regexp object used to match against the output of `dnf`. This ++ # is initialised the first time it is needed. ++ find_objfile_suggestions_re = None ++ ++ # Given BUILD_ID, a string containing a build-id, run a `dnf` ++ # command to figure out if any RPMs can provide a file with that ++ # build-id. ++ # ++ # If any suitable RPMs are found then `add_rpm_suggestion` is called ++ # to register the suggestion. ++ # ++ # This function is pretty slow, which is a shame, as the results ++ # returned are much nicer than just telling the user to try the ++ # lookup command for themselves. ++ def find_objfile_suggestions_in_thread(build_id): ++ global find_objfile_suggestions_re ++ ++ if find_objfile_suggestions_re is None: ++ find_objfile_suggestions_re = re.compile("^(.*)-debuginfo-(.*) : Debug information for package (.*)$") ++ ++ result = subprocess.run(['dnf', "--enablerepo=*debug*", '--nogpgcheck', '-C', 'provides', ++ build_id_to_usr_lib_filename(build_id, True)], ++ capture_output=True, timeout=30) ++ ++ lines = result.stdout.decode('utf-8').splitlines() ++ ts = rpm.TransactionSet() ++ ++ for l in lines: ++ m = find_objfile_suggestions_re.match(l) ++ if not m: ++ continue ++ if m.group(1) != m.group(3): ++ return ++ ++ main_rpm = m.group(1) + '-' + m.group(2) ++ dbg_rpm = m.group(1) + '-debuginfo-' + m.group(2) ++ ++ if not is_rpm_installed(ts, main_rpm): ++ add_rpm_suggestion(main_rpm) ++ ++ if not is_rpm_installed(ts, dbg_rpm): ++ add_rpm_suggestion(dbg_rpm) ++ ++ return ++ ++ # Call `find_objfile_suggestions_in_thread` is a separate thread, ++ # then wait for the thread to complete. Don't touch any shared ++ # state while waiting for the thread to complete. There's no ++ # locking on any of our caches, and the worker thread will add RPM ++ # suggestions as it wants. ++ # ++ # If thre thread takes too long to complete then print a message ++ # to the user telling them what's going on. ++ def find_objfile_suggestions_slow_core(build_id): ++ global __searching_message_printed ++ ++ thread = Thread(target = find_objfile_suggestions_in_thread, args = (build_id, )) ++ thread.start() ++ start = time.time_ns() ++ ++ while thread.is_alive (): ++ time.sleep(0.05) ++ now = time.time_ns () ++ if not __searching_message_printed and (now - start > 1000000000): ++ print("Searching for packages to install that could improve debugging...") ++ __searching_message_printed = True ++ ++ thread.join() ++ ++ ++ # Given BUILD_ID, a string containing a build-id, lookup suitable ++ # RPMs that could be installed to provide a file with the required ++ # build-id. ++ # ++ # Any suitable RPMs are recorded by calling `add_rpm_suggestion`, and ++ # will be printed before the next prompt. ++ def find_objfile_suggestions_slow(build_id): ++ global __build_id_lookup_cache ++ global __suggest_rpms ++ ++ # The code to lookup an RPM given only a build-id is pretty ++ # slow. Cache the results to try and reduce the UI delays. ++ if build_id in __build_id_lookup_cache: ++ rpms = __build_id_lookup_cache[build_id] ++ if rpms is not None: ++ for r in rpms: ++ add_rpm_suggestion(r) ++ return ++ ++ # Make sure the cache entry exists before we do the lookup. ++ # If, for any reason, the lookup raises an exception, then ++ # having a cache entry will prevent us retrying this lookup in ++ # the future. ++ __build_id_lookup_cache[build_id] = None ++ ++ # Now do the lookup. This is the slow part. ++ find_objfile_suggestions_slow_core(build_id) ++ ++ # Fill in the cache, for a given build-id which RPMs were ++ # suggested. ++ rpms = [] ++ for r in __suggest_rpms: ++ rpms.append(r) ++ __build_id_lookup_cache[build_id] = rpms ++ ++ ++ # Given BUILD_ID, a string containing a build-id, just record that we ++ # should advise the user to try installing RPMs based on this build-id. ++ def find_objfile_suggestions_fast(build_id): ++ add_build_id_suggestion(build_id) ++ ++ # Given BUILD_ID, a string containing a build-id, which GDB has failed ++ # to find, possibly record some information so that we can, at the next ++ # prompt, give some RPM installation advice to the user. ++ # ++ # We have two different strategies for RPM lookup based on a build-id, ++ # one approach is that we actually lookup the RPMs and only suggest ++ # something if there is a suitable RPM. However, this is pretty slow, ++ # and users will probably find this annoying. ++ # ++ # So we also have a fast way. With this approach we just record the ++ # build-id that was missing and tell the user to try installing based on ++ # the build-id. The downside with this is that if there is no RPM for ++ # that build-id, then the user will try the command, but nothing will ++ # install. ++ def find_objfile_suggestions(build_id): ++ if rpm_suggestion_is_disabled(): ++ return ++ ++ if param_rpm_suggestion_build_id_mode.fast_mode(): ++ find_objfile_suggestions_fast(build_id) ++ else: ++ find_objfile_suggestions_slow(build_id) ++ ++ # A missing debug handler class. Just forwards the name of the ++ # objfile for which we are missing debug information to ++ # find_debug_suggestions. ++ class RPM_MissingDebugHandler(gdb.missing_debug.MissingDebugHandler): ++ def __init__(self): ++ super().__init__("rpm-suggestions") ++ ++ def __call__(self, objfile): ++ find_debug_suggestions(objfile.filename) ++ return False ++ ++ # A missing objfile handler class. Just forwards the build-id of ++ # the objfile that is missing to find_objfile_suggestions. ++ class RPM_MissingObjfileHandler(gdb.missing_objfile.MissingObjfileHandler): ++ def __init__(self): ++ super().__init__("rpm-suggestions") ++ ++ def __call__(self, pspace, build_id, filename): ++ find_objfile_suggestions(build_id) ++ return False ++ ++ # Take a non-empty list of RPM names and print a command line a ++ # user could run to install these RPMs. ++ def print_rpm_suggestions(rpm_name_list): ++ print("Missing rpms, try: dnf --enablerepo='*debug*' install " + ' '.join(rpm_name_list)) ++ ++ # Take a non-empty list of build-id strings and print a series of ++ # lines that a user could run to instll the RPMs that provide ++ # files with this build-id. ++ # ++ # The printed commands will also install the corresponding debug ++ # packages for the executable with the given build-id. ++ def print_build_id_suggestions(build_id_list): ++ for build_id in build_id_list: ++ print("Missing file(s), try: dnf --enablerepo='*debug*' install " ++ + build_id_to_usr_lib_filename(build_id, False) ++ + ' ' ++ + build_id_to_usr_lib_filename(build_id, True, ".debug")) ++ ++ # Called before GDB displays its prompt. If the global __SUGGEST_RPMS ++ # dictionary is not empty, then this hook prints the keys of this ++ # dictionary as strings which are the names of RPMs. This hook formats ++ # each RPM name into a suggested 'dnf install' command and suggests this ++ # to the user. ++ # ++ # Additionally, if the global __SUGGEST_BUILD_IDS dictionary is not ++ # empty, then this hook uses the keys of this dictionary as build-ids ++ # that were found to be missing, and formats these into some file based ++ # 'dnf install' suggestions to the user. ++ def before_prompt(): ++ global __suggest_rpms ++ global __suggest_build_ids ++ global __searching_message_printed ++ ++ # We allow the searching message to be printed just once ++ # between prompts. ++ __searching_message_printed = False ++ ++ if len(__suggest_rpms) > 0: ++ print_rpm_suggestions(__suggest_rpms.keys()) ++ __suggest_rpms = {} ++ ++ if len(__suggest_build_ids) > 0: ++ print_build_id_suggestions(__suggest_build_ids.keys()) ++ __suggest_build_ids = {} ++ ++ # Called when the executable within a progrm space is changed. Clear ++ # the lists of RPM suggestions. We only clear the previous suggestion ++ # list when the executable really changes. If the user simply ++ # recompiles the executable, then we don't both clearing this list. ++ def executable_changed_handler(event): ++ global __missing_rpms ++ global __suggest_rpms ++ global __suggest_build_ids ++ global __missing_build_ids ++ ++ if not event.reload: ++ __missing_rpms = {} ++ __suggest_rpms = {} ++ __missing_build_ids = {} ++ __suggest_build_ids = {} ++ ++ ++ # Attach to the required GDB events. ++ gdb.events.executable_changed.connect(executable_changed_handler) ++ gdb.events.before_prompt.connect(before_prompt) ++ ++ # Register the missing debug and missing objfile handlers with GDB. ++ gdb.missing_debug.register_handler(None, RPM_MissingDebugHandler()) ++ gdb.missing_objfile.register_handler(None, RPM_MissingObjfileHandler()) ++ ++ # Implement the core of 'info rpm-suggestions'. Reprint all rpm ++ # suggestions. ++ def info_rpm_suggestions(): ++ global __missing_rpms ++ global __missing_build_ids ++ ++ if len(__missing_rpms) == 0 and len(__missing_build_ids) == 0: ++ print("No RPM suggestions have been made so far.") ++ return ++ ++ if len(__missing_rpms) > 0: ++ print_rpm_suggestions(__missing_rpms.keys()) ++ if len(__missing_build_ids) > 0: ++ print_build_id_suggestions(__missing_build_ids.keys()) ++ ++#################################################################### ++# The following code is outside the 'else' block of the attempt to # ++# load the 'rpm' module. Nothing after this point depends on the # ++# 'rpm' module. # ++#################################################################### ++ ++# The 'set rpm-suggestion' prefix command. ++class rpm_suggestion_set_prefix(gdb.Command): ++ """Prefix command for 'set' rpm-suggestion related commands.""" ++ ++ def __init__(self): ++ super().__init__("set rpm-suggestion", gdb.COMMAND_NONE, ++ gdb.COMPLETE_NONE, True) ++ ++# The 'show rpm-suggestion' prefix command. ++class rpm_suggestion_show_prefix(gdb.Command): ++ """Prefix command for 'show' rpm-suggestion related commands.""" ++ ++ def __init__(self): ++ super().__init__("show rpm-suggestion", gdb.COMMAND_NONE, ++ gdb.COMPLETE_NONE, True) ++ ++# The 'set/show rpm-suggestion enabled' command. ++class rpm_suggestion_enabled(gdb.Parameter): ++ """ ++ When 'on' GDB will search for RPMS that might provide additional ++ debug information, or provide missing executables or shared ++ libraries (when opening a core file), and will make suggestions ++ about what should be installed. ++ ++ When 'off' GDB will not make these suggestions. ++ """ ++ ++ set_doc = "Set whether to perform rpm-suggestion." ++ show_doc = "Show whether rpm-suggestion is enabled." ++ ++ def __init__(self): ++ super().__init__("rpm-suggestion enabled", gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN) ++ self.value = True ++ ++# The 'set/show rpm-suggestion enabled' command. ++class rpm_suggestion_build_id_mode(gdb.Parameter): ++ """ ++ When set to 'fast' (the default), GDB doesn't try to map a build-id to ++ an actual RPM, instead, GDB just suggests a command based on the ++ build-id which might install some RPMs, if there are any RPMs that ++ supply that build-id. However, it is equally possible that there are no ++ suitable RPMs, and nothing will install. This approach has almost zero ++ overhead. ++ ++ When set to 'slow', GDB first does the build-id to RPM check itself, and ++ only if something is found are RPMs installation commands suggested. ++ The suggested command will include the name of the RPM to install. This ++ approach is considerably slower as querying the RPM database for the RPM ++ that supplies a specific file is slow. ++ """ ++ ++ set_doc = "Set how build-id based rpm suggestions should be performed." ++ show_doc = "Show how build-id based rpm suggestions shoud be performed." ++ ++ def __init__(self): ++ super().__init__("rpm-suggestion build-id-mode", ++ gdb.COMMAND_NONE, gdb.PARAM_ENUM, ["fast", "slow"]) ++ self.value = "fast" ++ ++ def fast_mode(self): ++ return self.value == "fast" ++ ++# The 'info rpm-suggestions' command. ++class rpm_suggestion_info(gdb.Command): ++ """Relist RPM suggestions. ++ ++ Relist any RPM installation suggestions that have been made ++ since the executable was last changed.""" ++ def __init__(self): ++ super().__init__("info rpm-suggestions", gdb.COMMAND_NONE, gdb.COMPLETE_NONE) ++ ++ def invoke(self, args, from_tty): ++ if args != "": ++ raise gdb.GdbError("unexpected arguments: %s" % args) ++ ++ info_rpm_suggestions () ++ ++ ++# Create the 'set/show rpm-suggestion' commands. ++rpm_suggestion_set_prefix() ++rpm_suggestion_show_prefix() ++param_rpm_suggestion_enabled = rpm_suggestion_enabled() ++param_rpm_suggestion_build_id_mode = rpm_suggestion_build_id_mode() ++ ++# Create the 'info rpm-suggestions' commands. ++rpm_suggestion_info() +diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-lib.c +@@ -0,0 +1,21 @@ ++/* Copyright 2010 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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 3 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, see . */ ++ ++void ++lib (void) ++{ ++} +diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib-main.c +@@ -0,0 +1,25 @@ ++/* Copyright 2010 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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 3 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, see . */ ++ ++extern void lib (void); ++ ++int ++main (void) ++{ ++ lib (); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp +@@ -0,0 +1,104 @@ ++# Copyright 2016 Free Software Foundation, Inc. ++ ++# 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 3 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, see . ++ ++require allow_shlib_tests ++ ++set testfile "gcore-buildid-exec-but-not-solib" ++set srcmainfile ${testfile}-main.c ++set srclibfile ${testfile}-lib.c ++set libfile [standard_output_file ${testfile}-lib.so] ++set objfile [standard_output_file ${testfile}-main.o] ++set executable ${testfile}-main ++set binfile [standard_output_file ${executable}] ++set gcorefile [standard_output_file ${executable}.gcore] ++set outdir [file dirname $binfile] ++ ++if { [gdb_compile_shlib ${srcdir}/${subdir}/${srclibfile} ${libfile} "debug additional_flags=-Wl,--build-id"] != "" ++ || [gdb_compile ${srcdir}/${subdir}/${srcmainfile} ${objfile} object {debug}] != "" } { ++ unsupported "-Wl,--build-id compilation failed" ++ return -1 ++} ++set opts [list debug shlib=${libfile} "additional_flags=-Wl,--build-id"] ++if { [gdb_compile ${objfile} ${binfile} executable $opts] != "" } { ++ unsupported "-Wl,--build-id compilation failed" ++ return -1 ++} ++ ++clean_restart $executable ++gdb_load_shlib $libfile ++ ++# Does this gdb support gcore? ++set test "help gcore" ++gdb_test_multiple $test $test { ++ -re "Undefined command: .gcore.*\r\n$gdb_prompt $" { ++ # gcore command not supported -- nothing to test here. ++ unsupported "gdb does not support gcore on this target" ++ return -1; ++ } ++ -re "Save a core file .*\r\n$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++if { ![runto lib] } then { ++ return -1 ++} ++ ++set escapedfilename [string_to_regexp ${gcorefile}] ++ ++set test "save a corefile" ++gdb_test_multiple "gcore ${gcorefile}" $test { ++ -re "Saved corefile ${escapedfilename}\r\n$gdb_prompt $" { ++ pass $test ++ } ++ -re "Can't create a corefile\r\n$gdb_prompt $" { ++ unsupported $test ++ return -1 ++ } ++} ++ ++# Now restart gdb and load the corefile. ++ ++clean_restart $executable ++gdb_load_shlib $libfile ++ ++set buildid [build_id_debug_filename_get $libfile] ++ ++regsub {\.debug$} $buildid {} buildid ++ ++set debugdir [standard_output_file ${testfile}-debugdir] ++file delete -force -- $debugdir ++ ++file mkdir $debugdir/[file dirname $libfile] ++file copy $libfile $debugdir/${libfile} ++ ++file mkdir $debugdir/[file dirname $buildid] ++file copy $libfile $debugdir/${buildid} ++ ++remote_exec build "ln -s /lib ${debugdir}/" ++remote_exec build "ln -s /lib64 ${debugdir}/" ++# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2 ++ ++gdb_test_no_output "set solib-absolute-prefix $debugdir" \ ++ "set solib-absolute-prefix" ++ ++gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory" ++ ++gdb_test "core ${gcorefile}" "Core was generated by .*" "re-load generated corefile" ++ ++gdb_test "frame" "#0 \[^\r\n\]* lib .*" "library got loaded" ++ ++gdb_test "bt" ++gdb_test "info shared" +diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp +--- a/gdb/testsuite/gdb.base/gdbinit-history.exp ++++ b/gdb/testsuite/gdb.base/gdbinit-history.exp +@@ -179,7 +179,8 @@ proc test_empty_history_filename { } { + global env + global gdb_prompt + +- set common_history [list "set height 0" "set width 0"] ++ set common_history [list "set height 0" "set width 0" \ ++ "set rpm-suggestion enabled off"] + + set test_dir [standard_output_file history_test] + remote_exec host "mkdir -p $test_dir" +diff --git a/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/rhbz981154-misleading-yum-install-warning.exp +@@ -0,0 +1,60 @@ ++# Copyright (C) 2014 Free Software Foundation, Inc. ++ ++# 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 3 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, see . ++ ++# Create a core file, then hide the executable. Restart GDB and load ++# the core file. Check GDB gives a message suggesting a 'dnf' command ++# to try and install the executable based on its build-id. ++ ++standard_testfile "normal.c" ++ ++if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { ++ return -1 ++} ++ ++# Get the build-id of the file. ++set build_id_debug_file [build_id_debug_filename_get $binfile] ++regsub -all ".debug$" $build_id_debug_file "" build_id_without_debug ++ ++# Run to main. ++if { ![runto_main] } { ++ return -1 ++} ++ ++# We first need to generate a corefile. ++set corefilename "[standard_output_file gcore.test]" ++if { ![gdb_gcore_cmd "$corefilename" "save corefile"] } { ++ untested "could not generate a corefile" ++ return -1 ++} ++ ++# Move the binfile to a temporary name. ++remote_exec build "mv $binfile ${binfile}.old" ++ ++# Reinitialize GDB and see if we get a dnf suggestion. ++clean_restart ++ ++gdb_test "set rpm-suggestion enabled on" "" \ ++ "turn on rpm-suggestion feature" ++ ++# GDB only makes build-id based RPM suggestions if /usr/lib is in ++# the debug-file-directory list, the reason being that system RPMs ++# will always install under this location. If GDB is not looking ++# here then there's no point making suggestions. ++gdb_test "set debug-file-directory /usr/lib/" "" \ ++ "set debug-file-directory" ++ ++gdb_test "core-file [standard_output_file gcore.test]" \ ++ "Missing file\\(s\\), try: dnf --enablerepo='\\*debug\\*' install [string_to_regexp /usr/lib/$build_id_without_debug] [string_to_regexp /usr/lib/debug/$build_id_debug_file]" \ ++ "test first yum/dnf warning" +diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py +--- a/gdb/testsuite/gdb.python/py-missing-debug.py ++++ b/gdb/testsuite/gdb.python/py-missing-debug.py +@@ -19,6 +19,13 @@ from enum import Enum + import gdb + from gdb.missing_debug import MissingDebugHandler + ++# This is a RHEL/Fedora work around: There's already a ++# missing-debug-info handler registered for these versions of GDB. ++# Discard the handler now so that the tests will pass (the tests ++# assume no handler is currently registered). ++gdb.missing_debug_handlers = [] ++ ++ + # A global log that is filled in by instances of the LOG_HANDLER class + # when they are called. + handler_call_log = [] +@@ -118,4 +125,7 @@ def register(name, locus=None): + rhandler = exception_handler() + handler_obj = handler() + ++# Discard the rpm-suggestion handler. ++gdb.missing_file_handlers = [] ++ + print("Success") +diff --git a/gdb/testsuite/gdb.python/py-missing-objfile.py b/gdb/testsuite/gdb.python/py-missing-objfile.py +--- a/gdb/testsuite/gdb.python/py-missing-objfile.py ++++ b/gdb/testsuite/gdb.python/py-missing-objfile.py +@@ -164,4 +164,7 @@ def register(name, locus=None): + rhandler = exception_handler() + handler_obj = handler() + ++# Discard the rpm-suggestion handler. ++gdb.missing_file_handlers = [] ++ + print("Success") +diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp +--- a/gdb/testsuite/lib/gdb.exp ++++ b/gdb/testsuite/lib/gdb.exp +@@ -255,7 +255,8 @@ if ![info exists INTERNAL_GDBFLAGS] { + "-nx" \ + "-q" \ + {-iex "set height 0"} \ +- {-iex "set width 0"}]] ++ {-iex "set width 0"} \ ++ {-iex "set rpm-suggestion enabled off"}]] + + # If DEBUGINFOD_URLS is set, gdb will try to download sources and + # debug info for f.i. system libraries. Prevent this. +@@ -2610,6 +2611,18 @@ proc default_gdb_start { } { + } + } + ++ # Turn off the missing debug info messages as the testsuite does ++ # not expect them. ++ send_gdb "set rpm-suggestion enabled off\n" ++ gdb_expect 10 { ++ -re "$gdb_prompt $" { ++ verbose "Disabled the missing debug info messages." 2 ++ } ++ timeout { ++ warning "Could not disable the missing debug info messages." ++ } ++ } ++ + gdb_debug_init + return 0 + } +diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp +--- a/gdb/testsuite/lib/mi-support.exp ++++ b/gdb/testsuite/lib/mi-support.exp +@@ -321,6 +321,17 @@ proc default_mi_gdb_start { { flags {} } } { + warning "Couldn't set the width to 0." + } + } ++ # Turn off the missing debug info messages as the testsuite does ++ # not expect them. ++ send_gdb "190-gdb-set rpm-suggestion enabled off\n" ++ gdb_expect 10 { ++ -re ".*190-gdb-set rpm-suggestion enabled off\r\n190\\\^done\r\n$mi_gdb_prompt$" { ++ verbose "Disabled the missing debug info messages." 2 ++ } ++ timeout { ++ warning "Could not disable the missing debug info messages." ++ } ++ } + + if { $separate_inferior_pty } { + mi_create_inferior_pty diff --git a/rpm/gdb.spec b/rpm/gdb.spec index 21fe200..7dc0105 100644 --- a/rpm/gdb.spec +++ b/rpm/gdb.spec @@ -1,5 +1,3 @@ -%global __python %{__python3} - %global ctarch %{crosstarget}__%{_arch} Name: gdb @@ -9,35 +7,50 @@ Name: gdb %endif Summary: A GNU source-level debugger for C, C++, Java and other languages -Version: 12.1.0 +Version: 16.3.0 Release: 1 License: GPLv3+ -URL: http://gnu.org/software/gdb/ +URL: https://github.com/sailfishos/gdb Source0: %{name}-%{version}.tar.bz2 Source1: gdb-rpmlintrc -Source2: precheckin.sh - -# New locating of the matching binaries from the pure core file (build-id). -Patch1: gdb-6.6-buildid-locate.patch -# Fix loading of core files without build-ids but with build-ids in executables. -Patch2: gdb-6.6-buildid-locate-solib-missing-ids.patch -Patch3: gdb-6.6-buildid-locate-rpm.patch -# Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879). -Patch4: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch -Patch5: gdb-6.6-buildid-locate-rpm-suse.patch -Patch6: system-gdbinit-missing-parentheses.patch -BuildRequires: pkgconfig(ncurses) -BuildRequires: texinfo -BuildRequires: gettext -BuildRequires: flex +# Update gdb-add-index.sh such that, when the GDB environment +# variable is not set, the script is smarter than just looking for +# 'gdb' in the $PATH. +# +# The actual search order is now: /usr/bin/gdb.minimal, gdb (in the +# $PATH), then /usr/libexec/gdb. +# +# For the rationale of looking for gdb.minimal see: +# +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +# +#=fedora +Patch002: gdb-add-index.patch + +# Not a backport. Add a new script which hooks into GDB and suggests +# RPMs to install when GDB finds an objfile with no debug info. +Patch003: gdb-rpm-suggestion-script.patch + +# Backport "Fix another timeout in gdb.base/bg-execution-repeat.exp" +Patch004: gdb-fix-bg-execution-repeat.patch + +# Sailfish OS modifications to rpm suggestion script +Patch005: gdb-rpm-suggestion-script-sailfishos.patch + BuildRequires: bison -BuildRequires: expat-devel -BuildRequires: gmp-devel -BuildRequires: python3-devel +BuildRequires: flex +BuildRequires: gettext BuildRequires: libstdc++ -BuildRequires: zlib-devel +BuildRequires: texinfo +BuildRequires: pkgconfig(expat) +BuildRequires: pkgconfig(gmp) +BuildRequires: pkgconfig(mpfr) +BuildRequires: pkgconfig(ncurses) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(zlib) Requires: python3-base +Recommends: rpm-python %description GDB, the GNU debugger, allows you to debug programs written in C, C++, @@ -46,16 +59,10 @@ and printing their data. %prep -%setup -q -n %{name}-%{version}/upstream -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 +%autosetup -p1 -n %{name}-%{version}/upstream cat > gdb/version.in << _FOO -Mer (%{version}) +Sailfish OS (%{version}) _FOO # Remove the info and other generated files added by the FSF release @@ -93,7 +100,7 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-rpath \ --with-expat \ --enable-tui \ - --with-python=%{__python} \ + --with-python=%{__python3} \ --without-libunwind \ --enable-64-bit-bfd \ --enable-static \ @@ -108,8 +115,8 @@ export CFLAGS="$RPM_OPT_FLAGS" --disable-gprofng \ %{_target_platform} -make %{?_smp_mflags} -make %{?_smp_mflags} info +%make_build +%make_build info %install @@ -127,6 +134,7 @@ mkdir -p "%{buildroot}%{_docdir}/%{name}-%{version}" install -m 0644 -t "%{buildroot}%{_docdir}/%{name}-%{version}" README gdb/NEWS rm "%{buildroot}%{_infodir}"/bfd* rm -f "%{buildroot}%{_infodir}"/ctf-spec* +rm -f "%{buildroot}%{_infodir}"/sframe-spec* %else rm -r "%{buildroot}%{_infodir}/" rm -r "%{buildroot}%{_mandir}/" @@ -136,18 +144,6 @@ rm -r "%{buildroot}%{_mandir}/" %if "%{?crosstarget}" == "" #### NON-CROSS PACS -%files -%defattr(-,root,root,-) -%license COPYING COPYING.LIB -%{_bindir}/gcore -%{_bindir}/gdb -%{_bindir}/gdb-add-index -%{_datadir}/gdb -%if "%{_arch}" == "aarch64" -%{_libdir}/libinproctrace.so -%endif - - %package gdbserver Summary: A standalone server for GDB (the GNU source-level debugger) %ifarch %{ix86} x86_64 @@ -163,19 +159,6 @@ and printing their data. This package provides a program that allows you to run GDB on a different machine than the one which is running the program being debugged. -%ifarch %{ix86} x86_64 -%post gdbserver -p /sbin/ldconfig -%postun gdbserver -p /sbin/ldconfig -%endif - -%files gdbserver -%defattr(-,root,root,-) -%{_bindir}/gdbserver -%ifarch %{ix86} x86_64 -%{_libdir}/libinproctrace.so -%endif - - %package doc Summary: Documentation for %{name} Requires: %{name} = %{version}-%{release} @@ -185,6 +168,11 @@ Requires(postun): /sbin/install-info %description doc Man and info pages for %{name}. +%ifarch %{ix86} x86_64 +%post gdbserver -p /sbin/ldconfig +%postun gdbserver -p /sbin/ldconfig +%endif + %post doc %install_info --info-dir=%{_infodir} %{_infodir}/annotate.info.gz %install_info --info-dir=%{_infodir} %{_infodir}/gdb.info.gz @@ -200,12 +188,30 @@ then %install_info_delete --info-dir=%{_infodir} %{_infodir}/stabs.info.gz fi + +%files +%license COPYING3 COPYING3.LIB +%{_bindir}/gcore +%{_bindir}/gdb +%{_bindir}/gdb-add-index +%{_bindir}/gstack +%{_datadir}/gdb +%if "%{_arch}" == "aarch64" +%{_libdir}/libinproctrace.so +%endif + +%files gdbserver +%{_bindir}/gdbserver +%ifarch %{ix86} x86_64 +%{_libdir}/libinproctrace.so +%endif + %files doc -%defattr(-,root,root,-) %{_mandir}/*/gdb.1* %{_mandir}/*/gdbserver.1* %{_mandir}/man1/gcore.1.gz %{_mandir}/man1/gdb-add-index.1.gz +%{_mandir}/man1/gstack.1.gz %{_mandir}/man5/gdbinit.5.gz %{_infodir}/annotate.info.gz %{_infodir}/gdb.info.gz @@ -213,24 +219,27 @@ fi %{_docdir}/%{name}-%{version} -%else # crosstarget +%else +# crosstarget #### CROSS PACS %files -%defattr(-,root,root,-) /opt/cross/share/%{crosstarget}-gdb -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "armv7hl-meego-linux-gnueabi__arm" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/bin/gcore /opt/cross/bin/gdb /opt/cross/bin/gdb-add-index /opt/cross/bin/gdbserver +/opt/cross/bin/gstack %else /opt/cross/bin/%{crosstarget}-gdb /opt/cross/bin/%{crosstarget}-gdb-add-index +/opt/cross/bin/%{crosstarget}-gstack %endif -%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" +%if "%{ctarch}" == "aarch64-meego-linux-gnu__aarch64" || "%{ctarch}" == "i486-meego-linux-gnu__i386" || "%{ctarch}" == "x86_64-meego-linux-gnu__x86_64" /opt/cross/%{_lib}/libinproctrace.so %endif -%endif # crosstarget +# crosstarget +%endif diff --git a/rpm/system-gdbinit-missing-parentheses.patch b/rpm/system-gdbinit-missing-parentheses.patch deleted file mode 100644 index fdc7bcc..0000000 --- a/rpm/system-gdbinit-missing-parentheses.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/gdb/system-gdbinit/elinos.py b/gdb/system-gdbinit/elinos.py -index a7f098b013..1a51687773 100644 ---- a/gdb/system-gdbinit/elinos.py -+++ b/gdb/system-gdbinit/elinos.py -@@ -21,7 +21,7 @@ import gdb - - - def warn(msg): -- print "warning: %s" % msg -+ print("warning: %s" % msg) - - - def get_elinos_environment(): -diff --git a/gdb/system-gdbinit/wrs-linux.py b/gdb/system-gdbinit/wrs-linux.py -index 0a8174754b..22ba178716 100644 ---- a/gdb/system-gdbinit/wrs-linux.py -+++ b/gdb/system-gdbinit/wrs-linux.py -@@ -21,5 +21,5 @@ if 'ENV_PREFIX' in os.environ: - gdb.execute("set sysroot %s" % os.environ["ENV_PREFIX"]) - - else: -- print "warning: ENV_PREFIX environment variable missing." -- print "The debugger will probably be unable to find the correct system libraries" -+ print("warning: ENV_PREFIX environment variable missing.") -+ print("The debugger will probably be unable to find the correct system libraries") diff --git a/upstream b/upstream index e53a8e8..140ba01 160000 --- a/upstream +++ b/upstream @@ -1 +1 @@ -Subproject commit e53a8e8685685c97588f8319d993ea6cd5635e47 +Subproject commit 140ba011c003fda0fb2f746cf2bc0f010bf4ac03