Branch data Line data Source code
1 : : /* Create descriptor from ELF descriptor for processing file.
2 : : Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc.
3 : : Copyright (C) 2023, 2026 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <system.h>
35 : :
36 : : #include <assert.h>
37 : : #include <stdbool.h>
38 : : #include <stddef.h>
39 : : #include <stdlib.h>
40 : : #include <stdio.h>
41 : : #include <string.h>
42 : : #include <sys/types.h>
43 : : #include <sys/stat.h>
44 : : #include <fcntl.h>
45 : :
46 : : #include "libelfP.h"
47 : : #include "libdwP.h"
48 : :
49 : :
50 : : /* Section names. (Note .debug_str_offsets is the largest 19 chars.) */
51 : : static const char dwarf_scnnames[IDX_last][19] =
52 : : {
53 : : [IDX_debug_info] = ".debug_info",
54 : : [IDX_debug_types] = ".debug_types",
55 : : [IDX_debug_abbrev] = ".debug_abbrev",
56 : : [IDX_debug_addr] = ".debug_addr",
57 : : [IDX_debug_aranges] = ".debug_aranges",
58 : : [IDX_debug_line] = ".debug_line",
59 : : [IDX_debug_line_str] = ".debug_line_str",
60 : : [IDX_debug_frame] = ".debug_frame",
61 : : [IDX_debug_loc] = ".debug_loc",
62 : : [IDX_debug_loclists] = ".debug_loclists",
63 : : [IDX_debug_pubnames] = ".debug_pubnames",
64 : : [IDX_debug_str] = ".debug_str",
65 : : [IDX_debug_str_offsets] = ".debug_str_offsets",
66 : : [IDX_debug_macinfo] = ".debug_macinfo",
67 : : [IDX_debug_macro] = ".debug_macro",
68 : : [IDX_debug_ranges] = ".debug_ranges",
69 : : [IDX_debug_rnglists] = ".debug_rnglists",
70 : : [IDX_debug_cu_index] = ".debug_cu_index",
71 : : [IDX_debug_tu_index] = ".debug_tu_index",
72 : : [IDX_debug_sup] = ".debug_sup",
73 : : [IDX_debug_dwp] = ".debug_dwp",
74 : : [IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
75 : : };
76 : : #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
77 : :
78 : : /* Map from section index to string section index.
79 : : Non-string sections should have STR_SCN_IDX_last. */
80 : : static const enum string_section_index scn_to_string_section_idx[IDX_last] =
81 : : {
82 : : [IDX_debug_info] = STR_SCN_IDX_last,
83 : : [IDX_debug_types] = STR_SCN_IDX_last,
84 : : [IDX_debug_abbrev] = STR_SCN_IDX_last,
85 : : [IDX_debug_addr] = STR_SCN_IDX_last,
86 : : [IDX_debug_aranges] = STR_SCN_IDX_last,
87 : : [IDX_debug_line] = STR_SCN_IDX_last,
88 : : [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str,
89 : : [IDX_debug_frame] = STR_SCN_IDX_last,
90 : : [IDX_debug_loc] = STR_SCN_IDX_last,
91 : : [IDX_debug_loclists] = STR_SCN_IDX_last,
92 : : [IDX_debug_pubnames] = STR_SCN_IDX_last,
93 : : [IDX_debug_str] = STR_SCN_IDX_debug_str,
94 : : [IDX_debug_str_offsets] = STR_SCN_IDX_last,
95 : : [IDX_debug_macinfo] = STR_SCN_IDX_last,
96 : : [IDX_debug_macro] = STR_SCN_IDX_last,
97 : : [IDX_debug_ranges] = STR_SCN_IDX_last,
98 : : [IDX_debug_rnglists] = STR_SCN_IDX_last,
99 : : [IDX_debug_cu_index] = STR_SCN_IDX_last,
100 : : [IDX_debug_tu_index] = STR_SCN_IDX_last,
101 : : [IDX_debug_sup] = STR_SCN_IDX_last,
102 : : [IDX_debug_dwp] = STR_SCN_IDX_last,
103 : : [IDX_gnu_debugaltlink] = STR_SCN_IDX_last
104 : : };
105 : :
106 : : static Dwarf_Type
107 : 381228 : scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
108 : : {
109 : 381228 : GElf_Shdr shdr_mem;
110 : 381228 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
111 [ + - ]: 381228 : if (shdr == NULL)
112 : : return DWARF_T_AUTO;
113 : :
114 : 762456 : const char *scnname = elf_strptr (result->elf, shstrndx,
115 : 381228 : shdr->sh_name);
116 [ + + ]: 381228 : if (scnname != NULL)
117 : : {
118 [ + + ]: 381146 : if (startswith (scnname, ".gnu.debuglto_.debug"))
119 : : return DWARF_T_GNU_LTO;
120 [ + + ]: 381104 : else if (strcmp (scnname, ".debug_cu_index") == 0
121 [ + + ]: 381080 : || strcmp (scnname, ".debug_tu_index") == 0
122 [ + - ]: 381058 : || strcmp (scnname, ".zdebug_cu_index") == 0
123 [ + - ]: 381058 : || strcmp (scnname, ".zdebug_tu_index") == 0)
124 : : return DWARF_T_DWO;
125 [ + - ]: 381058 : if (strcmp (scnname, ".debug_dwp") == 0
126 [ + - ]: 381058 : || strcmp (scnname, ".zdebug_dwp") == 0
127 [ + - ]: 381058 : || strcmp (scnname, ".debug_sup") == 0
128 [ + - ]: 381058 : || strcmp (scnname, ".zdebug_sup") == 0)
129 : : return DWARF_T_AUTO; /* not a "real" debug section. */
130 [ + + + + ]: 381058 : else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
131 : : {
132 : 12606 : size_t len = strlen (scnname);
133 [ + + ]: 12606 : if (strcmp (scnname + len - 4, ".dwo") == 0)
134 : : return DWARF_T_DWO;
135 : : else
136 : 12008 : return DWARF_T_PLAIN;
137 : : }
138 : : }
139 : : return DWARF_T_AUTO;
140 : : }
141 : : static Dwarf *
142 : 660866 : check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
143 : : {
144 : 660866 : GElf_Shdr shdr_mem;
145 : 660866 : GElf_Shdr *shdr;
146 : :
147 : : /* Get the section header data. */
148 : 660866 : shdr = gelf_getshdr (scn, &shdr_mem);
149 [ - + ]: 660866 : if (shdr == NULL)
150 : : /* We may read /proc/PID/mem with only program headers mapped and section
151 : : headers out of the mapped pages. */
152 : 0 : goto err;
153 : :
154 : : /* Ignore any SHT_NOBITS sections. Debugging sections should not
155 : : have been stripped, but in case of a corrupt file we won't try
156 : : to look at the missing data. */
157 [ + + ]: 660866 : if (unlikely (shdr->sh_type == SHT_NOBITS))
158 : : return result;
159 : :
160 : : /* Make sure the section is part of a section group only iff we
161 : : really need it. If we are looking for the global (= non-section
162 : : group debug info) we have to ignore all the info in section
163 : : groups. If we are looking into a section group we cannot look at
164 : : a section which isn't part of the section group. */
165 [ + - + + ]: 625696 : if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
166 : : /* Ignore the section. */
167 : : return result;
168 : :
169 : :
170 : : /* We recognize the DWARF section by their names. This is not very
171 : : safe and stable but the best we can do. */
172 : 1213628 : const char *scnname = elf_strptr (result->elf, shstrndx,
173 : 606814 : shdr->sh_name);
174 [ + + ]: 606814 : if (scnname == NULL)
175 : : {
176 : : /* The section name must be valid. Otherwise is the ELF file
177 : : invalid. */
178 : 2 : err:
179 : 2 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
180 : 2 : __libdw_seterrno (DWARF_E_INVALID_ELF);
181 : 2 : free (result);
182 : 2 : return NULL;
183 : : }
184 : :
185 : : /* Recognize the various sections. Most names start with .debug_.
186 : : They might be compressed (and start with .z). Or end with .dwo
187 : : for split dwarf sections. Or start with .gnu.debuglto_ for
188 : : LTO debug sections. We should only use one consistent set at
189 : : a time. We prefer PLAIN over DWO over LTO. */
190 : : size_t cnt;
191 : 12412984 : bool gnu_compressed = false;
192 [ + + ]: 12412984 : for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
193 : : {
194 : : /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix,
195 : : but they are for DWO. */
196 [ + + ]: 11910408 : if (result->type != DWARF_T_DWO
197 [ + + ]: 11884762 : && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
198 : 1004600 : continue;
199 : 21811616 : bool need_dot_dwo =
200 : : (result->type == DWARF_T_DWO
201 : : && cnt != IDX_debug_cu_index
202 [ + + ]: 25646 : && cnt != IDX_debug_tu_index
203 [ + + + + ]: 10930056 : && cnt != IDX_debug_dwp);
204 : 10905808 : size_t dbglen = strlen (dwarf_scnnames[cnt]);
205 : 10905808 : size_t scnlen = strlen (scnname);
206 [ + + ]: 10905808 : if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
207 [ + + ]: 125506 : && ((!need_dot_dwo && dbglen == scnlen)
208 [ + + ]: 22754 : || (need_dot_dwo
209 [ + + ]: 1646 : && scnlen == dbglen + 4
210 [ + + ]: 1314 : && strstr (scnname, ".dwo") == scnname + dbglen)))
211 : : break;
212 [ + + + + ]: 10801746 : else if (scnname[0] == '.' && scnname[1] == 'z'
213 [ + + ]: 1188 : && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
214 : : dbglen - 1) == 0
215 [ + - - + ]: 164 : && ((!need_dot_dwo && scnlen == dbglen + 1)
216 : : || (need_dot_dwo
217 [ # # ]: 0 : && scnlen == dbglen + 5
218 : 0 : && strstr (scnname,
219 [ # # ]: 0 : ".dwo") == scnname + dbglen + 1))))
220 : : {
221 : : gnu_compressed = true;
222 : : break;
223 : : }
224 [ + + ]: 10801582 : else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
225 [ + + ]: 1067218 : && startswith (scnname, ".gnu.debuglto_")
226 [ + + ]: 658 : && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
227 : : {
228 [ + + ]: 40 : if (result->type == DWARF_T_GNU_LTO)
229 : : break;
230 : : }
231 : : }
232 : :
233 [ + + ]: 606812 : if (cnt >= ndwarf_scnnames)
234 : : /* Not a debug section; ignore it. */
235 : : return result;
236 : :
237 [ + + ]: 104236 : if (unlikely (result->sectiondata[cnt] != NULL))
238 : : /* A section appears twice. That's bad. We ignore the section. */
239 : : return result;
240 : :
241 : : /* We cannot know whether or not a GNU compressed section has already
242 : : been uncompressed or not, so ignore any errors. */
243 [ + + ]: 104228 : if (gnu_compressed)
244 : 164 : elf_compress_gnu (scn, 0, 0);
245 : :
246 [ + + ]: 104228 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
247 : : {
248 [ + - ]: 682 : if (elf_compress (scn, 0, 0) < 0)
249 : : {
250 : : /* It would be nice if we could fail with a specific error.
251 : : But we don't know if this was an essential section or not.
252 : : So just continue for now. See also valid_p(). */
253 : : return result;
254 : : }
255 : : }
256 : :
257 : : /* Get the section data. Should be raw bytes, no conversion needed. */
258 : 104228 : Elf_Data *data = elf_rawdata (scn, NULL);
259 [ - + ]: 104228 : if (data == NULL)
260 : 0 : goto err;
261 : :
262 [ + + + - ]: 104228 : if (data->d_buf == NULL || data->d_size == 0)
263 : : /* No data actually available, ignore it. */
264 : : return result;
265 : :
266 : : /* We can now read the section data into results. */
267 : 104216 : result->sectiondata[cnt] = data;
268 : :
269 : : /* If the section contains string data, we want to know a size of a prefix
270 : : where any string will be null-terminated. */
271 : 104216 : enum string_section_index string_section_idx = scn_to_string_section_idx[cnt];
272 [ + + ]: 104216 : if (string_section_idx < STR_SCN_IDX_last)
273 : : {
274 : 22540 : size_t size = data->d_size;
275 : : /* Reduce the size by the number of non-zero bytes at the end of the
276 : : section. */
277 [ + - - + ]: 22540 : while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
278 : : --size;
279 : 22540 : result->string_section_size[string_section_idx] = size;
280 : : }
281 : :
282 : : return result;
283 : : }
284 : :
285 : : char *
286 : 13606 : __libdw_elfpath (int fd)
287 : : {
288 : : /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */
289 : 13606 : char devfdpath[25];
290 [ + - ]: 13606 : sprintf (devfdpath, "/proc/self/fd/%u", fd);
291 [ + - ]: 13606 : return realpath (devfdpath, NULL);
292 : : }
293 : :
294 : :
295 : : void
296 : 12918 : __libdw_set_debugdir (Dwarf *dbg)
297 : : {
298 [ + + + - ]: 12918 : if (dbg->elfpath == NULL || dbg->elfpath[0] != '/')
299 : : return;
300 : 11820 : size_t dirlen = strrchr (dbg->elfpath, '/') - dbg->elfpath + 1;
301 : 11820 : dbg->debugdir = malloc (dirlen + 1);
302 [ + - ]: 11820 : if (dbg->debugdir == NULL)
303 : : return;
304 : 11820 : memcpy (dbg->debugdir, dbg->elfpath, dirlen);
305 : 11820 : dbg->debugdir[dirlen] = '\0';
306 : : }
307 : :
308 : :
309 : : /* Check whether all the necessary DWARF information is available. */
310 : : static Dwarf *
311 : 12494 : valid_p (Dwarf *result)
312 : : {
313 : : /* We looked at all the sections. Now determine whether all the
314 : : sections with debugging information we need are there.
315 : :
316 : : Require at least one section that can be read "standalone". */
317 [ + + ]: 12494 : if (likely (result != NULL)
318 [ + + + + : 12492 : && unlikely (result->sectiondata[IDX_debug_info] == NULL
+ + ]
319 : : && result->sectiondata[IDX_debug_line] == NULL
320 : : && result->sectiondata[IDX_debug_frame] == NULL))
321 : : {
322 : 306 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
323 : 306 : __libdw_seterrno (DWARF_E_NO_DWARF);
324 : 306 : free (result);
325 : 306 : result = NULL;
326 : : }
327 : :
328 : : /* We are setting up some "fake" CUs, which need an address size.
329 : : Check the ELF class to come up with something reasonable. */
330 : 24666 : int elf_addr_size = 8;
331 [ + - ]: 12480 : if (result != NULL)
332 : : {
333 : 12186 : GElf_Ehdr ehdr;
334 [ - + ]: 12186 : if (gelf_getehdr (result->elf, &ehdr) == NULL)
335 : : {
336 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
337 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
338 : 0 : free (result);
339 : 0 : result = NULL;
340 : : }
341 [ + + ]: 12186 : else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
342 : 228 : elf_addr_size = 4;
343 : : }
344 : :
345 : : /* For dwarf_location_attr () we need a "fake" CU to indicate
346 : : where the "fake" attribute data comes from. This is a block
347 : : inside the .debug_loc or .debug_loclists section. */
348 [ + - + + ]: 12186 : if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
349 : : {
350 : 332 : result->fake_loc_cu = malloc (sizeof (Dwarf_CU));
351 [ - + ]: 332 : if (unlikely (result->fake_loc_cu == NULL))
352 : : {
353 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
354 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
355 : 0 : free (result);
356 : 0 : result = NULL;
357 : : }
358 : : else
359 : : {
360 : 332 : result->fake_loc_cu->sec_idx = IDX_debug_loc;
361 : 332 : result->fake_loc_cu->dbg = result;
362 : 332 : result->fake_loc_cu->startp
363 : 332 : = result->sectiondata[IDX_debug_loc]->d_buf;
364 : 332 : result->fake_loc_cu->endp
365 : 332 : = (result->sectiondata[IDX_debug_loc]->d_buf
366 : 332 : + result->sectiondata[IDX_debug_loc]->d_size);
367 : 332 : result->fake_loc_cu->address_size = elf_addr_size;
368 : 332 : result->fake_loc_cu->offset_size = 4;
369 : 332 : result->fake_loc_cu->version = 4;
370 : 332 : result->fake_loc_cu->split = NULL;
371 : : }
372 : : }
373 : :
374 [ + + ]: 12186 : if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
375 : : {
376 : 10462 : result->fake_loclists_cu = malloc (sizeof (Dwarf_CU));
377 [ - + ]: 10462 : if (unlikely (result->fake_loclists_cu == NULL))
378 : : {
379 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
380 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
381 : 0 : free (result->fake_loc_cu);
382 : 0 : free (result);
383 : 0 : result = NULL;
384 : : }
385 : : else
386 : : {
387 : 10462 : result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
388 : 10462 : result->fake_loclists_cu->dbg = result;
389 : 10462 : result->fake_loclists_cu->startp
390 : 10462 : = result->sectiondata[IDX_debug_loclists]->d_buf;
391 : 10462 : result->fake_loclists_cu->endp
392 : 10462 : = (result->sectiondata[IDX_debug_loclists]->d_buf
393 : 10462 : + result->sectiondata[IDX_debug_loclists]->d_size);
394 : 10462 : result->fake_loclists_cu->address_size = elf_addr_size;
395 : 10462 : result->fake_loclists_cu->offset_size = 4;
396 : 10462 : result->fake_loclists_cu->version = 5;
397 : 10462 : result->fake_loclists_cu->split = NULL;
398 : : }
399 : : }
400 : :
401 : : /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
402 : : the dwarf_location_attr () will need a "fake" address CU to
403 : : indicate where the attribute data comes from. This is a just
404 : : inside the .debug_addr section, if it exists. */
405 [ + + ]: 12186 : if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
406 : : {
407 : 142 : result->fake_addr_cu = malloc (sizeof (Dwarf_CU));
408 [ - + ]: 142 : if (unlikely (result->fake_addr_cu == NULL))
409 : : {
410 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
411 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
412 : 0 : free (result->fake_loc_cu);
413 : 0 : free (result->fake_loclists_cu);
414 : 0 : free (result);
415 : 0 : result = NULL;
416 : : }
417 : : else
418 : : {
419 : 142 : result->fake_addr_cu->sec_idx = IDX_debug_addr;
420 : 142 : result->fake_addr_cu->dbg = result;
421 : 142 : result->fake_addr_cu->startp
422 : 142 : = result->sectiondata[IDX_debug_addr]->d_buf;
423 : 142 : result->fake_addr_cu->endp
424 : 142 : = (result->sectiondata[IDX_debug_addr]->d_buf
425 : 142 : + result->sectiondata[IDX_debug_addr]->d_size);
426 : 142 : result->fake_addr_cu->address_size = elf_addr_size;
427 : 142 : result->fake_addr_cu->offset_size = 4;
428 : 142 : result->fake_addr_cu->version = 5;
429 : 142 : result->fake_addr_cu->split = NULL;
430 : : }
431 : : }
432 : :
433 : 142 : if (result != NULL)
434 : : {
435 [ - + ]: 12186 : if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
436 : : {
437 : 0 : free (result->fake_loc_cu);
438 : 0 : free (result->fake_loclists_cu);
439 : 0 : free (result->fake_addr_cu);
440 : 0 : free (result);
441 : 0 : __libdw_seterrno (DWARF_E_NOMEM); /* no memory. */
442 : 0 : return NULL;
443 : : }
444 : :
445 : 12186 : result->elfpath = __libdw_elfpath (result->elf->fildes);
446 : 12186 : __libdw_set_debugdir(result);
447 : :
448 : : /* Initialize locks and search_trees. */
449 : 12186 : mutex_init (result->dwarf_lock);
450 : 12186 : mutex_init (result->macro_lock);
451 : 12186 : eu_search_tree_init (&result->cu_tree);
452 : 12186 : eu_search_tree_init (&result->tu_tree);
453 : 12186 : eu_search_tree_init (&result->split_tree);
454 : 12186 : eu_search_tree_init (&result->macro_ops_tree);
455 : 12186 : eu_search_tree_init (&result->files_lines_tree);
456 : :
457 [ + + ]: 12186 : if (result->fake_loc_cu != NULL)
458 : : {
459 : 332 : eu_search_tree_init (&result->fake_loc_cu->locs_tree);
460 : 332 : rwlock_init (result->fake_loc_cu->split_lock);
461 : 332 : mutex_init (result->fake_loc_cu->abbrev_lock);
462 : 332 : mutex_init (result->fake_loc_cu->src_lock);
463 : 332 : mutex_init (result->fake_loc_cu->str_off_base_lock);
464 : 332 : mutex_init (result->fake_loc_cu->intern_lock);
465 : : }
466 : :
467 [ + + ]: 12186 : if (result->fake_loclists_cu != NULL)
468 : : {
469 : 10462 : eu_search_tree_init (&result->fake_loclists_cu->locs_tree);
470 : 10462 : rwlock_init (result->fake_loclists_cu->split_lock);
471 : 10462 : mutex_init (result->fake_loclists_cu->abbrev_lock);
472 : 10462 : mutex_init (result->fake_loclists_cu->src_lock);
473 : 10462 : mutex_init (result->fake_loclists_cu->str_off_base_lock);
474 : 10462 : mutex_init (result->fake_loclists_cu->intern_lock);
475 : : }
476 : :
477 [ + + ]: 12186 : if (result->fake_addr_cu != NULL)
478 : : {
479 : 142 : eu_search_tree_init (&result->fake_addr_cu->locs_tree);
480 : 142 : rwlock_init (result->fake_addr_cu->split_lock);
481 : 142 : mutex_init (result->fake_addr_cu->abbrev_lock);
482 : 142 : mutex_init (result->fake_addr_cu->src_lock);
483 : 142 : mutex_init (result->fake_addr_cu->str_off_base_lock);
484 : 142 : mutex_init (result->fake_addr_cu->intern_lock);
485 : : }
486 : : }
487 : :
488 : : return result;
489 : : }
490 : :
491 : :
492 : : static Dwarf *
493 : 12500 : global_read (Dwarf *result, Elf *elf, size_t shstrndx,
494 : : Dwarf_Type requested_type)
495 : : {
496 : 12500 : Elf_Scn *scn = NULL;
497 : :
498 [ + + ]: 12500 : if (requested_type == DWARF_T_AUTO)
499 : : {
500 : : /* First check the type (PLAIN, DWO, LTO) we are looking for. We
501 : : prefer PLAIN if available over DWO, over LTO. */
502 : 786440 : while ((scn = elf_nextscn (elf, scn)) != NULL
503 [ + + + + ]: 393220 : && result->type != DWARF_T_PLAIN)
504 : : {
505 : 380870 : Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
506 [ + + ]: 380870 : if (type > result->type)
507 : 12046 : result->type = type;
508 : : }
509 : : }
510 : : else
511 : : {
512 : : /* Check there is at least one section of the requested type. */
513 : : bool found = false;
514 [ + + + + ]: 508 : while ((scn = elf_nextscn (elf, scn)) != NULL && !found)
515 : : {
516 : 358 : Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
517 [ + + ]: 358 : if (type == requested_type)
518 : 144 : found = true;
519 : : }
520 : :
521 [ + + ]: 150 : if (!found)
522 : : {
523 : : /* Requested type not available. */
524 : 6 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
525 : 6 : __libdw_seterrno (DWARF_E_NO_DWARF);
526 : 6 : free (result);
527 : 6 : return NULL;
528 : : }
529 : :
530 : 144 : result->type = requested_type;
531 : : }
532 : :
533 : 12494 : scn = NULL;
534 [ + + + + ]: 673360 : while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
535 : 660866 : result = check_section (result, shstrndx, scn, false);
536 : :
537 : 12494 : return valid_p (result);
538 : : }
539 : :
540 : :
541 : : static Dwarf *
542 : 0 : scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx,
543 : : Dwarf_Type requested_type, Elf_Scn *scngrp)
544 : : {
545 : 0 : GElf_Shdr shdr_mem;
546 : 0 : GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
547 [ # # ]: 0 : if (shdr == NULL)
548 : : {
549 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
550 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
551 : 0 : free (result);
552 : 0 : return NULL;
553 : : }
554 : :
555 [ # # ]: 0 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0
556 [ # # ]: 0 : && elf_compress (scngrp, 0, 0) < 0)
557 : : {
558 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
559 : 0 : __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
560 : 0 : free (result);
561 : 0 : return NULL;
562 : : }
563 : :
564 : : /* SCNGRP is the section descriptor for a section group which might
565 : : contain debug sections. */
566 : 0 : Elf_Data *data = elf_getdata (scngrp, NULL);
567 [ # # ]: 0 : if (data == NULL)
568 : : {
569 : : /* We cannot read the section content. Fail! */
570 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
571 : 0 : free (result);
572 : 0 : return NULL;
573 : : }
574 : :
575 : : /* The content of the section is a number of 32-bit words which
576 : : represent section indices. The first word is a flag word. */
577 : 0 : Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
578 : 0 : size_t cnt;
579 : :
580 [ # # ]: 0 : if (requested_type == DWARF_T_AUTO)
581 : : {
582 : : /* First check the type (PLAIN, DWO, LTO) we are looking for. We
583 : : prefer PLAIN if available over DWO, over LTO. */
584 [ # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
585 : : {
586 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
587 [ # # ]: 0 : if (scn == NULL)
588 : : {
589 : : /* A section group refers to a non-existing section. Should
590 : : never happen. */
591 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
592 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
593 : 0 : free (result);
594 : 0 : return NULL;
595 : : }
596 : :
597 : 0 : Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
598 [ # # ]: 0 : if (type > result->type)
599 : 0 : result->type = type;
600 : : }
601 : : }
602 : : else
603 : : {
604 : : /* Check there is at least one section of the requested type. */
605 : : bool found = false;
606 [ # # # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && !found; ++cnt)
607 : : {
608 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
609 [ # # ]: 0 : if (scn == NULL)
610 : : {
611 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
612 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
613 : 0 : free (result);
614 : 0 : return NULL;
615 : : }
616 : :
617 : 0 : Dwarf_Type type = scn_dwarf_type (result, shstrndx, scn);
618 [ # # ]: 0 : if (type == requested_type)
619 : 0 : found = true;
620 : : }
621 : :
622 [ # # ]: 0 : if (!found)
623 : : {
624 : : /* Requested type not available. */
625 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
626 : 0 : __libdw_seterrno (DWARF_E_NO_DWARF);
627 : 0 : free (result);
628 : 0 : return NULL;
629 : : }
630 : :
631 : 0 : result->type = requested_type;
632 : : }
633 : :
634 [ # # # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
635 : : {
636 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
637 [ # # ]: 0 : if (scn == NULL)
638 : : {
639 : : /* Bad section in section group, not yet tested above. */
640 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
641 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
642 : 0 : free (result);
643 : 0 : return NULL;
644 : : }
645 : 0 : result = check_section (result, shstrndx, scn, true);
646 [ # # ]: 0 : if (result == NULL)
647 : : break;
648 : : }
649 : :
650 : 0 : return valid_p (result);
651 : : }
652 : :
653 : :
654 : : Dwarf *
655 : 12500 : dwarf_begin_elf_type (Elf *elf, Dwarf_Cmd cmd, Dwarf_Type type,
656 : : Elf_Scn *scngrp)
657 : : {
658 : 12500 : GElf_Ehdr *ehdr;
659 : 12500 : GElf_Ehdr ehdr_mem;
660 : :
661 : : /* Get the ELF header of the file. We need various pieces of
662 : : information from it. */
663 : 12500 : ehdr = gelf_getehdr (elf, &ehdr_mem);
664 [ - + ]: 12500 : if (ehdr == NULL)
665 : : {
666 [ # # ]: 0 : if (elf_kind (elf) != ELF_K_ELF)
667 : 0 : __libdw_seterrno (DWARF_E_NOELF);
668 : : else
669 : 0 : __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
670 : :
671 : : return NULL;
672 : : }
673 : :
674 : :
675 : : /* Default memory allocation size. */
676 : 12500 : size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
677 [ - + ]: 12500 : assert (sizeof (struct Dwarf) < mem_default_size);
678 : :
679 : : /* Allocate the data structure. */
680 : 12500 : Dwarf *result = calloc (1, sizeof (Dwarf));
681 [ + - ]: 12500 : if (unlikely (result == NULL)
682 [ - + ]: 12500 : || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
683 : : {
684 : 0 : free (result);
685 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
686 : 0 : return NULL;
687 : : }
688 : :
689 : : /* Fill in some values. */
690 [ + + ]: 12500 : if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
691 : : || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
692 : 132 : result->other_byte_order = true;
693 : :
694 : 12500 : result->elf = elf;
695 : 12500 : result->alt_fd = -1;
696 : 12500 : result->dwp_fd = -1;
697 : :
698 : : /* Initialize the memory handling. Initial blocks are allocated on first
699 : : actual allocation. */
700 : 12500 : result->mem_default_size = mem_default_size;
701 : 12500 : result->oom_handler = __libdw_oom;
702 : :
703 : 12500 : result->mem_stacks = 0;
704 : 12500 : result->mem_tails = NULL;
705 : :
706 [ + - ]: 12500 : if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
707 : : {
708 : : /* All sections are recognized by name, so pass the section header
709 : : string index along to easily get the section names. */
710 : 12500 : size_t shstrndx;
711 [ - + ]: 12500 : if (elf_getshdrstrndx (elf, &shstrndx) != 0)
712 : : {
713 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
714 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
715 : 0 : free (result);
716 : 0 : return NULL;
717 : : }
718 : :
719 : : /* If the caller provides a section group we get the DWARF
720 : : sections only from this section group. Otherwise we search
721 : : for the first section with the required name. Further
722 : : sections with the name are ignored. The DWARF specification
723 : : does not really say this is allowed. */
724 [ + - ]: 12500 : if (scngrp == NULL)
725 : 12500 : return global_read (result, elf, shstrndx, type);
726 : : else
727 : 0 : return scngrp_read (result, elf, shstrndx, type, scngrp);
728 : : }
729 [ # # ]: 0 : else if (cmd == DWARF_C_WRITE)
730 : : {
731 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
732 : 0 : __libdw_seterrno (DWARF_E_UNIMPL);
733 : 0 : free (result);
734 : 0 : return NULL;
735 : : }
736 : :
737 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
738 : 0 : __libdw_seterrno (DWARF_E_INVALID_CMD);
739 : 0 : free (result);
740 : 0 : return NULL;
741 : : }
742 : : INTDEF(dwarf_begin_elf_type)
743 : :
744 : : Dwarf *
745 : 11732 : dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
746 : : {
747 : 11732 : return dwarf_begin_elf_type (elf, cmd, DWARF_T_AUTO, scngrp);
748 : : }
749 : : INTDEF(dwarf_begin_elf)
750 : :
751 : : Dwarf_Type
752 : 16 : dwarf_get_type (Dwarf *dwarf)
753 : : {
754 [ + + ]: 16 : if (dwarf == NULL)
755 : : return DWARF_T_AUTO;
756 : :
757 : 10 : return dwarf->type;
758 : : }
759 : : INTDEF(dwarf_get_type)
760 : :
|