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 <[email protected]>
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
scn_dwarf_type(Dwarf * result,size_t shstrndx,Elf_Scn * scn)103 scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
104 {
105 GElf_Shdr shdr_mem;
106 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
107 if (shdr == NULL)
108 return TYPE_UNKNOWN;
109
110 const char *scnname = elf_strptr (result->elf, shstrndx,
111 shdr->sh_name);
112 if (scnname != NULL)
113 {
114 if (startswith (scnname, ".gnu.debuglto_.debug"))
115 return TYPE_GNU_LTO;
116 else if (strcmp (scnname, ".debug_cu_index") == 0
117 || strcmp (scnname, ".debug_tu_index") == 0
118 || strcmp (scnname, ".zdebug_cu_index") == 0
119 || strcmp (scnname, ".zdebug_tu_index") == 0)
120 return TYPE_DWO;
121 else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
122 {
123 size_t len = strlen (scnname);
124 if (strcmp (scnname + len - 4, ".dwo") == 0)
125 return TYPE_DWO;
126 else
127 return TYPE_PLAIN;
128 }
129 }
130 return TYPE_UNKNOWN;
131 }
132 static Dwarf *
check_section(Dwarf * result,size_t shstrndx,Elf_Scn * scn,bool inscngrp)133 check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
134 {
135 GElf_Shdr shdr_mem;
136 GElf_Shdr *shdr;
137
138 /* Get the section header data. */
139 shdr = gelf_getshdr (scn, &shdr_mem);
140 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 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 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 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 const char *scnname = elf_strptr (result->elf, shstrndx,
164 shdr->sh_name);
165 if (scnname == NULL)
166 {
167 /* The section name must be valid. Otherwise is the ELF file
168 invalid. */
169 err:
170 Dwarf_Sig8_Hash_free (&result->sig8_hash);
171 __libdw_seterrno (DWARF_E_INVALID_ELF);
172 free (result);
173 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 bool gnu_compressed = false;
183 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 if (result->type != TYPE_DWO
188 && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
189 continue;
190 bool need_dot_dwo =
191 (result->type == TYPE_DWO
192 && cnt != IDX_debug_cu_index
193 && cnt != IDX_debug_tu_index);
194 size_t dbglen = strlen (dwarf_scnnames[cnt]);
195 size_t scnlen = strlen (scnname);
196 if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
197 && ((!need_dot_dwo && dbglen == scnlen)
198 || (need_dot_dwo
199 && scnlen == dbglen + 4
200 && strstr (scnname, ".dwo") == scnname + dbglen)))
201 break;
202 else if (scnname[0] == '.' && scnname[1] == 'z'
203 && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
204 dbglen - 1) == 0
205 && ((!need_dot_dwo && scnlen == dbglen + 1)
206 || (need_dot_dwo
207 && scnlen == dbglen + 5
208 && strstr (scnname,
209 ".dwo") == scnname + dbglen + 1))))
210 {
211 gnu_compressed = true;
212 break;
213 }
214 else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
215 && startswith (scnname, ".gnu.debuglto_")
216 && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
217 {
218 if (result->type == TYPE_GNU_LTO)
219 break;
220 }
221 }
222
223 if (cnt >= ndwarf_scnnames)
224 /* Not a debug section; ignore it. */
225 return result;
226
227 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 if (gnu_compressed)
234 elf_compress_gnu (scn, 0, 0);
235
236 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
237 {
238 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 Elf_Data *data = elf_rawdata (scn, NULL);
249 if (data == NULL)
250 goto err;
251
252 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 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 enum string_section_index string_section_idx = scn_to_string_section_idx[cnt];
262 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 while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
268 --size;
269 result->string_section_size[string_section_idx] = size;
270 }
271
272 return result;
273 }
274
275 char *
__libdw_elfpath(int fd)276 __libdw_elfpath (int fd)
277 {
278 /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */
279 char devfdpath[25];
280 sprintf (devfdpath, "/proc/self/fd/%u", fd);
281 return realpath (devfdpath, NULL);
282 }
283
284
285 void
__libdw_set_debugdir(Dwarf * dbg)286 __libdw_set_debugdir (Dwarf *dbg)
287 {
288 if (dbg->elfpath == NULL || dbg->elfpath[0] != '/')
289 return;
290 size_t dirlen = strrchr (dbg->elfpath, '/') - dbg->elfpath + 1;
291 dbg->debugdir = malloc (dirlen + 1);
292 if (dbg->debugdir == NULL)
293 return;
294 memcpy (dbg->debugdir, dbg->elfpath, dirlen);
295 dbg->debugdir[dirlen] = '\0';
296 }
297
298
299 /* Check whether all the necessary DWARF information is available. */
300 static Dwarf *
valid_p(Dwarf * result)301 valid_p (Dwarf *result)
302 {
303 /* We looked at all the sections. Now determine whether all the
304 sections with debugging information we need are there.
305
306 Require at least one section that can be read "standalone". */
307 if (likely (result != NULL)
308 && unlikely (result->sectiondata[IDX_debug_info] == NULL
309 && result->sectiondata[IDX_debug_line] == NULL
310 && result->sectiondata[IDX_debug_frame] == NULL))
311 {
312 Dwarf_Sig8_Hash_free (&result->sig8_hash);
313 __libdw_seterrno (DWARF_E_NO_DWARF);
314 free (result);
315 result = NULL;
316 }
317
318 /* We are setting up some "fake" CUs, which need an address size.
319 Check the ELF class to come up with something reasonable. */
320 int elf_addr_size = 8;
321 if (result != NULL)
322 {
323 GElf_Ehdr ehdr;
324 if (gelf_getehdr (result->elf, &ehdr) == NULL)
325 {
326 Dwarf_Sig8_Hash_free (&result->sig8_hash);
327 __libdw_seterrno (DWARF_E_INVALID_ELF);
328 free (result);
329 result = NULL;
330 }
331 else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
332 elf_addr_size = 4;
333 }
334
335 /* For dwarf_location_attr () we need a "fake" CU to indicate
336 where the "fake" attribute data comes from. This is a block
337 inside the .debug_loc or .debug_loclists section. */
338 if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
339 {
340 result->fake_loc_cu = malloc (sizeof (Dwarf_CU));
341 if (unlikely (result->fake_loc_cu == NULL))
342 {
343 Dwarf_Sig8_Hash_free (&result->sig8_hash);
344 __libdw_seterrno (DWARF_E_NOMEM);
345 free (result);
346 result = NULL;
347 }
348 else
349 {
350 result->fake_loc_cu->sec_idx = IDX_debug_loc;
351 result->fake_loc_cu->dbg = result;
352 result->fake_loc_cu->startp
353 = result->sectiondata[IDX_debug_loc]->d_buf;
354 result->fake_loc_cu->endp
355 = (result->sectiondata[IDX_debug_loc]->d_buf
356 + result->sectiondata[IDX_debug_loc]->d_size);
357 result->fake_loc_cu->locs = NULL;
358 result->fake_loc_cu->address_size = elf_addr_size;
359 result->fake_loc_cu->offset_size = 4;
360 result->fake_loc_cu->version = 4;
361 result->fake_loc_cu->split = NULL;
362 }
363 }
364
365 if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
366 {
367 result->fake_loclists_cu = malloc (sizeof (Dwarf_CU));
368 if (unlikely (result->fake_loclists_cu == NULL))
369 {
370 Dwarf_Sig8_Hash_free (&result->sig8_hash);
371 __libdw_seterrno (DWARF_E_NOMEM);
372 free (result->fake_loc_cu);
373 free (result);
374 result = NULL;
375 }
376 else
377 {
378 result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
379 result->fake_loclists_cu->dbg = result;
380 result->fake_loclists_cu->startp
381 = result->sectiondata[IDX_debug_loclists]->d_buf;
382 result->fake_loclists_cu->endp
383 = (result->sectiondata[IDX_debug_loclists]->d_buf
384 + result->sectiondata[IDX_debug_loclists]->d_size);
385 result->fake_loclists_cu->locs = NULL;
386 result->fake_loclists_cu->address_size = elf_addr_size;
387 result->fake_loclists_cu->offset_size = 4;
388 result->fake_loclists_cu->version = 5;
389 result->fake_loclists_cu->split = NULL;
390 }
391 }
392
393 /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
394 the dwarf_location_attr () will need a "fake" address CU to
395 indicate where the attribute data comes from. This is a just
396 inside the .debug_addr section, if it exists. */
397 if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
398 {
399 result->fake_addr_cu = malloc (sizeof (Dwarf_CU));
400 if (unlikely (result->fake_addr_cu == NULL))
401 {
402 Dwarf_Sig8_Hash_free (&result->sig8_hash);
403 __libdw_seterrno (DWARF_E_NOMEM);
404 free (result->fake_loc_cu);
405 free (result->fake_loclists_cu);
406 free (result);
407 result = NULL;
408 }
409 else
410 {
411 result->fake_addr_cu->sec_idx = IDX_debug_addr;
412 result->fake_addr_cu->dbg = result;
413 result->fake_addr_cu->startp
414 = result->sectiondata[IDX_debug_addr]->d_buf;
415 result->fake_addr_cu->endp
416 = (result->sectiondata[IDX_debug_addr]->d_buf
417 + result->sectiondata[IDX_debug_addr]->d_size);
418 result->fake_addr_cu->locs = NULL;
419 result->fake_addr_cu->address_size = elf_addr_size;
420 result->fake_addr_cu->offset_size = 4;
421 result->fake_addr_cu->version = 5;
422 result->fake_addr_cu->split = NULL;
423 }
424 }
425
426 if (result != NULL)
427 {
428 result->elfpath = __libdw_elfpath (result->elf->fildes);
429 __libdw_set_debugdir(result);
430 }
431
432 return result;
433 }
434
435
436 static Dwarf *
global_read(Dwarf * result,Elf * elf,size_t shstrndx)437 global_read (Dwarf *result, Elf *elf, size_t shstrndx)
438 {
439 Elf_Scn *scn = NULL;
440
441 /* First check the type (PLAIN, DWO, LTO) we are looking for. We
442 prefer PLAIN if available over DWO, over LTO. */
443 while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN)
444 {
445 enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
446 if (type > result->type)
447 result->type = type;
448 }
449
450 scn = NULL;
451 while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
452 result = check_section (result, shstrndx, scn, false);
453
454 return valid_p (result);
455 }
456
457
458 static Dwarf *
scngrp_read(Dwarf * result,Elf * elf,size_t shstrndx,Elf_Scn * scngrp)459 scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
460 {
461 GElf_Shdr shdr_mem;
462 GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
463 if (shdr == NULL)
464 {
465 Dwarf_Sig8_Hash_free (&result->sig8_hash);
466 __libdw_seterrno (DWARF_E_INVALID_ELF);
467 free (result);
468 return NULL;
469 }
470
471 if ((shdr->sh_flags & SHF_COMPRESSED) != 0
472 && elf_compress (scngrp, 0, 0) < 0)
473 {
474 Dwarf_Sig8_Hash_free (&result->sig8_hash);
475 __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
476 free (result);
477 return NULL;
478 }
479
480 /* SCNGRP is the section descriptor for a section group which might
481 contain debug sections. */
482 Elf_Data *data = elf_getdata (scngrp, NULL);
483 if (data == NULL)
484 {
485 /* We cannot read the section content. Fail! */
486 Dwarf_Sig8_Hash_free (&result->sig8_hash);
487 free (result);
488 return NULL;
489 }
490
491 /* The content of the section is a number of 32-bit words which
492 represent section indices. The first word is a flag word. */
493 Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
494 size_t cnt;
495
496 /* First check the type (PLAIN, DWO, LTO) we are looking for. We
497 prefer PLAIN if available over DWO, over LTO. */
498 for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
499 {
500 Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
501 if (scn == NULL)
502 {
503 /* A section group refers to a non-existing section. Should
504 never happen. */
505 Dwarf_Sig8_Hash_free (&result->sig8_hash);
506 __libdw_seterrno (DWARF_E_INVALID_ELF);
507 free (result);
508 return NULL;
509 }
510
511 enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
512 if (type > result->type)
513 result->type = type;
514 }
515
516 for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
517 {
518 Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
519 assert (scn != NULL); // checked above
520 result = check_section (result, shstrndx, scn, true);
521 if (result == NULL)
522 break;
523 }
524
525 return valid_p (result);
526 }
527
528
529 Dwarf *
dwarf_begin_elf(Elf * elf,Dwarf_Cmd cmd,Elf_Scn * scngrp)530 dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
531 {
532 GElf_Ehdr *ehdr;
533 GElf_Ehdr ehdr_mem;
534
535 /* Get the ELF header of the file. We need various pieces of
536 information from it. */
537 ehdr = gelf_getehdr (elf, &ehdr_mem);
538 if (ehdr == NULL)
539 {
540 if (elf_kind (elf) != ELF_K_ELF)
541 __libdw_seterrno (DWARF_E_NOELF);
542 else
543 __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
544
545 return NULL;
546 }
547
548
549 /* Default memory allocation size. */
550 size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
551 assert (sizeof (struct Dwarf) < mem_default_size);
552
553 /* Allocate the data structure. */
554 Dwarf *result = calloc (1, sizeof (Dwarf));
555 if (unlikely (result == NULL)
556 || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
557 {
558 free (result);
559 __libdw_seterrno (DWARF_E_NOMEM);
560 return NULL;
561 }
562
563 /* Fill in some values. */
564 if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
565 || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
566 result->other_byte_order = true;
567
568 result->elf = elf;
569 result->alt_fd = -1;
570 result->dwp_fd = -1;
571
572 /* Initialize the memory handling. Initial blocks are allocated on first
573 actual allocation. */
574 result->mem_default_size = mem_default_size;
575 result->oom_handler = __libdw_oom;
576 if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
577 {
578 free (result);
579 __libdw_seterrno (DWARF_E_NOMEM); /* no memory. */
580 return NULL;
581 }
582 result->mem_stacks = 0;
583 result->mem_tails = NULL;
584
585 if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
586 {
587 /* All sections are recognized by name, so pass the section header
588 string index along to easily get the section names. */
589 size_t shstrndx;
590 if (elf_getshdrstrndx (elf, &shstrndx) != 0)
591 {
592 Dwarf_Sig8_Hash_free (&result->sig8_hash);
593 __libdw_seterrno (DWARF_E_INVALID_ELF);
594 free (result);
595 return NULL;
596 }
597
598 /* If the caller provides a section group we get the DWARF
599 sections only from this section group. Otherwise we search
600 for the first section with the required name. Further
601 sections with the name are ignored. The DWARF specification
602 does not really say this is allowed. */
603 if (scngrp == NULL)
604 return global_read (result, elf, shstrndx);
605 else
606 return scngrp_read (result, elf, shstrndx, scngrp);
607 }
608 else if (cmd == DWARF_C_WRITE)
609 {
610 Dwarf_Sig8_Hash_free (&result->sig8_hash);
611 __libdw_seterrno (DWARF_E_UNIMPL);
612 free (result);
613 return NULL;
614 }
615
616 Dwarf_Sig8_Hash_free (&result->sig8_hash);
617 __libdw_seterrno (DWARF_E_INVALID_CMD);
618 free (result);
619 return NULL;
620 }
621 INTDEF(dwarf_begin_elf)
622