xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/dwarf2/dwz.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* DWARF DWZ handling for GDB.
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 2003-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include "defs.h"
217d62b00eSchristos #include "dwarf2/dwz.h"
227d62b00eSchristos 
23*6881a400Schristos #include "build-id.h"
24*6881a400Schristos #include "debuginfod-support.h"
25*6881a400Schristos #include "dwarf2/read.h"
26*6881a400Schristos #include "dwarf2/sect-names.h"
27*6881a400Schristos #include "filenames.h"
28*6881a400Schristos #include "gdb_bfd.h"
29*6881a400Schristos #include "gdbcore.h"
30*6881a400Schristos #include "gdbsupport/pathstuff.h"
31*6881a400Schristos #include "gdbsupport/scoped_fd.h"
32*6881a400Schristos 
337d62b00eSchristos const char *
347d62b00eSchristos dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
357d62b00eSchristos {
367d62b00eSchristos   str.read (objfile);
377d62b00eSchristos 
387d62b00eSchristos   if (str.buffer == NULL)
397d62b00eSchristos     error (_("DW_FORM_GNU_strp_alt used without .debug_str "
407d62b00eSchristos 	     "section [in module %s]"),
417d62b00eSchristos 	   bfd_get_filename (dwz_bfd.get ()));
427d62b00eSchristos   if (str_offset >= str.size)
437d62b00eSchristos     error (_("DW_FORM_GNU_strp_alt pointing outside of "
447d62b00eSchristos 	     ".debug_str section [in module %s]"),
457d62b00eSchristos 	   bfd_get_filename (dwz_bfd.get ()));
467d62b00eSchristos   gdb_assert (HOST_CHAR_BIT == 8);
477d62b00eSchristos   if (str.buffer[str_offset] == '\0')
487d62b00eSchristos     return NULL;
497d62b00eSchristos   return (const char *) (str.buffer + str_offset);
507d62b00eSchristos }
51*6881a400Schristos 
52*6881a400Schristos /* A helper function to find the sections for a .dwz file.  */
53*6881a400Schristos 
54*6881a400Schristos static void
55*6881a400Schristos locate_dwz_sections (bfd *abfd, asection *sectp, dwz_file *dwz_file)
56*6881a400Schristos {
57*6881a400Schristos   /* Note that we only support the standard ELF names, because .dwz
58*6881a400Schristos      is ELF-only (at the time of writing).  */
59*6881a400Schristos   if (dwarf2_elf_names.abbrev.matches (sectp->name))
60*6881a400Schristos     {
61*6881a400Schristos       dwz_file->abbrev.s.section = sectp;
62*6881a400Schristos       dwz_file->abbrev.size = bfd_section_size (sectp);
63*6881a400Schristos     }
64*6881a400Schristos   else if (dwarf2_elf_names.info.matches (sectp->name))
65*6881a400Schristos     {
66*6881a400Schristos       dwz_file->info.s.section = sectp;
67*6881a400Schristos       dwz_file->info.size = bfd_section_size (sectp);
68*6881a400Schristos     }
69*6881a400Schristos   else if (dwarf2_elf_names.str.matches (sectp->name))
70*6881a400Schristos     {
71*6881a400Schristos       dwz_file->str.s.section = sectp;
72*6881a400Schristos       dwz_file->str.size = bfd_section_size (sectp);
73*6881a400Schristos     }
74*6881a400Schristos   else if (dwarf2_elf_names.line.matches (sectp->name))
75*6881a400Schristos     {
76*6881a400Schristos       dwz_file->line.s.section = sectp;
77*6881a400Schristos       dwz_file->line.size = bfd_section_size (sectp);
78*6881a400Schristos     }
79*6881a400Schristos   else if (dwarf2_elf_names.macro.matches (sectp->name))
80*6881a400Schristos     {
81*6881a400Schristos       dwz_file->macro.s.section = sectp;
82*6881a400Schristos       dwz_file->macro.size = bfd_section_size (sectp);
83*6881a400Schristos     }
84*6881a400Schristos   else if (dwarf2_elf_names.gdb_index.matches (sectp->name))
85*6881a400Schristos     {
86*6881a400Schristos       dwz_file->gdb_index.s.section = sectp;
87*6881a400Schristos       dwz_file->gdb_index.size = bfd_section_size (sectp);
88*6881a400Schristos     }
89*6881a400Schristos   else if (dwarf2_elf_names.debug_names.matches (sectp->name))
90*6881a400Schristos     {
91*6881a400Schristos       dwz_file->debug_names.s.section = sectp;
92*6881a400Schristos       dwz_file->debug_names.size = bfd_section_size (sectp);
93*6881a400Schristos     }
94*6881a400Schristos }
95*6881a400Schristos 
96*6881a400Schristos /* Attempt to find a .dwz file (whose full path is represented by
97*6881a400Schristos    FILENAME) in all of the specified debug file directories provided.
98*6881a400Schristos 
99*6881a400Schristos    Return the equivalent gdb_bfd_ref_ptr of the .dwz file found, or
100*6881a400Schristos    nullptr if it could not find anything.  */
101*6881a400Schristos 
102*6881a400Schristos static gdb_bfd_ref_ptr
103*6881a400Schristos dwz_search_other_debugdirs (std::string &filename, bfd_byte *buildid,
104*6881a400Schristos 			    size_t buildid_len)
105*6881a400Schristos {
106*6881a400Schristos   /* Let's assume that the path represented by FILENAME has the
107*6881a400Schristos      "/.dwz/" subpath in it.  This is what (most) GNU/Linux
108*6881a400Schristos      distributions do, anyway.  */
109*6881a400Schristos   size_t dwz_pos = filename.find ("/.dwz/");
110*6881a400Schristos 
111*6881a400Schristos   if (dwz_pos == std::string::npos)
112*6881a400Schristos     return nullptr;
113*6881a400Schristos 
114*6881a400Schristos   /* This is an obvious assertion, but it's here more to educate
115*6881a400Schristos      future readers of this code that FILENAME at DWZ_POS *must*
116*6881a400Schristos      contain a directory separator.  */
117*6881a400Schristos   gdb_assert (IS_DIR_SEPARATOR (filename[dwz_pos]));
118*6881a400Schristos 
119*6881a400Schristos   gdb_bfd_ref_ptr dwz_bfd;
120*6881a400Schristos   std::vector<gdb::unique_xmalloc_ptr<char>> debugdir_vec
121*6881a400Schristos     = dirnames_to_char_ptr_vec (debug_file_directory.c_str ());
122*6881a400Schristos 
123*6881a400Schristos   for (const gdb::unique_xmalloc_ptr<char> &debugdir : debugdir_vec)
124*6881a400Schristos     {
125*6881a400Schristos       /* The idea is to iterate over the
126*6881a400Schristos 	 debug file directories provided by the user and
127*6881a400Schristos 	 replace the hard-coded path in the "filename" by each
128*6881a400Schristos 	 debug-file-directory.
129*6881a400Schristos 
130*6881a400Schristos 	 For example, suppose that filename is:
131*6881a400Schristos 
132*6881a400Schristos 	   /usr/lib/debug/.dwz/foo.dwz
133*6881a400Schristos 
134*6881a400Schristos 	 And suppose that we have "$HOME/bar" as the
135*6881a400Schristos 	 debug-file-directory.  We would then adjust filename
136*6881a400Schristos 	 to look like:
137*6881a400Schristos 
138*6881a400Schristos 	   $HOME/bar/.dwz/foo.dwz
139*6881a400Schristos 
140*6881a400Schristos 	 which would hopefully allow us to find the alt debug
141*6881a400Schristos 	 file.  */
142*6881a400Schristos       std::string ddir = debugdir.get ();
143*6881a400Schristos 
144*6881a400Schristos       if (ddir.empty ())
145*6881a400Schristos 	continue;
146*6881a400Schristos 
147*6881a400Schristos       /* Make sure the current debug-file-directory ends with a
148*6881a400Schristos 	 directory separator.  This is needed because, if FILENAME
149*6881a400Schristos 	 contains something like "/usr/lib/abcde/.dwz/foo.dwz" and
150*6881a400Schristos 	 DDIR is "/usr/lib/abc", then could wrongfully skip it
151*6881a400Schristos 	 below.  */
152*6881a400Schristos       if (!IS_DIR_SEPARATOR (ddir.back ()))
153*6881a400Schristos 	ddir += SLASH_STRING;
154*6881a400Schristos 
155*6881a400Schristos       /* Check whether the beginning of FILENAME is DDIR.  If it is,
156*6881a400Schristos 	 then we are dealing with a file which we already attempted to
157*6881a400Schristos 	 open before, so we just skip it and continue processing the
158*6881a400Schristos 	 remaining debug file directories.  */
159*6881a400Schristos       if (filename.size () > ddir.size ()
160*6881a400Schristos 	  && filename.compare (0, ddir.size (), ddir) == 0)
161*6881a400Schristos 	continue;
162*6881a400Schristos 
163*6881a400Schristos       /* Replace FILENAME's default debug-file-directory with
164*6881a400Schristos 	 DDIR.  */
165*6881a400Schristos       std::string new_filename = ddir + &filename[dwz_pos + 1];
166*6881a400Schristos 
167*6881a400Schristos       dwz_bfd = gdb_bfd_open (new_filename.c_str (), gnutarget);
168*6881a400Schristos 
169*6881a400Schristos       if (dwz_bfd == nullptr)
170*6881a400Schristos 	continue;
171*6881a400Schristos 
172*6881a400Schristos       if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
173*6881a400Schristos 	{
174*6881a400Schristos 	  dwz_bfd.reset (nullptr);
175*6881a400Schristos 	  continue;
176*6881a400Schristos 	}
177*6881a400Schristos 
178*6881a400Schristos       /* Found it.  */
179*6881a400Schristos       break;
180*6881a400Schristos     }
181*6881a400Schristos 
182*6881a400Schristos   return dwz_bfd;
183*6881a400Schristos }
184*6881a400Schristos 
185*6881a400Schristos /* See dwz.h.  */
186*6881a400Schristos 
187*6881a400Schristos struct dwz_file *
188*6881a400Schristos dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
189*6881a400Schristos {
190*6881a400Schristos   bfd_size_type buildid_len_arg;
191*6881a400Schristos   size_t buildid_len;
192*6881a400Schristos   bfd_byte *buildid;
193*6881a400Schristos 
194*6881a400Schristos   if (per_bfd->dwz_file != NULL)
195*6881a400Schristos     return per_bfd->dwz_file.get ();
196*6881a400Schristos 
197*6881a400Schristos   bfd_set_error (bfd_error_no_error);
198*6881a400Schristos   gdb::unique_xmalloc_ptr<char> data
199*6881a400Schristos     (bfd_get_alt_debug_link_info (per_bfd->obfd,
200*6881a400Schristos 				  &buildid_len_arg, &buildid));
201*6881a400Schristos   if (data == NULL)
202*6881a400Schristos     {
203*6881a400Schristos       if (bfd_get_error () == bfd_error_no_error)
204*6881a400Schristos 	{
205*6881a400Schristos 	  if (!require)
206*6881a400Schristos 	    return nullptr;
207*6881a400Schristos 	  error (_("could not read '.gnu_debugaltlink' section"));
208*6881a400Schristos 	}
209*6881a400Schristos       error (_("could not read '.gnu_debugaltlink' section: %s"),
210*6881a400Schristos 	     bfd_errmsg (bfd_get_error ()));
211*6881a400Schristos     }
212*6881a400Schristos 
213*6881a400Schristos   gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
214*6881a400Schristos 
215*6881a400Schristos   buildid_len = (size_t) buildid_len_arg;
216*6881a400Schristos 
217*6881a400Schristos   std::string filename = data.get ();
218*6881a400Schristos 
219*6881a400Schristos   if (!IS_ABSOLUTE_PATH (filename.c_str ()))
220*6881a400Schristos     {
221*6881a400Schristos       gdb::unique_xmalloc_ptr<char> abs
222*6881a400Schristos 	= gdb_realpath (bfd_get_filename (per_bfd->obfd));
223*6881a400Schristos 
224*6881a400Schristos       filename = ldirname (abs.get ()) + SLASH_STRING + filename;
225*6881a400Schristos     }
226*6881a400Schristos 
227*6881a400Schristos   /* First try the file name given in the section.  If that doesn't
228*6881a400Schristos      work, try to use the build-id instead.  */
229*6881a400Schristos   gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename.c_str (), gnutarget));
230*6881a400Schristos   if (dwz_bfd != NULL)
231*6881a400Schristos     {
232*6881a400Schristos       if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
233*6881a400Schristos 	dwz_bfd.reset (nullptr);
234*6881a400Schristos     }
235*6881a400Schristos 
236*6881a400Schristos   if (dwz_bfd == NULL)
237*6881a400Schristos     dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
238*6881a400Schristos 
239*6881a400Schristos   if (dwz_bfd == nullptr)
240*6881a400Schristos     {
241*6881a400Schristos       /* If the user has provided us with different
242*6881a400Schristos 	 debug file directories, we can try them in order.  */
243*6881a400Schristos       dwz_bfd = dwz_search_other_debugdirs (filename, buildid, buildid_len);
244*6881a400Schristos     }
245*6881a400Schristos 
246*6881a400Schristos   if (dwz_bfd == nullptr)
247*6881a400Schristos     {
248*6881a400Schristos       gdb::unique_xmalloc_ptr<char> alt_filename;
249*6881a400Schristos       const char *origname = bfd_get_filename (per_bfd->obfd);
250*6881a400Schristos 
251*6881a400Schristos       scoped_fd fd (debuginfod_debuginfo_query (buildid,
252*6881a400Schristos 						buildid_len,
253*6881a400Schristos 						origname,
254*6881a400Schristos 						&alt_filename));
255*6881a400Schristos 
256*6881a400Schristos       if (fd.get () >= 0)
257*6881a400Schristos 	{
258*6881a400Schristos 	  /* File successfully retrieved from server.  */
259*6881a400Schristos 	  dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget);
260*6881a400Schristos 
261*6881a400Schristos 	  if (dwz_bfd == nullptr)
262*6881a400Schristos 	    warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
263*6881a400Schristos 		     alt_filename.get ());
264*6881a400Schristos 	  else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
265*6881a400Schristos 	    dwz_bfd.reset (nullptr);
266*6881a400Schristos 	}
267*6881a400Schristos     }
268*6881a400Schristos 
269*6881a400Schristos   if (dwz_bfd == NULL)
270*6881a400Schristos     error (_("could not find '.gnu_debugaltlink' file for %s"),
271*6881a400Schristos 	   bfd_get_filename (per_bfd->obfd));
272*6881a400Schristos 
273*6881a400Schristos   std::unique_ptr<struct dwz_file> result
274*6881a400Schristos     (new struct dwz_file (std::move (dwz_bfd)));
275*6881a400Schristos 
276*6881a400Schristos   for (asection *sec : gdb_bfd_sections (result->dwz_bfd))
277*6881a400Schristos     locate_dwz_sections (result->dwz_bfd.get (), sec, result.get ());
278*6881a400Schristos 
279*6881a400Schristos   gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
280*6881a400Schristos   per_bfd->dwz_file = std::move (result);
281*6881a400Schristos   return per_bfd->dwz_file.get ();
282*6881a400Schristos }
283