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, 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_gnu_debugaltlink] = ".gnu_debugaltlink"
73 : : };
74 : : #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
75 : :
76 : : /* Map from section index to string section index.
77 : : Non-string sections should have STR_SCN_IDX_last. */
78 : : static const enum string_section_index scn_to_string_section_idx[IDX_last] =
79 : : {
80 : : [IDX_debug_info] = STR_SCN_IDX_last,
81 : : [IDX_debug_types] = STR_SCN_IDX_last,
82 : : [IDX_debug_abbrev] = STR_SCN_IDX_last,
83 : : [IDX_debug_addr] = STR_SCN_IDX_last,
84 : : [IDX_debug_aranges] = STR_SCN_IDX_last,
85 : : [IDX_debug_line] = STR_SCN_IDX_last,
86 : : [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str,
87 : : [IDX_debug_frame] = STR_SCN_IDX_last,
88 : : [IDX_debug_loc] = STR_SCN_IDX_last,
89 : : [IDX_debug_loclists] = STR_SCN_IDX_last,
90 : : [IDX_debug_pubnames] = STR_SCN_IDX_last,
91 : : [IDX_debug_str] = STR_SCN_IDX_debug_str,
92 : : [IDX_debug_str_offsets] = STR_SCN_IDX_last,
93 : : [IDX_debug_macinfo] = STR_SCN_IDX_last,
94 : : [IDX_debug_macro] = STR_SCN_IDX_last,
95 : : [IDX_debug_ranges] = STR_SCN_IDX_last,
96 : : [IDX_debug_rnglists] = STR_SCN_IDX_last,
97 : : [IDX_debug_cu_index] = STR_SCN_IDX_last,
98 : : [IDX_debug_tu_index] = STR_SCN_IDX_last,
99 : : [IDX_gnu_debugaltlink] = STR_SCN_IDX_last
100 : : };
101 : :
102 : : static enum dwarf_type
103 : 353536 : scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
104 : : {
105 : 353536 : GElf_Shdr shdr_mem;
106 : 353536 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
107 [ - + ]: 353536 : if (shdr == NULL)
108 : : return TYPE_UNKNOWN;
109 : :
110 : 707072 : const char *scnname = elf_strptr (result->elf, shstrndx,
111 : 353536 : shdr->sh_name);
112 [ + + ]: 353536 : if (scnname != NULL)
113 : : {
114 [ + + ]: 353454 : if (startswith (scnname, ".gnu.debuglto_.debug"))
115 : : return TYPE_GNU_LTO;
116 [ + - ]: 353444 : else if (strcmp (scnname, ".debug_cu_index") == 0
117 [ + - ]: 353444 : || strcmp (scnname, ".debug_tu_index") == 0
118 [ + - ]: 353444 : || strcmp (scnname, ".zdebug_cu_index") == 0
119 [ + - ]: 353444 : || strcmp (scnname, ".zdebug_tu_index") == 0)
120 : : return TYPE_DWO;
121 [ + + + + ]: 353444 : else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
122 : : {
123 : 12286 : size_t len = strlen (scnname);
124 [ + + ]: 12286 : if (strcmp (scnname + len - 4, ".dwo") == 0)
125 : : return TYPE_DWO;
126 : : else
127 : 11450 : return TYPE_PLAIN;
128 : : }
129 : : }
130 : : return TYPE_UNKNOWN;
131 : : }
132 : : static Dwarf *
133 : 598424 : check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
134 : : {
135 : 598424 : GElf_Shdr shdr_mem;
136 : 598424 : GElf_Shdr *shdr;
137 : :
138 : : /* Get the section header data. */
139 : 598424 : shdr = gelf_getshdr (scn, &shdr_mem);
140 [ - + ]: 598424 : if (shdr == NULL)
141 : : /* We may read /proc/PID/mem with only program headers mapped and section
142 : : headers out of the mapped pages. */
143 : 0 : goto err;
144 : :
145 : : /* Ignore any SHT_NOBITS sections. Debugging sections should not
146 : : have been stripped, but in case of a corrupt file we won't try
147 : : to look at the missing data. */
148 [ + + ]: 598424 : if (unlikely (shdr->sh_type == SHT_NOBITS))
149 : : return result;
150 : :
151 : : /* Make sure the section is part of a section group only iff we
152 : : really need it. If we are looking for the global (= non-section
153 : : group debug info) we have to ignore all the info in section
154 : : groups. If we are looking into a section group we cannot look at
155 : : a section which isn't part of the section group. */
156 [ + - + + ]: 566022 : if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
157 : : /* Ignore the section. */
158 : : return result;
159 : :
160 : :
161 : : /* We recognize the DWARF section by their names. This is not very
162 : : safe and stable but the best we can do. */
163 : 1132040 : const char *scnname = elf_strptr (result->elf, shstrndx,
164 : 566020 : shdr->sh_name);
165 [ + + ]: 566020 : if (scnname == NULL)
166 : : {
167 : : /* The section name must be valid. Otherwise is the ELF file
168 : : invalid. */
169 : 2 : err:
170 : 2 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
171 : 2 : __libdw_seterrno (DWARF_E_INVALID_ELF);
172 : 2 : free (result);
173 : 2 : return NULL;
174 : : }
175 : :
176 : : /* Recognize the various sections. Most names start with .debug_.
177 : : They might be compressed (and start with .z). Or end with .dwo
178 : : for split dwarf sections. Or start with .gnu.debuglto_ for
179 : : LTO debug sections. We should only use one consistent set at
180 : : a time. We prefer PLAIN over DWO over LTO. */
181 : : size_t cnt;
182 : 10662182 : bool gnu_compressed = false;
183 [ + + ]: 10662182 : for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
184 : : {
185 : : /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix,
186 : : but they are for DWO. */
187 [ + + ]: 10186346 : if (result->type != TYPE_DWO
188 [ + + ]: 10171758 : && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
189 : 951056 : continue;
190 : 18470580 : bool need_dot_dwo =
191 : : (result->type == TYPE_DWO
192 : : && cnt != IDX_debug_cu_index
193 [ + + + + ]: 9235290 : && cnt != IDX_debug_tu_index);
194 : 9235290 : size_t dbglen = strlen (dwarf_scnnames[cnt]);
195 : 9235290 : size_t scnlen = strlen (scnname);
196 [ + + ]: 9235290 : if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
197 [ + + ]: 110914 : && ((!need_dot_dwo && dbglen == scnlen)
198 [ + + ]: 21732 : || (need_dot_dwo
199 [ + + ]: 1040 : && scnlen == dbglen + 4
200 [ - + ]: 836 : && strstr (scnname, ".dwo") == scnname + dbglen)))
201 : : break;
202 [ + + + + ]: 9145272 : else if (scnname[0] == '.' && scnname[1] == 'z'
203 [ + + ]: 1188 : && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
204 : : dbglen - 1) == 0
205 [ + - - + ]: 164 : && ((!need_dot_dwo && scnlen == dbglen + 1)
206 : : || (need_dot_dwo
207 [ # # ]: 0 : && scnlen == dbglen + 5
208 : 0 : && strstr (scnname,
209 [ # # ]: 0 : ".dwo") == scnname + dbglen + 1))))
210 : : {
211 : : gnu_compressed = true;
212 : : break;
213 : : }
214 [ + + ]: 9145108 : else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
215 [ + + ]: 769356 : && startswith (scnname, ".gnu.debuglto_")
216 [ + + ]: 180 : && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
217 : : {
218 [ + - ]: 10 : if (result->type == TYPE_GNU_LTO)
219 : : break;
220 : : }
221 : : }
222 : :
223 [ + + ]: 566018 : if (cnt >= ndwarf_scnnames)
224 : : /* Not a debug section; ignore it. */
225 : : return result;
226 : :
227 [ - + ]: 90182 : if (unlikely (result->sectiondata[cnt] != NULL))
228 : : /* A section appears twice. That's bad. We ignore the section. */
229 : : return result;
230 : :
231 : : /* We cannot know whether or not a GNU compressed section has already
232 : : been uncompressed or not, so ignore any errors. */
233 [ + + ]: 90182 : if (gnu_compressed)
234 : 164 : elf_compress_gnu (scn, 0, 0);
235 : :
236 [ + + ]: 90182 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
237 : : {
238 [ - + ]: 806 : if (elf_compress (scn, 0, 0) < 0)
239 : : {
240 : : /* It would be nice if we could fail with a specific error.
241 : : But we don't know if this was an essential section or not.
242 : : So just continue for now. See also valid_p(). */
243 : : return result;
244 : : }
245 : : }
246 : :
247 : : /* Get the section data. Should be raw bytes, no conversion needed. */
248 : 90182 : Elf_Data *data = elf_rawdata (scn, NULL);
249 [ - + ]: 90182 : if (data == NULL)
250 : 0 : goto err;
251 : :
252 [ + + - + ]: 90182 : if (data->d_buf == NULL || data->d_size == 0)
253 : : /* No data actually available, ignore it. */
254 : : return result;
255 : :
256 : : /* We can now read the section data into results. */
257 : 90170 : result->sectiondata[cnt] = data;
258 : :
259 : : /* If the section contains string data, we want to know a size of a prefix
260 : : where any string will be null-terminated. */
261 : 90170 : enum string_section_index string_section_idx = scn_to_string_section_idx[cnt];
262 [ + + ]: 90170 : if (string_section_idx < STR_SCN_IDX_last)
263 : : {
264 : : size_t size = data->d_size;
265 : : /* Reduce the size by the number of non-zero bytes at the end of the
266 : : section. */
267 [ + - - + ]: 21856 : while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
268 : : --size;
269 : 21856 : result->string_section_size[string_section_idx] = size;
270 : : }
271 : :
272 : : return result;
273 : : }
274 : :
275 : :
276 : : /* Helper function to set debugdir field. We want to cache the dir
277 : : where we found this Dwarf ELF file to locate alt and dwo files. */
278 : : char *
279 : 12990 : __libdw_debugdir (int fd)
280 : : {
281 : : /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */
282 : 12990 : char devfdpath[25];
283 [ + - ]: 12990 : sprintf (devfdpath, "/proc/self/fd/%u", fd);
284 [ + - ]: 12990 : char *fdpath = realpath (devfdpath, NULL);
285 : 12990 : char *fddir;
286 [ + + + - ]: 12990 : if (fdpath != NULL && fdpath[0] == '/'
287 [ + - ]: 12112 : && (fddir = strrchr (fdpath, '/')) != NULL)
288 : : {
289 : 12112 : *++fddir = '\0';
290 : 12112 : return fdpath;
291 : : }
292 : : return NULL;
293 : : }
294 : :
295 : :
296 : : /* Check whether all the necessary DWARF information is available. */
297 : : static Dwarf *
298 : 11912 : valid_p (Dwarf *result)
299 : : {
300 : : /* We looked at all the sections. Now determine whether all the
301 : : sections with debugging information we need are there.
302 : :
303 : : Require at least one section that can be read "standalone". */
304 [ + + ]: 11912 : if (likely (result != NULL)
305 [ + + + + : 11910 : && unlikely (result->sectiondata[IDX_debug_info] == NULL
+ + ]
306 : : && result->sectiondata[IDX_debug_line] == NULL
307 : : && result->sectiondata[IDX_debug_frame] == NULL))
308 : : {
309 : 320 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
310 : 320 : __libdw_seterrno (DWARF_E_NO_DWARF);
311 : 320 : free (result);
312 : 320 : result = NULL;
313 : : }
314 : :
315 : : /* We are setting up some "fake" CUs, which need an address size.
316 : : Check the ELF class to come up with something reasonable. */
317 : 23490 : int elf_addr_size = 8;
318 [ + + ]: 11900 : if (result != NULL)
319 : : {
320 : 11590 : GElf_Ehdr ehdr;
321 [ - + ]: 11590 : if (gelf_getehdr (result->elf, &ehdr) == NULL)
322 : : {
323 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
324 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
325 : 0 : free (result);
326 : 0 : result = NULL;
327 : : }
328 [ + + ]: 11590 : else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
329 : 236 : elf_addr_size = 4;
330 : : }
331 : :
332 : : /* For dwarf_location_attr () we need a "fake" CU to indicate
333 : : where the "fake" attribute data comes from. This is a block
334 : : inside the .debug_loc or .debug_loclists section. */
335 [ + + ]: 11590 : if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
336 : : {
337 : 296 : result->fake_loc_cu = malloc (sizeof (Dwarf_CU));
338 [ - + ]: 296 : if (unlikely (result->fake_loc_cu == NULL))
339 : : {
340 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
341 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
342 : 0 : free (result);
343 : 0 : result = NULL;
344 : : }
345 : : else
346 : : {
347 : 296 : result->fake_loc_cu->sec_idx = IDX_debug_loc;
348 : 296 : result->fake_loc_cu->dbg = result;
349 : 296 : result->fake_loc_cu->startp
350 : 296 : = result->sectiondata[IDX_debug_loc]->d_buf;
351 : 296 : result->fake_loc_cu->endp
352 : 296 : = (result->sectiondata[IDX_debug_loc]->d_buf
353 : 296 : + result->sectiondata[IDX_debug_loc]->d_size);
354 : 296 : result->fake_loc_cu->locs = NULL;
355 : 296 : result->fake_loc_cu->address_size = elf_addr_size;
356 : 296 : result->fake_loc_cu->offset_size = 4;
357 : 296 : result->fake_loc_cu->version = 4;
358 : 296 : result->fake_loc_cu->split = NULL;
359 : : }
360 : : }
361 : :
362 [ + + ]: 11590 : if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
363 : : {
364 : 10380 : result->fake_loclists_cu = malloc (sizeof (Dwarf_CU));
365 [ - + ]: 10380 : if (unlikely (result->fake_loclists_cu == NULL))
366 : : {
367 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
368 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
369 : 0 : free (result->fake_loc_cu);
370 : 0 : free (result);
371 : 0 : result = NULL;
372 : : }
373 : : else
374 : : {
375 : 10380 : result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
376 : 10380 : result->fake_loclists_cu->dbg = result;
377 : 10380 : result->fake_loclists_cu->startp
378 : 10380 : = result->sectiondata[IDX_debug_loclists]->d_buf;
379 : 10380 : result->fake_loclists_cu->endp
380 : 10380 : = (result->sectiondata[IDX_debug_loclists]->d_buf
381 : 10380 : + result->sectiondata[IDX_debug_loclists]->d_size);
382 : 10380 : result->fake_loclists_cu->locs = NULL;
383 : 10380 : result->fake_loclists_cu->address_size = elf_addr_size;
384 : 10380 : result->fake_loclists_cu->offset_size = 4;
385 : 10380 : result->fake_loclists_cu->version = 5;
386 : 10380 : result->fake_loclists_cu->split = NULL;
387 : : }
388 : : }
389 : :
390 : : /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
391 : : the dwarf_location_attr () will need a "fake" address CU to
392 : : indicate where the attribute data comes from. This is a just
393 : : inside the .debug_addr section, if it exists. */
394 [ + + ]: 11590 : if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
395 : : {
396 : 82 : result->fake_addr_cu = malloc (sizeof (Dwarf_CU));
397 [ - + ]: 82 : if (unlikely (result->fake_addr_cu == NULL))
398 : : {
399 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
400 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
401 : 0 : free (result->fake_loc_cu);
402 : 0 : free (result->fake_loclists_cu);
403 : 0 : free (result);
404 : 0 : result = NULL;
405 : : }
406 : : else
407 : : {
408 : 82 : result->fake_addr_cu->sec_idx = IDX_debug_addr;
409 : 82 : result->fake_addr_cu->dbg = result;
410 : 82 : result->fake_addr_cu->startp
411 : 82 : = result->sectiondata[IDX_debug_addr]->d_buf;
412 : 82 : result->fake_addr_cu->endp
413 : 82 : = (result->sectiondata[IDX_debug_addr]->d_buf
414 : 82 : + result->sectiondata[IDX_debug_addr]->d_size);
415 : 82 : result->fake_addr_cu->locs = NULL;
416 : 82 : result->fake_addr_cu->address_size = elf_addr_size;
417 : 82 : result->fake_addr_cu->offset_size = 4;
418 : 82 : result->fake_addr_cu->version = 5;
419 : 82 : result->fake_addr_cu->split = NULL;
420 : : }
421 : : }
422 : :
423 : 82 : if (result != NULL)
424 : 11590 : result->debugdir = __libdw_debugdir (result->elf->fildes);
425 : :
426 : 11912 : return result;
427 : : }
428 : :
429 : :
430 : : static Dwarf *
431 : 11912 : global_read (Dwarf *result, Elf *elf, size_t shstrndx)
432 : : {
433 : 11912 : Elf_Scn *scn = NULL;
434 : :
435 : : /* First check the type (PLAIN, DWO, LTO) we are looking for. We
436 : : prefer PLAIN if available over DWO, over LTO. */
437 [ + + + + ]: 365448 : while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN)
438 : : {
439 : 353536 : enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
440 [ + + ]: 353536 : if (type > result->type)
441 : 11592 : result->type = type;
442 : : }
443 : :
444 : : scn = NULL;
445 [ + + + + ]: 610336 : while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
446 : 598424 : result = check_section (result, shstrndx, scn, false);
447 : :
448 : 11912 : return valid_p (result);
449 : : }
450 : :
451 : :
452 : : static Dwarf *
453 : 0 : scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
454 : : {
455 : 0 : GElf_Shdr shdr_mem;
456 : 0 : GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
457 [ # # ]: 0 : if (shdr == NULL)
458 : : {
459 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
460 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
461 : 0 : free (result);
462 : 0 : return NULL;
463 : : }
464 : :
465 [ # # ]: 0 : if ((shdr->sh_flags & SHF_COMPRESSED) != 0
466 [ # # ]: 0 : && elf_compress (scngrp, 0, 0) < 0)
467 : : {
468 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
469 : 0 : __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
470 : 0 : free (result);
471 : 0 : return NULL;
472 : : }
473 : :
474 : : /* SCNGRP is the section descriptor for a section group which might
475 : : contain debug sections. */
476 : 0 : Elf_Data *data = elf_getdata (scngrp, NULL);
477 [ # # ]: 0 : if (data == NULL)
478 : : {
479 : : /* We cannot read the section content. Fail! */
480 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
481 : 0 : free (result);
482 : 0 : return NULL;
483 : : }
484 : :
485 : : /* The content of the section is a number of 32-bit words which
486 : : represent section indices. The first word is a flag word. */
487 : 0 : Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
488 : 0 : size_t cnt;
489 : :
490 : : /* First check the type (PLAIN, DWO, LTO) we are looking for. We
491 : : prefer PLAIN if available over DWO, over LTO. */
492 [ # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
493 : : {
494 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
495 [ # # ]: 0 : if (scn == NULL)
496 : : {
497 : : /* A section group refers to a non-existing section. Should
498 : : never happen. */
499 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
500 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
501 : 0 : free (result);
502 : 0 : return NULL;
503 : : }
504 : :
505 : 0 : enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
506 [ # # ]: 0 : if (type > result->type)
507 : 0 : result->type = type;
508 : : }
509 : :
510 [ # # # # ]: 0 : for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
511 : : {
512 : 0 : Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
513 [ # # ]: 0 : assert (scn != NULL); // checked above
514 : 0 : result = check_section (result, shstrndx, scn, true);
515 [ # # ]: 0 : if (result == NULL)
516 : : break;
517 : : }
518 : :
519 : 0 : return valid_p (result);
520 : : }
521 : :
522 : :
523 : : Dwarf *
524 : 11912 : dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
525 : : {
526 : 11912 : GElf_Ehdr *ehdr;
527 : 11912 : GElf_Ehdr ehdr_mem;
528 : :
529 : : /* Get the ELF header of the file. We need various pieces of
530 : : information from it. */
531 : 11912 : ehdr = gelf_getehdr (elf, &ehdr_mem);
532 [ - + ]: 11912 : if (ehdr == NULL)
533 : : {
534 [ # # ]: 0 : if (elf_kind (elf) != ELF_K_ELF)
535 : 0 : __libdw_seterrno (DWARF_E_NOELF);
536 : : else
537 : 0 : __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
538 : :
539 : 0 : return NULL;
540 : : }
541 : :
542 : :
543 : : /* Default memory allocation size. */
544 : 11912 : size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
545 [ - + ]: 11912 : assert (sizeof (struct Dwarf) < mem_default_size);
546 : :
547 : : /* Allocate the data structure. */
548 : 11912 : Dwarf *result = calloc (1, sizeof (Dwarf));
549 [ + - ]: 11912 : if (unlikely (result == NULL)
550 [ - + ]: 11912 : || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
551 : : {
552 : 0 : free (result);
553 : 0 : __libdw_seterrno (DWARF_E_NOMEM);
554 : 0 : return NULL;
555 : : }
556 : :
557 : : /* Fill in some values. */
558 [ + + ]: 11912 : if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
559 : : || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
560 : 132 : result->other_byte_order = true;
561 : :
562 : 11912 : result->elf = elf;
563 : 11912 : result->alt_fd = -1;
564 : :
565 : : /* Initialize the memory handling. Initial blocks are allocated on first
566 : : actual allocation. */
567 : 11912 : result->mem_default_size = mem_default_size;
568 : 11912 : result->oom_handler = __libdw_oom;
569 [ - + ]: 11912 : if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
570 : : {
571 : 0 : free (result);
572 : 0 : __libdw_seterrno (DWARF_E_NOMEM); /* no memory. */
573 : 0 : return NULL;
574 : : }
575 : 11912 : result->mem_stacks = 0;
576 : 11912 : result->mem_tails = NULL;
577 : :
578 [ + - ]: 11912 : if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
579 : : {
580 : : /* All sections are recognized by name, so pass the section header
581 : : string index along to easily get the section names. */
582 : 11912 : size_t shstrndx;
583 [ - + ]: 11912 : if (elf_getshdrstrndx (elf, &shstrndx) != 0)
584 : : {
585 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
586 : 0 : __libdw_seterrno (DWARF_E_INVALID_ELF);
587 : 0 : free (result);
588 : 0 : return NULL;
589 : : }
590 : :
591 : : /* If the caller provides a section group we get the DWARF
592 : : sections only from this section group. Otherwise we search
593 : : for the first section with the required name. Further
594 : : sections with the name are ignored. The DWARF specification
595 : : does not really say this is allowed. */
596 [ + - ]: 11912 : if (scngrp == NULL)
597 : 11912 : return global_read (result, elf, shstrndx);
598 : : else
599 : 0 : return scngrp_read (result, elf, shstrndx, scngrp);
600 : : }
601 [ # # ]: 0 : else if (cmd == DWARF_C_WRITE)
602 : : {
603 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
604 : 0 : __libdw_seterrno (DWARF_E_UNIMPL);
605 : 0 : free (result);
606 : 0 : return NULL;
607 : : }
608 : :
609 : 0 : Dwarf_Sig8_Hash_free (&result->sig8_hash);
610 : 0 : __libdw_seterrno (DWARF_E_INVALID_CMD);
611 : 0 : free (result);
612 : 0 : return NULL;
613 : : }
614 : : INTDEF(dwarf_begin_elf)
|