From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id B7C883858D33 for ; Mon, 20 Nov 2023 18:39:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B7C883858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B7C883858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700505603; cv=none; b=x7dYR+kCAN7we1twJzvNpR69wWFT81sNs+nXpI7R1Oc+3CppIknohS57C7QwakTqT33OB8sj58rOxClwBrJueRT9Z4ygZMIIQZ7ubRGsZXbM49DtjTxYEnYbIz/EZyLWLti/I3713ndDVmmQ8ZUEiEGuMORk0cyoMNPJayGqpZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700505603; c=relaxed/simple; bh=Muu2FxUvYQ27uh6raPf90DhzTr+HgNUq9QgP6NWJnDA=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=PvY3UeEIq3elE95a8XNCUJldSY7Q3nNd9IaEbl0/gBX/Im0vNhHlBBMC6Qwoz+QUC6f3OC+Rj2aIAW9plODzT70EHJ8Dewurdnyk31pfyZAsQCwf6Sd/5AcF2PrWPWopQ2w6lMUaIKR369qPriaEvF5KwLl/aL7Xd0+dP1vLXEE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700505598; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bVdfhutbxY//I7Q+SA2OSPAP95O4XUxxZLS/ebtB50Y=; b=gjCGA05nFAl99m1thpoV6BX/f80ArUjA8wbKJ2urYOEuEilMZTMioBdoOG65LoMimGwn3V /wi/7ku4qvqFD4d132QyDyvp0mQGmlnm0u8YL0YOfwZZurnUDtkjR/ue2kO0KpePp9qju9 VRt+nxcqXwuUoVWyJmiyY1JA6ELv260= Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-10-T5IztU_NN_eW6QIVPv7sLg-1; Mon, 20 Nov 2023 13:39:56 -0500 X-MC-Unique: T5IztU_NN_eW6QIVPv7sLg-1 Received: by mail-pg1-f198.google.com with SMTP id 41be03b00d2f7-5c19a2f606dso5107301a12.3 for ; Mon, 20 Nov 2023 10:39:56 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700505595; x=1701110395; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bVdfhutbxY//I7Q+SA2OSPAP95O4XUxxZLS/ebtB50Y=; b=Vq3l3d8EhDy1G2zJMWu8wUAPVScGHaqB4IzBBlRDdiP/+UekclTZZMfh0HF82RVD3g hiC3rUdyYzWimVer34TW5gTo1y+HDrP57l2kCsDvt7/4mubCBjpH70BRCplLLBDjIJDp NB6Ww4eZvCySgnC4w/CRkUZiFRJ0QqCTq60vPzVM0S+De3Q11fBEUkqWCx4uq/lj5KFE 42A3EIUwnGl5hB2seVVMKph3m7mKFwOcIxl0zIGegNgSWi6DveY9IauhX/OXJWfs9Tcx g6V72k4i71InVThzbCaI11cen8Qwq4+zE7KpO8ZtxS7ZphM+ftgwWpmQcp1i9+yje0Fe 2jCw== X-Gm-Message-State: AOJu0Yx9w5UVhfLi3/XW+QBbQKwqN5/yZfG6wBhC896S5+19PBhijRaK 15yhyC/Xo3bbSyDglkZ2xMksMAF6APDaXFS4mpZJNKK21MYvjuxCdVWfO2eoCNpAu3MUo2wFlkt lGXVLm+OW+IytLBOfv2xt1uXvEhImbQdKyJKdxfhDJIjD X-Received: by 2002:a17:90b:3b90:b0:27f:f655:e14c with SMTP id pc16-20020a17090b3b9000b0027ff655e14cmr6159942pjb.42.1700505595260; Mon, 20 Nov 2023 10:39:55 -0800 (PST) X-Google-Smtp-Source: AGHT+IE4bZoso/GoRyeLH8Kq5G++M2zyU3UZ3k9lGJR9xwY0A0nbD+M0sdQiQ5qlQcKkjvrnjUxpB+wzzDD6eRKd69A= X-Received: by 2002:a17:90b:3b90:b0:27f:f655:e14c with SMTP id pc16-20020a17090b3b9000b0027ff655e14cmr6159906pjb.42.1700505594479; Mon, 20 Nov 2023 10:39:54 -0800 (PST) MIME-Version: 1.0 References: <20231028002008.1105723-1-amerey@redhat.com> <20231028002008.1105723-4-amerey@redhat.com> In-Reply-To: From: Aaron Merey Date: Mon, 20 Nov 2023 13:39:43 -0500 Message-ID: Subject: [PING*2][PATCH 3/4 v4] gdb/debuginfod: Support on-demand debuginfo downloading To: gdb-patches@sourceware.org Cc: Andrew Burgess X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Ping Thanks, Aaron On Sun, Nov 12, 2023 at 3:20=E2=80=AFPM Aaron Merey wro= te: > > Ping > > Thanks, > Aaron > > On Fri, Oct 27, 2023 at 8:20=E2=80=AFPM Aaron Merey w= rote: > > > > v3: https://sourceware.org/pipermail/gdb-patches/2023-June/199987.html > > > > v4 improves testcases when running with --target_board=3Dnative-gdbserv= er. > > > > v4 also fixes a bug where objfile observers could clear selected_frame > > if debuginfo was downloaded during get_selected_frame. > > > > Commit message: > > > > At the beginning of a session, gdb may attempt to download debuginfo > > for all shared libraries associated with the process or core file > > being debugged. This can be a waste of time and storage space when muc= h > > of the debuginfo ends up not being used during the session. > > > > To reduce the gdb's startup latency and to download only the debuginfo > > that is really needed, this patch adds on-demand downloading of debugin= fo. > > > > 'set debuginfo enabled on' now causes gdb to attempt to download a .gdb= _index > > for each shared library instead of its full debuginfo. Each correspond= ing > > separate debuginfo will be deferred until gdb needs to expand symtabs > > associated with the debuginfo's index. > > > > Because these indices are significantly smaller than their correspondin= g > > debuginfo, this generally reduces the total amount of data gdb download= s. > > Reductions of 80%-95% have been observed when debugging large GUI progr= ams. > > > > (gdb) set debuginfod enabled on > > (gdb) start > > Downloading section .gdb_index for /lib64/libcurl.so.4 > > [...] > > 1826 client->server_mhandle =3D curl_multi_init (); > > (gdb) step > > Downloading separate debug info for /lib64/libcurl.so.4 > > Downloading separate debug info for [libcurl dwz] > > Downloading source file /usr/src/debug/curl-7.85.0-6.fc37.x86_64/bu= ild-full/lib/../../lib/multi.c > > curl_multi_init () at ../../lib/multi.c:457 > > 457 { > > (gdb) > > > > Some of the key functions below include dwarf2_has_separate_index which > > downloads the separate .gdb_index. If successful, the shared library > > objfile owns the index until the separate debug objfile is downloaded > > or confirmed to not be available. > > > > read_full_dwarf_from_debuginfod downloads the full debuginfo and > > initializes the separate debug objfile. It is called by functions > > such as dwarf2_gdb_index::expand_symtabs_matching and > > dwarf2_base_index_functions::find_pc_sect_compunit_symtab when symtab > > expansion is required. > > --- > > gdb/dwarf2/frame.c | 13 ++ > > gdb/dwarf2/frame.h | 4 + > > gdb/dwarf2/index-cache.c | 33 ++++ > > gdb/dwarf2/index-cache.h | 13 ++ > > gdb/dwarf2/public.h | 7 + > > gdb/dwarf2/read-gdb-index.c | 156 +++++++++++++++-- > > gdb/dwarf2/read.c | 146 +++++++++++++++- > > gdb/dwarf2/read.h | 10 ++ > > gdb/dwarf2/section.c | 3 +- > > gdb/elfread.c | 2 +- > > gdb/frame.c | 7 + > > gdb/objfile-flags.h | 4 + > > gdb/objfiles.h | 20 +++ > > gdb/quick-symbol.h | 4 + > > gdb/symfile.c | 13 +- > > gdb/symtab.c | 18 +- > > gdb/testsuite/gdb.debuginfod/libsection1.c | 40 +++++ > > gdb/testsuite/gdb.debuginfod/libsection2.c | 37 +++++ > > gdb/testsuite/gdb.debuginfod/section.c | 29 ++++ > > gdb/testsuite/gdb.debuginfod/section.exp | 184 +++++++++++++++++++++ > > gdb/testsuite/lib/debuginfod-support.exp | 27 ++- > > 21 files changed, 746 insertions(+), 24 deletions(-) > > create mode 100644 gdb/testsuite/gdb.debuginfod/libsection1.c > > create mode 100644 gdb/testsuite/gdb.debuginfod/libsection2.c > > create mode 100644 gdb/testsuite/gdb.debuginfod/section.c > > create mode 100644 gdb/testsuite/gdb.debuginfod/section.exp > > > > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > > index abc8d613482..257f0316731 100644 > > --- a/gdb/dwarf2/frame.c > > +++ b/gdb/dwarf2/frame.c > > @@ -1617,6 +1617,19 @@ set_comp_unit (struct objfile *objfile, struct c= omp_unit *unit) > > return dwarf2_frame_bfd_data.set (abfd, unit); > > } > > > > +/* See frame.h. */ > > + > > +void > > +dwarf2_clear_frame_data (struct objfile *objfile) > > +{ > > + bfd *abfd =3D objfile->obfd.get (); > > + > > + if (gdb_bfd_requires_relocations (abfd)) > > + dwarf2_frame_objfile_data.clear (objfile); > > + else > > + dwarf2_frame_bfd_data.clear (abfd); > > +} > > + > > /* Find the FDE for *PC. Return a pointer to the FDE, and store the > > initial location associated with it into *PC. */ > > > > diff --git a/gdb/dwarf2/frame.h b/gdb/dwarf2/frame.h > > index 5643e557513..2391e313e7c 100644 > > --- a/gdb/dwarf2/frame.h > > +++ b/gdb/dwarf2/frame.h > > @@ -238,6 +238,10 @@ void dwarf2_append_unwinders (struct gdbarch *gdba= rch); > > extern const struct frame_base * > > dwarf2_frame_base_sniffer (frame_info_ptr this_frame); > > > > +/* Delete OBJFILEs comp_unit. */ > > + > > +extern void dwarf2_clear_frame_data (struct objfile * objfile); > > + > > /* Compute the DWARF CFA for a frame. */ > > > > CORE_ADDR dwarf2_frame_cfa (frame_info_ptr this_frame); > > diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c > > index 69f70642dc6..8c969ecd590 100644 > > --- a/gdb/dwarf2/index-cache.c > > +++ b/gdb/dwarf2/index-cache.c > > @@ -240,6 +240,33 @@ index_cache::lookup_gdb_index (const bfd_build_id = *build_id, > > return {}; > > } > > > > +/* See index-cache.h. */ > > + > > +gdb::array_view > > +index_cache::lookup_gdb_index_debuginfod (const char *index_path, > > + std::unique_ptr *resource) > > +{ > > + try > > + { > > + /* Try to map that file. */ > > + index_cache_resource_mmap *mmap_resource > > + =3D new index_cache_resource_mmap (index_path); > > + > > + /* Hand the resource to the caller. */ > > + resource->reset (mmap_resource); > > + > > + return gdb::array_view > > + ((const gdb_byte *) mmap_resource->mapping.get (), > > + mmap_resource->mapping.size ()); > > + } > > + catch (const gdb_exception_error &except) > > + { > > + warning (_("Unable to read %s: %s"), index_path, except.what ())= ; > > + } > > + > > + return {}; > > +} > > + > > #else /* !HAVE_SYS_MMAN_H */ > > > > /* See dwarf-index-cache.h. This is a no-op on unsupported systems. = */ > > @@ -251,6 +278,12 @@ index_cache::lookup_gdb_index (const bfd_build_id = *build_id, > > return {}; > > } > > > > +gdb::array_view > > +index_cache::lookup_gdb_index_debuginfod (const char *index_path, > > + std::unique_ptr *resource) > > +{ > > + return {}; > > +} > > #endif > > > > /* See dwarf-index-cache.h. */ > > diff --git a/gdb/dwarf2/index-cache.h b/gdb/dwarf2/index-cache.h > > index cfa45435fbd..9d18717fe56 100644 > > --- a/gdb/dwarf2/index-cache.h > > +++ b/gdb/dwarf2/index-cache.h > > @@ -90,6 +90,19 @@ class index_cache > > lookup_gdb_index (const bfd_build_id *build_id, > > std::unique_ptr *resource); > > > > + /* Look for an index file located at INDEX_PATH in the debuginfod ca= che. > > + Unlike lookup_gdb_index, this function does not exit early if the > > + index cache has not been enabled. > > + > > + If found, return the contents as an array_view and store the unde= rlying > > + resources (allocated memory, mapped file, etc) in RESOURCE. The = returned > > + array_view is valid as long as RESOURCE is not destroyed. > > + > > + If no matching index file is found, return an empty array view. = */ > > + gdb::array_view > > + lookup_gdb_index_debuginfod (const char *index_path, > > + std::unique_ptr *r= esource); > > + > > /* Return the number of cache hits. */ > > unsigned int n_hits () const > > { return m_n_hits; } > > diff --git a/gdb/dwarf2/public.h b/gdb/dwarf2/public.h > > index 0e74857eb1a..4a44cdbc223 100644 > > --- a/gdb/dwarf2/public.h > > +++ b/gdb/dwarf2/public.h > > @@ -40,4 +40,11 @@ extern void dwarf2_initialize_objfile (struct objfil= e *objfile); > > > > extern void dwarf2_build_frame_info (struct objfile *); > > > > +/* Query debuginfod for the .gdb_index associated with OBJFILE. If > > + successful, create an objfile to hold the .gdb_index information > > + and act as a placeholder until the full debuginfo needs to be > > + downloaded. */ > > + > > +extern bool dwarf2_has_separate_index (struct objfile *); > > + > > #endif /* DWARF2_PUBLIC_H */ > > diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c > > index e789e9c2654..da88a8b405c 100644 > > --- a/gdb/dwarf2/read-gdb-index.c > > +++ b/gdb/dwarf2/read-gdb-index.c > > @@ -139,6 +139,7 @@ struct dwarf2_gdb_index : public dwarf2_base_index_= functions > > gdb.dwarf2/gdb-index.exp testcase. */ > > void dump (struct objfile *objfile) override; > > > > + /* Calls do_expand_matching_symbols and downloads debuginfo if neces= sary. */ > > void expand_matching_symbols > > (struct objfile *, > > const lookup_name_info &lookup_name, > > @@ -146,6 +147,14 @@ struct dwarf2_gdb_index : public dwarf2_base_index= _functions > > int global, > > symbol_compare_ftype *ordered_compare) override; > > > > + void do_expand_matching_symbols > > + (struct objfile *, > > + const lookup_name_info &lookup_name, > > + domain_enum domain, > > + int global, > > + symbol_compare_ftype *ordered_compare); > > + > > + /* Calls do_expand_symtabs_matching and downloads debuginfo if neces= sary. */ > > bool expand_symtabs_matching > > (struct objfile *objfile, > > gdb::function_view file_matche= r, > > @@ -155,8 +164,59 @@ struct dwarf2_gdb_index : public dwarf2_base_index= _functions > > block_search_flags search_flags, > > domain_enum domain, > > enum search_domain kind) override; > > + > > + bool do_expand_symtabs_matching > > + (struct objfile *objfile, > > + gdb::function_view file_matche= r, > > + const lookup_name_info *lookup_name, > > + gdb::function_view symbol_ma= tcher, > > + gdb::function_view expansion_not= ify, > > + block_search_flags search_flags, > > + domain_enum domain, > > + enum search_domain kind); > > + > > + /* Calls dwarf2_base_index_functions::expand_all_symtabs and downloa= ds > > + debuginfo if necessary. */ > > + void expand_all_symtabs (struct objfile *objfile) override; > > + > > + /* Calls dwarf2_base_index_functions::find_last_source_symtab and do= wnloads > > + debuginfo if necessary. */ > > + struct symtab *find_last_source_symtab (struct objfile *objfile) ove= rride; > > }; > > > > +void > > +dwarf2_gdb_index::expand_all_symtabs (struct objfile *objfile) > > +{ > > + try > > + { > > + dwarf2_base_index_functions::expand_all_symtabs (objfile); > > + } > > + catch (const gdb_exception &e) > > + { > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + exception_print (gdb_stderr, e); > > + else > > + read_full_dwarf_from_debuginfod (objfile, this); > > + } > > +} > > + > > +struct symtab * > > +dwarf2_gdb_index::find_last_source_symtab (struct objfile *objfile) > > +{ > > + try > > + { > > + return dwarf2_base_index_functions::find_last_source_symtab (obj= file); > > + } > > + catch (const gdb_exception &e) > > + { > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + exception_print (gdb_stderr, e); > > + else > > + read_full_dwarf_from_debuginfod (objfile, this); > > + return nullptr; > > + } > > +} > > + > > /* This dumps minimal information about the index. > > It is called via "mt print objfiles". > > One use is to verify .gdb_index has been loaded by the > > @@ -318,7 +378,7 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *i= ter, > > } > > > > void > > -dwarf2_gdb_index::expand_matching_symbols > > +dwarf2_gdb_index::do_expand_matching_symbols > > (struct objfile *objfile, > > const lookup_name_info &name, domain_enum domain, > > int global, > > @@ -356,6 +416,29 @@ dwarf2_gdb_index::expand_matching_symbols > > }, per_objfile); > > } > > > > +void > > +dwarf2_gdb_index::expand_matching_symbols > > + (struct objfile *objfile, > > + const lookup_name_info &lookup_name, > > + domain_enum domain, > > + int global, > > + symbol_compare_ftype *ordered_compare) > > +{ > > + try > > + { > > + do_expand_matching_symbols (objfile, lookup_name, domain, > > + global, ordered_compare); > > + } > > + catch (const gdb_exception &e) > > + { > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + exception_print (gdb_stderr, e); > > + else > > + read_full_dwarf_from_debuginfod (objfile, this); > > + return; > > + } > > +} > > + > > /* Helper for dw2_expand_matching symtabs. Called on each symbol > > matched, to expand corresponding CUs that were marked. IDX is the > > index of the symbol name that matched. */ > > @@ -458,7 +541,7 @@ dw2_expand_marked_cus > > } > > > > bool > > -dwarf2_gdb_index::expand_symtabs_matching > > +dwarf2_gdb_index::do_expand_symtabs_matching > > (struct objfile *objfile, > > gdb::function_view file_matche= r, > > const lookup_name_info *lookup_name, > > @@ -507,6 +590,39 @@ dwarf2_gdb_index::expand_symtabs_matching > > return result; > > } > > > > +bool > > +dwarf2_gdb_index::expand_symtabs_matching > > + (struct objfile *objfile, > > + gdb::function_view file_matche= r, > > + const lookup_name_info *lookup_name, > > + gdb::function_view symbol_ma= tcher, > > + gdb::function_view expansion_not= ify, > > + block_search_flags search_flags, > > + domain_enum domain, > > + enum search_domain kind) > > +{ > > + if (objfile->flags & OBJF_READNEVER) > > + return false; > > + > > + try > > + { > > + return do_expand_symtabs_matching (objfile, file_matcher, lookup= _name, > > + symbol_matcher, expansion_noti= fy, > > + search_flags, domain, kind); > > + } > > + catch (const gdb_exception &e) > > + { > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + { > > + exception_print (gdb_stderr, e); > > + return false; > > + } > > + > > + read_full_dwarf_from_debuginfod (objfile, this); > > + return true; > > + } > > +} > > + > > quick_symbol_functions_up > > mapped_gdb_index::make_quick_functions () const > > { > > @@ -842,28 +958,32 @@ dwarf2_read_gdb_index > > > > /* If there is a .dwz file, read it so we can get its CU list as > > well. */ > > - dwz =3D dwarf2_get_dwz_file (per_bfd); > > - if (dwz !=3D NULL) > > + if (get_gdb_index_contents_dwz !=3D nullptr) > > { > > mapped_gdb_index dwz_map; > > const gdb_byte *dwz_types_ignore; > > offset_type dwz_types_elements_ignore; > > + dwz =3D dwarf2_get_dwz_file (per_bfd); > > > > - gdb::array_view dwz_index_content > > - =3D get_gdb_index_contents_dwz (objfile, dwz); > > - > > - if (dwz_index_content.empty ()) > > - return 0; > > - > > - if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.= get ()), > > - 1, dwz_index_content, &dwz_map, > > - &dwz_list, &dwz_list_elements, > > - &dwz_types_ignore, > > - &dwz_types_elements_ignore)) > > + if (dwz !=3D nullptr) > > { > > - warning (_("could not read '.gdb_index' section from %s; skip= ping"), > > - bfd_get_filename (dwz->dwz_bfd.get ())); > > - return 0; > > + gdb::array_view dwz_index_content > > + =3D get_gdb_index_contents_dwz (objfile, dwz); > > + > > + if (dwz_index_content.empty ()) > > + return 0; > > + > > + if (!read_gdb_index_from_buffer (bfd_get_filename > > + (dwz->dwz_bfd.get ()), > > + 1, dwz_index_content, &dwz_m= ap, > > + &dwz_list, &dwz_list_element= s, > > + &dwz_types_ignore, > > + &dwz_types_elements_ignore)) > > + { > > + warning (_("could not read '.gdb_index' section from %s; = skipping"), > > + bfd_get_filename (dwz->dwz_bfd.get ())); > > + return 0; > > + } > > } > > } > > > > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c > > index ea0b2328a3e..0c5689c63ef 100644 > > --- a/gdb/dwarf2/read.c > > +++ b/gdb/dwarf2/read.c > > @@ -34,6 +34,7 @@ > > #include "dwarf2/attribute.h" > > #include "dwarf2/comp-unit-head.h" > > #include "dwarf2/cu.h" > > +#include "dwarf2/frame.h" > > #include "dwarf2/index-cache.h" > > #include "dwarf2/index-common.h" > > #include "dwarf2/leb.h" > > @@ -95,6 +96,8 @@ > > #include "split-name.h" > > #include "gdbsupport/parallel-for.h" > > #include "gdbsupport/thread-pool.h" > > +#include "inferior.h" > > +#include "debuginfod-support.h" > > > > /* When =3D=3D 1, print basic high level tracing messages. > > When > 1, be more verbose. > > @@ -3188,7 +3191,7 @@ dwarf2_base_index_functions::find_per_cu (dwarf2_= per_bfd *per_bfd, > > } > > > > struct compunit_symtab * > > -dwarf2_base_index_functions::find_pc_sect_compunit_symtab > > +dwarf2_base_index_functions::do_find_pc_sect_compunit_symtab > > (struct objfile *objfile, > > struct bound_minimal_symbol msymbol, > > CORE_ADDR pc, > > @@ -3219,6 +3222,32 @@ dwarf2_base_index_functions::find_pc_sect_compun= it_symtab > > return result; > > } > > > > +struct compunit_symtab * > > +dwarf2_base_index_functions::find_pc_sect_compunit_symtab > > + (struct objfile *objfile, > > + struct bound_minimal_symbol msymbol, > > + CORE_ADDR pc, > > + struct obj_section *section, > > + int warn_if_readin) > > +{ > > + if (objfile->flags & OBJF_READNEVER) > > + return nullptr; > > + > > + try > > + { > > + return do_find_pc_sect_compunit_symtab (objfile, msymbol, pc, > > + section, warn_if_readin); > > + } > > + catch (const gdb_exception &e) > > + { > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + exception_print (gdb_stderr, e); > > + else > > + read_full_dwarf_from_debuginfod (objfile, this); > > + return nullptr; > > + } > > +} > > + > > void > > dwarf2_base_index_functions::map_symbol_filenames > > (struct objfile *objfile, > > @@ -3375,6 +3404,29 @@ get_gdb_index_contents_from_cache_dwz (objfile *= obj, dwz_file *dwz) > > return global_index_cache.lookup_gdb_index (build_id, &dwz->index_ca= che_res); > > } > > > > +/* Query debuginfod for the .gdb_index matching OBJFILE's build-id. R= eturn the > > + contents if successful. */ > > + > > +static gdb::array_view > > +get_gdb_index_contents_from_debuginfod (objfile *objfile, dwarf2_per_b= fd *per_bfd) > > +{ > > + const bfd_build_id *build_id =3D build_id_bfd_get (objfile->obfd.get= ()); > > + if (build_id =3D=3D nullptr) > > + return {}; > > + > > + gdb::unique_xmalloc_ptr index_path; > > + scoped_fd fd =3D debuginfod_section_query (build_id->data, build_id-= >size, > > + bfd_get_filename > > + (objfile->obfd.get ()), > > + ".gdb_index", > > + &index_path); > > + if (fd.get () < 0) > > + return {}; > > + > > + return global_index_cache.lookup_gdb_index_debuginfod > > + (index_path.get (), &per_bfd->index_cache_res); > > +} > > + > > static quick_symbol_functions_up make_cooked_index_funcs (); > > > > /* See dwarf2/public.h. */ > > @@ -3440,10 +3492,102 @@ dwarf2_initialize_objfile (struct objfile *obj= file) > > return; > > } > > > > + if ((objfile->flags & OBJF_DOWNLOAD_DEFERRED) > > + && dwarf2_read_gdb_index (per_objfile, > > + get_gdb_index_contents_from_debuginfod, > > + nullptr)) > > + { > > + dwarf_read_debug_printf ("found .gdb_index from debuginfod"); > > + objfile->qf.push_front (per_bfd->index_table->make_quick_functio= ns ()); > > + objfile->qf.begin ()->get ()->from_separate_index =3D true; > > + return; > > + } > > + > > global_index_cache.miss (); > > objfile->qf.push_front (make_cooked_index_funcs ()); > > } > > > > +/* See read.h. */ > > + > > +void > > +read_full_dwarf_from_debuginfod (struct objfile *objfile, > > + dwarf2_base_index_functions *fncs) > > +{ > > + gdb_assert (objfile->flags & OBJF_DOWNLOAD_DEFERRED); > > + > > + const struct bfd_build_id *build_id =3D build_id_bfd_get (objfile->o= bfd.get ()); > > + const char *filename; > > + gdb_bfd_ref_ptr debug_bfd; > > + gdb::unique_xmalloc_ptr symfile_path; > > + scoped_fd fd; > > + > > + if (build_id =3D=3D nullptr) > > + goto unset; > > + > > + filename =3D bfd_get_filename (objfile->obfd.get ()); > > + fd =3D debuginfod_debuginfo_query (build_id->data, build_id->size, > > + filename, &symfile_path); > > + if (fd.get () < 0) > > + goto unset; > > + > > + /* Separate debuginfo successfully retrieved from server. */ > > + debug_bfd =3D symfile_bfd_open (symfile_path.get ()); > > + if (debug_bfd =3D=3D nullptr > > + || !build_id_verify (debug_bfd.get (), build_id->size, build_id-= >data)) > > + { > > + warning (_("File \"%s\" from debuginfod cannot be opened as bfd"= ), > > + filename); > > + goto unset; > > + } > > + > > + /* Clear frame data so it can be recalculated using DWARF. */ > > + dwarf2_clear_frame_data (objfile); > > + > > + /* This may also trigger a dwz download. */ > > + symbol_file_add_separate (debug_bfd, symfile_path.get (), > > + current_inferior ()->symfile_flags, objfil= e); > > + > > +unset: > > + objfile->remove_deferred_status (); > > +} > > + > > +/* See public.h. */ > > + > > +bool > > +dwarf2_has_separate_index (struct objfile *objfile) > > +{ > > + if (objfile->flags & OBJF_DOWNLOAD_DEFERRED) > > + return true; > > + if (objfile->flags & OBJF_MAINLINE) > > + return false; > > + if (!IS_DIR_SEPARATOR (*objfile_filename (objfile))) > > + return false; > > + > > + gdb::unique_xmalloc_ptr index_path; > > + const bfd_build_id *build_id =3D build_id_bfd_get (objfile->obfd.get= ()); > > + > > + if (build_id =3D=3D nullptr) > > + return false; > > + > > + scoped_fd fd =3D debuginfod_section_query (build_id->data, > > + build_id->size, > > + bfd_get_filename > > + (objfile->obfd.get ()), > > + ".gdb_index", > > + &index_path); > > + > > + if (fd.get () < 0) > > + return false; > > + > > + /* We found a separate .gdb_index file so a separate debuginfo file > > + should exist, but we don't want to download it until necessary. > > + Attach the index to this objfile and defer the debuginfo download > > + until gdb needs to expand symtabs referenced by the index. */ > > + objfile->flags |=3D OBJF_DOWNLOAD_DEFERRED; > > + dwarf2_initialize_objfile (objfile); > > + return true; > > +} > > + > > > > > > /* Build a partial symbol table. */ > > diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h > > index dc7abf23ba4..6ed0be7203b 100644 > > --- a/gdb/dwarf2/read.h > > +++ b/gdb/dwarf2/read.h > > @@ -883,6 +883,10 @@ struct dwarf2_base_index_functions : public quick_= symbol_functions > > CORE_ADDR pc, struct obj_section *section, int warn_if_readin) > > override final; > > > > + struct compunit_symtab *do_find_pc_sect_compunit_symtab > > + (struct objfile *objfile, struct bound_minimal_symbol msymbol, > > + CORE_ADDR pc, struct obj_section *section, int warn_if_readin); > > + > > struct compunit_symtab *find_compunit_symtab_by_address > > (struct objfile *objfile, CORE_ADDR address) override > > { > > @@ -959,4 +963,10 @@ extern bool read_addrmap_from_aranges (dwarf2_per_= objfile *per_objfile, > > dwarf2_section_info *section, > > addrmap *mutable_map); > > > > +/* If OBJFILE contains information from a separately downloaded .gdb_i= ndex, > > + attempt to download the full debuginfo. */ > > + > > +extern void read_full_dwarf_from_debuginfod (struct objfile *, > > + dwarf2_base_index_function= s *); > > + > > #endif /* DWARF2READ_H */ > > diff --git a/gdb/dwarf2/section.c b/gdb/dwarf2/section.c > > index 1235f293f45..b674103c72f 100644 > > --- a/gdb/dwarf2/section.c > > +++ b/gdb/dwarf2/section.c > > @@ -54,7 +54,8 @@ dwarf2_section_info::get_bfd_owner () const > > section =3D get_containing_section (); > > gdb_assert (!section->is_virtual); > > } > > - gdb_assert (section->s.section !=3D nullptr); > > + if (section->s.section =3D=3D nullptr) > > + error (_("Can't find owner of DWARF section.")); > > return section->s.section->owner; > > } > > > > diff --git a/gdb/elfread.c b/gdb/elfread.c > > index 7900dfbc388..5c89598eee7 100644 > > --- a/gdb/elfread.c > > +++ b/gdb/elfread.c > > @@ -1235,7 +1235,7 @@ elf_symfile_read_dwarf2 (struct objfile *objfile, > > symbol_file_add_separate (debug_bfd, debugfile.c_str (), > > symfile_flags, objfile); > > } > > - else > > + else if (!dwarf2_has_separate_index (objfile)) > > { > > has_dwarf2 =3D false; > > const struct bfd_build_id *build_id > > diff --git a/gdb/frame.c b/gdb/frame.c > > index 7077016ccba..00dbffed1ef 100644 > > --- a/gdb/frame.c > > +++ b/gdb/frame.c > > @@ -1892,6 +1892,13 @@ get_selected_frame (const char *message) > > error (("%s"), message); > > > > lookup_selected_frame (selected_frame_id, selected_frame_level); > > + > > + /* It is possible for lookup_selected_frame to cause a new objfi= le > > + to be loaded. Some objfile observers may choose to clear > > + selected_frame when an objfile is loaded. Work around this by > > + calling lookup_selected_frame again if the first try failed. = */ > > + if (selected_frame =3D=3D nullptr) > > + lookup_selected_frame (selected_frame_id, selected_frame_level)= ; > > } > > /* There is always a frame. */ > > gdb_assert (selected_frame !=3D NULL); > > diff --git a/gdb/objfile-flags.h b/gdb/objfile-flags.h > > index 9dee2ee51a0..fb3f741c899 100644 > > --- a/gdb/objfile-flags.h > > +++ b/gdb/objfile-flags.h > > @@ -60,6 +60,10 @@ enum objfile_flag : unsigned > > /* User requested that we do not read this objfile's symbolic > > information. */ > > OBJF_READNEVER =3D 1 << 6, > > + > > + /* A separate .gdb_index has been downloaded for this objfile. > > + Debuginfo for this objfile can be downloaded when required. */ > > + OBJF_DOWNLOAD_DEFERRED =3D 1 << 7, > > }; > > > > DEF_ENUM_FLAGS_TYPE (enum objfile_flag, objfile_flags); > > diff --git a/gdb/objfiles.h b/gdb/objfiles.h > > index c20b63ceadf..ea9bd2157dc 100644 > > --- a/gdb/objfiles.h > > +++ b/gdb/objfiles.h > > @@ -612,6 +612,26 @@ struct objfile > > /* See quick_symbol_functions. */ > > void require_partial_symbols (bool verbose); > > > > + /* Indicate that the aquisition of this objfile's separate debug obj= file > > + is no longer deferred. Used when the debug objfile has been aqui= red > > + or could not be found. */ > > + void remove_deferred_status () > > + { > > + flags &=3D ~OBJF_DOWNLOAD_DEFERRED; > > + > > + /* Remove quick_symbol_functions derived from a separately downloa= ded > > + index. If available the separate debug objfile's index will be= used > > + instead, since that objfile actually contains the symbols and C= Us > > + referenced in the index. > > + > > + No more than one element of qf should have from_separate_index = set > > + to true. */ > > + qf.remove_if ([&] (const quick_symbol_functions_up &qf_up) > > + { > > + return qf_up->from_separate_index; > > + }); > > + } > > + > > /* Return the relocation offset applied to SECTION. */ > > CORE_ADDR section_offset (bfd_section *section) const > > { > > diff --git a/gdb/quick-symbol.h b/gdb/quick-symbol.h > > index a7fea2ccb49..e7163503e39 100644 > > --- a/gdb/quick-symbol.h > > +++ b/gdb/quick-symbol.h > > @@ -225,6 +225,10 @@ struct quick_symbol_functions > > virtual void read_partial_symbols (struct objfile *objfile) > > { > > } > > + > > + /* True if this quick_symbol_functions is derived from a separately > > + downloaded index. */ > > + bool from_separate_index =3D false; > > }; > > > > typedef std::unique_ptr quick_symbol_functions= _up; > > diff --git a/gdb/symfile.c b/gdb/symfile.c > > index eebc5ea44b9..0491a33e8f5 100644 > > --- a/gdb/symfile.c > > +++ b/gdb/symfile.c > > @@ -991,6 +991,10 @@ syms_from_objfile (struct objfile *objfile, > > static void > > finish_new_objfile (struct objfile *objfile, symfile_add_flags add_fla= gs) > > { > > + struct objfile *parent =3D objfile->separate_debug_objfile_backlink; > > + bool was_deferred > > + =3D (parent !=3D nullptr) && (parent->flags & OBJF_DOWNLOAD_DEFERR= ED); > > + > > /* If this is the main symbol file we have to clean up all users of = the > > old main symbol file. Otherwise it is sufficient to fixup all th= e > > breakpoints that may have been redefined by this symbol file. */ > > @@ -1001,7 +1005,8 @@ finish_new_objfile (struct objfile *objfile, symf= ile_add_flags add_flags) > > > > clear_symtab_users (add_flags); > > } > > - else if ((add_flags & SYMFILE_DEFER_BP_RESET) =3D=3D 0) > > + else if ((add_flags & SYMFILE_DEFER_BP_RESET) =3D=3D 0 > > + && !was_deferred) > > { > > breakpoint_re_set (); > > } > > @@ -1122,6 +1127,12 @@ symbol_file_add_with_addrs (const gdb_bfd_ref_pt= r &abfd, const char *name, > > if (objfile->sf !=3D nullptr) > > finish_new_objfile (objfile, add_flags); > > > > + /* Remove deferred status now in case any observers trigger symtab > > + expansion. Otherwise gdb might try to read parent for psymbols > > + when it should read the separate debug objfile instead. */ > > + if (parent !=3D nullptr && (parent->flags & OBJF_DOWNLOAD_DEFERRED)) > > + parent->remove_deferred_status (); > > + > > gdb::observers::new_objfile.notify (objfile); > > > > bfd_cache_close_all (); > > diff --git a/gdb/symtab.c b/gdb/symtab.c > > index 5ec56f4f2af..bd01a75189d 100644 > > --- a/gdb/symtab.c > > +++ b/gdb/symtab.c > > @@ -2925,14 +2925,30 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, str= uct obj_section *section) > > if (best_cust !=3D NULL) > > return best_cust; > > > > + int warn_if_readin =3D 1; > > + > > /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs).= */ > > > > for (objfile *objf : current_program_space->objfiles ()) > > { > > + bool was_deferred =3D objf->flags & OBJF_DOWNLOAD_DEFERRED; > > + > > struct compunit_symtab *result > > - =3D objf->find_pc_sect_compunit_symtab (msymbol, pc, section, 1= ); > > + =3D objf->find_pc_sect_compunit_symtab (msymbol, pc, section, > > + warn_if_readin); > > + > > if (result !=3D NULL) > > return result; > > + > > + /* If objf's separate debug info was just acquired, disable > > + warn_if_readin for the next iteration of this loop. This prev= ents > > + a spurious warning in case an observer already triggered expan= sion > > + of the separate debug objfile's symtabs. */ > > + if (was_deferred && objf->separate_debug_objfile !=3D nullptr > > + && (objf->flags & OBJF_DOWNLOAD_DEFERRED) =3D=3D 0) > > + warn_if_readin =3D 0; > > + else if (warn_if_readin =3D=3D 0) > > + warn_if_readin =3D 1; > > } > > > > return NULL; > > diff --git a/gdb/testsuite/gdb.debuginfod/libsection1.c b/gdb/testsuite= /gdb.debuginfod/libsection1.c > > new file mode 100644 > > index 00000000000..60824b415c6 > > --- /dev/null > > +++ b/gdb/testsuite/gdb.debuginfod/libsection1.c > > @@ -0,0 +1,40 @@ > > +/* This testcase is part of GDB, the GNU debugger. > > + > > + Copyright 2023 Free Software Foundation, Inc. > > + > > + This program is free software; you can redistribute it and/or modif= y > > + it under the terms of the GNU General Public License as published b= y > > + 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 . */ > > + > > +#include > > +#include > > +#include > > + > > +extern void libsection2_test (); > > +extern void *libsection2_thread_test (void *); > > + > > +void > > +libsection1_test () > > +{ > > + pthread_t thr; > > + > > + printf ("In libsection1\n"); > > + libsection2_test (); > > + > > + pthread_create (&thr, NULL, libsection2_thread_test, NULL); > > + > > + /* Give the new thread a chance to actually enter libsection2_thread= _test. */ > > + sleep (3); > > + printf ("Cancelling thread\n"); > > + > > + pthread_cancel (thr); > > +} > > diff --git a/gdb/testsuite/gdb.debuginfod/libsection2.c b/gdb/testsuite= /gdb.debuginfod/libsection2.c > > new file mode 100644 > > index 00000000000..629a67f94a5 > > --- /dev/null > > +++ b/gdb/testsuite/gdb.debuginfod/libsection2.c > > @@ -0,0 +1,37 @@ > > +/* This testcase is part of GDB, the GNU debugger. > > + > > + Copyright 2023 Free Software Foundation, Inc. > > + > > + This program is free software; you can redistribute it and/or modif= y > > + it under the terms of the GNU General Public License as published b= y > > + 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 . */ > > + > > +#include > > + > > +void > > +libsection2_test () > > +{ > > + printf ("In libsection2\n"); > > +} > > + > > +void * > > +libsection2_thread_test (void *arg) > > +{ > > + (void) arg; > > + > > + printf ("In thread test\n"); > > + > > + while (1) > > + ; > > + > > + return NULL; > > +} > > diff --git a/gdb/testsuite/gdb.debuginfod/section.c b/gdb/testsuite/gdb= .debuginfod/section.c > > new file mode 100644 > > index 00000000000..d391a8f898e > > --- /dev/null > > +++ b/gdb/testsuite/gdb.debuginfod/section.c > > @@ -0,0 +1,29 @@ > > +/* This testcase is part of GDB, the GNU debugger. > > + > > + Copyright 2023 Free Software Foundation, Inc. > > + > > + This program is free software; you can redistribute it and/or modif= y > > + it under the terms of the GNU General Public License as published b= y > > + 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 . */ > > + > > +#include > > + > > +extern void libsection1_test (); > > + > > +int > > +main() > > +{ > > + libsection1_test (); > > + printf ("in section exec\n"); > > + > > + return 0; > > +} > > diff --git a/gdb/testsuite/gdb.debuginfod/section.exp b/gdb/testsuite/g= db.debuginfod/section.exp > > new file mode 100644 > > index 00000000000..ff57c6e32b7 > > --- /dev/null > > +++ b/gdb/testsuite/gdb.debuginfod/section.exp > > @@ -0,0 +1,184 @@ > > +# 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 = . > > + > > +# Test debuginfod functionality > > + > > +standard_testfile > > + > > +load_lib debuginfod-support.exp > > + > > +require allow_debuginfod_tests > > + > > +set sourcetmp [standard_output_file tmp-${srcfile}] > > +set outputdir [standard_output_file {}] > > + > > +# SECTEXEC is an executable which calls a function from LIB_SL1. > > +set sectfile "section" > > +set sectsrc $srcdir/$subdir/section.c > > +set sectexec [standard_output_file $sectfile] > > + > > +# Solib LIB_SL1 calls functions from LIB_SL2. > > +set libfile1 "libsection1" > > +set libsrc1 $srcdir/$subdir/$libfile1.c > > +set lib_sl1 [standard_output_file $libfile1.sl] > > + > > +set libfile2 "libsection2" > > +set libsrc2 $srcdir/$subdir/$libfile2.c > > +set lib_sl2 [standard_output_file $libfile2.sl] > > + > > +set lib_opts1 [list debug build-id shlib=3D$lib_sl2] > > +set lib_opts2 [list debug build-id] > > +set exec_opts [list debug build-id shlib=3D$lib_sl1 shlib=3D$lib_sl2] > > + > > +clean_restart > > + > > +if {[enable_section_downloads] =3D=3D 0} { > > + untested "GDB does not support debuginfod section downloads" > > + return -1 > > +} > > + > > +# Compile SECTEXEC, LIB_SL1 and LIB_SL2. > > +if { [gdb_compile_shlib $libsrc2 $lib_sl2 $lib_opts2] !=3D "" } { > > + untested "failed to compile $libfile2" > > + return -1 > > +} > > + > > +if { [gdb_compile_shlib_pthreads $libsrc1 $lib_sl1 $lib_opts1] !=3D ""= } { > > + untested "failed to compile $libfile1" > > + return -1 > > +} > > + > > +if { [gdb_compile $sectsrc $sectexec executable $exec_opts] !=3D "" } = { > > + untested "failed to compile $sectfile" > > + return -1 > > +} > > + > > +# Add .gdb_index to solibs. > > +if { [have_index $lib_sl1] !=3D "gdb_index" > > + && [add_gdb_index $lib_sl1] =3D=3D 0 } { > > + untested "failed to add .gdb_index to $libfile1" > > + return -1 > > +} > > + > > +if { [have_index $lib_sl2] !=3D "gdb_index" > > + && [add_gdb_index $lib_sl2] =3D=3D 0 } { > > + untested "failed to add .gdb_index to $libfile2" > > + return -1 > > +} > > + > > +# Strip solib debuginfo into separate files. > > +if { [gdb_gnu_strip_debug $lib_sl1 ""] !=3D 0} { > > + fail "strip $lib_sl1 debuginfo" > > + return -1 > > +} > > + > > +if { [gdb_gnu_strip_debug $lib_sl2 ""] !=3D 0} { > > + fail "strip $lib_sl2 debuginfo" > > + return -1 > > +} > > + > > +# Move debuginfo files into directory that debuginfod will serve from. > > +set debugdir [standard_output_file "debug"] > > +set debuginfo_sl1 [standard_output_file $libfile1.sl.debug] > > +set debuginfo_sl2 [standard_output_file $libfile2.sl.debug] > > + > > +file mkdir $debugdir > > +file rename -force $debuginfo_sl1 $debugdir > > +file rename -force $debuginfo_sl2 $debugdir > > + > > +# Restart GDB and clear the debuginfod client cache. Then load BINFILE= into > > +# GDB and start running it. Match output with pattern RES and use TES= TNAME > > +# as the test name. > > +proc_with_prefix clean_restart_with_prompt { binfile res testname } { > > + global cache > > + > > + # Delete client cache so debuginfo downloads again. > > + file delete -force $cache > > + clean_restart > > + > > + gdb_test "set debuginfod enabled on" "" "clean_restart enable $tes= tname" > > + gdb_load $binfile > > + > > + if {![runto_main]} { > > + return > > + } > > +} > > + > > +# Tests with no debuginfod server running. > > +proc_with_prefix no_url { } { > > + global sectexec libfile1 libfile2 > > + > > + gdb_load $sectexec > > + if {![runto_main]} { > > + return > > + } > > + > > + # Check that no section is downloaded and no debuginfo is found. > > + gdb_test "info sharedlibrary" ".*Yes \\(\\*\\).*$libfile1.*" \ > > + "found no url lib1" > > + gdb_test "info sharedlibrary" ".*Yes \\(\\*\\).*$libfile2.*" \ > > + "found no url lib2" > > +} > > + > > +# Tests with a debuginfod server running. > > +proc_with_prefix local_url { } { > > + global sectexec > > + global libsrc1 lib_sl1 libfile1 > > + global libsrc2 lib_sl2 libfile2 > > + global debugdir db > > + > > + set url [start_debuginfod $db $debugdir] > > + if { $url =3D=3D "" } { > > + unresolved "failed to start debuginfod server" > > + return > > + } > > + > > + # Point GDB to the server. > > + setenv DEBUGINFOD_URLS $url > > + > > + # Download .gdb_index for solibs. > > + set res ".*section \.gdb_index for $lib_sl1.*\ > > + section \.gdb_index for $lib_sl2.*" > > + clean_restart_with_prompt $sectexec $res "index" > > + > > + # Download debuginfo when stepping into a function. > > + set res ".*separate debug info for $lib_sl1.*\"In ${libfile1}\\\\n= \".*" > > + gdb_test "step" $res "step" > > + > > + clean_restart_with_prompt $sectexec "" "break" > > + > > + # Download debuginfo when setting a breakpoint. > > + set res "Download.*separate debug info for $lib_sl2.*" > > + gdb_test "br libsection2_test" $res "break set" > > + > > + # Hit the breakpoint. > > + set res ".*Breakpoint 2, libsection2_test.*\"In ${libfile2}\\\\n\"= .*" > > + gdb_test "c" $res "break continue" > > + > > + # Check that download progress message is correctly formatted > > + # during backtrace. > > + set res ".*debug info for $lib_sl1\.\.\.\r\n\#1.*" > > + gdb_test "bt" $res "break backtrace" > > +} > > + > > +# Create CACHE and DB directories ready for debuginfod to use. > > +prepare_for_debuginfod cache db > > + > > +with_debuginfod_env $cache { > > + no_url > > + local_url > > +} > > + > > +stop_debuginfod > > diff --git a/gdb/testsuite/lib/debuginfod-support.exp b/gdb/testsuite/l= ib/debuginfod-support.exp > > index 50a8b512a4a..e0b3dc39f51 100644 > > --- a/gdb/testsuite/lib/debuginfod-support.exp > > +++ b/gdb/testsuite/lib/debuginfod-support.exp > > @@ -113,6 +113,8 @@ proc with_debuginfod_env { cache body } { > > proc start_debuginfod { db debugdir } { > > global debuginfod_spawn_id spawn_id > > > > + set logfile [standard_output_file "server_log"] > > + > > # Find an unused port. > > set port 7999 > > set found false > > @@ -127,7 +129,8 @@ proc start_debuginfod { db debugdir } { > > set old_spawn_id $spawn_id > > } > > > > - spawn debuginfod -vvvv -d $db -p $port -F $debugdir > > + spawn sh -c "debuginfod -vvvv -d $db -p $port -F $debugdir 2>&1= \ > > + | tee $logfile" > > set debuginfod_spawn_id $spawn_id > > > > if { [info exists old_spawn_id] } { > > @@ -194,3 +197,25 @@ proc stop_debuginfod { } { > > unset debuginfod_spawn_id > > } > > } > > + > > +# Return 1 if gdb is configured to download ELF/DWARF sections from > > +# debuginfod servers. Otherwise return 0. > > +proc enable_section_downloads { } { > > + global gdb_prompt > > + > > + set cmd "maint set debuginfod download-sections on" > > + set msg "enable section downloads" > > + > > + gdb_test_multiple $cmd $msg { > > + -re -wrap ".*not compiled into GDB.*" { > > + return 0 > > + } > > + -re -wrap "^" { > > + return 1 > > + } > > + -re -wrap "" { > > + fail "$gdb_test_name (unexpected output)" > > + return 0 > > + } > > + } > > +} > > -- > > 2.41.0 > >