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