]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libdwarf/dwarf_init.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libdwarf / dwarf_init.c
1 /*-
2  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include "_libdwarf.h"
32
33 static const char *debug_snames[DWARF_DEBUG_SNAMES] = {
34         ".debug_abbrev",
35         ".debug_aranges",
36         ".debug_frame",
37         ".debug_info",
38         ".debug_line",
39         ".debug_pubnames",
40         ".eh_frame",
41         ".debug_macinfo",
42         ".debug_str",
43         ".debug_loc",
44         ".debug_pubtypes",
45         ".debug_ranges",
46         ".debug_static_func",
47         ".debug_static_vars",
48         ".debug_types",
49         ".debug_weaknames",
50         ".symtab",
51         ".strtab"
52 };
53
54 static uint64_t (*dwarf_read) (Elf_Data **, uint64_t *, int);
55 static void (*dwarf_write) (Elf_Data **, uint64_t *, uint64_t, int);
56
57 static uint64_t
58 dwarf_read_lsb(Elf_Data **dp, uint64_t *offsetp, int bytes_to_read)
59 {
60         uint64_t ret = 0;
61
62         uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp;
63
64         switch (bytes_to_read) {
65         case 8:
66                 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
67                 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
68         case 4:
69                 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
70         case 2:
71                 ret |= ((uint64_t) src[1]) << 8;
72         case 1:
73                 ret |= src[0];
74                 break;
75         default:
76                 return 0;
77                 break;
78         }
79
80         *offsetp += bytes_to_read;
81
82         return ret;
83 }
84
85 static uint64_t
86 dwarf_read_msb(Elf_Data **dp, uint64_t *offsetp, int bytes_to_read)
87 {
88         uint64_t ret = 0;
89
90         uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp;
91
92         switch (bytes_to_read) {
93         case 1:
94                 ret = src[0];
95                 break;
96         case 2:
97                 ret = src[1] | ((uint64_t) src[0]) << 8;
98                 break;
99         case 4:
100                 ret = src[3] | ((uint64_t) src[2]) << 8;
101                 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
102                 break;
103         case 8:
104                 ret = src[7] | ((uint64_t) src[6]) << 8;
105                 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
106                 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
107                 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
108                 break;
109         default:
110                 return 0;
111                 break;
112         }
113
114         *offsetp += bytes_to_read;
115
116         return ret;
117 }
118
119 static void
120 dwarf_write_lsb(Elf_Data **dp, uint64_t *offsetp, uint64_t value, int bytes_to_write)
121 {
122         uint8_t *dst = (uint8_t *) (*dp)->d_buf + *offsetp;
123
124         switch (bytes_to_write) {
125         case 8:
126                 dst[7] = (value >> 56) & 0xff;
127                 dst[6] = (value >> 48) & 0xff;
128                 dst[5] = (value >> 40) & 0xff;
129                 dst[4] = (value >> 32) & 0xff;
130         case 4:
131                 dst[3] = (value >> 24) & 0xff;
132                 dst[2] = (value >> 16) & 0xff;
133         case 2:
134                 dst[1] = (value >> 8) & 0xff;
135         case 1:
136                 dst[0] = value & 0xff;
137                 break;
138         default:
139                 return;
140                 break;
141         }
142
143         *offsetp += bytes_to_write;
144 }
145
146 static void
147 dwarf_write_msb(Elf_Data **dp, uint64_t *offsetp, uint64_t value, int bytes_to_write)
148 {
149         uint8_t *dst = (uint8_t *) (*dp)->d_buf + *offsetp;
150
151         switch (bytes_to_write) {
152         case 8:
153                 dst[7] = value & 0xff;
154                 dst[6] = (value >> 8) & 0xff;
155                 dst[5] = (value >> 16) & 0xff;
156                 dst[4] = (value >> 24) & 0xff;
157                 value >>= 32;
158         case 4:
159                 dst[3] = value & 0xff;
160                 dst[2] = (value >> 8) & 0xff;
161                 value >>= 16;
162         case 2:
163                 dst[1] = value & 0xff;
164                 value >>= 8;
165         case 1:
166                 dst[0] = value & 0xff;
167                 break;
168         default:
169                 return;
170                 break;
171         }
172
173         *offsetp += bytes_to_write;
174 }
175
176 static int64_t
177 dwarf_read_sleb128(Elf_Data **dp, uint64_t *offsetp)
178 {
179         int64_t ret = 0;
180         uint8_t b;
181         int shift = 0;
182
183         uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp;
184
185         do {
186                 b = *src++;
187
188                 ret |= ((b & 0x7f) << shift);
189
190                 (*offsetp)++;
191
192                 shift += 7;
193         } while ((b & 0x80) != 0);
194
195         if (shift < 32 && (b & 0x40) != 0)
196                 ret |= (-1 << shift);
197
198         return ret;
199 }
200
201 static uint64_t
202 dwarf_read_uleb128(Elf_Data **dp, uint64_t *offsetp)
203 {
204         uint64_t ret = 0;
205         uint8_t b;
206         int shift = 0;
207
208         uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp;
209
210         do {
211                 b = *src++;
212
213                 ret |= ((b & 0x7f) << shift);
214
215                 (*offsetp)++;
216
217                 shift += 7;
218         } while ((b & 0x80) != 0);
219
220         return ret;
221 }
222
223 static const char *
224 dwarf_read_string(Elf_Data **dp, uint64_t *offsetp)
225 {
226         char *ret;
227
228         char *src = (char *) (*dp)->d_buf + *offsetp;
229
230         ret = src;
231
232         while (*src != '\0' && *offsetp < (*dp)->d_size) {
233                 src++;
234                 (*offsetp)++;
235         }
236
237         if (*src == '\0' && *offsetp < (*dp)->d_size)
238                 (*offsetp)++;
239
240         return ret;
241 }
242
243 static uint8_t *
244 dwarf_read_block(Elf_Data **dp, uint64_t *offsetp, uint64_t length)
245 {
246         uint8_t *ret;
247
248         uint8_t *src = (char *) (*dp)->d_buf + *offsetp;
249
250         ret = src;
251
252         (*offsetp) += length;
253
254         return ret;
255 }
256
257 static int
258 dwarf_apply_relocations(Dwarf_Debug dbg, Elf_Data *reld, int secindx)
259 {
260         Elf_Data *d;
261         GElf_Rela rela;
262         int indx = 0;
263         int ret = DWARF_E_NONE;
264         uint64_t offset;
265
266         /* Point to the data to be relocated: */
267         d = dbg->dbg_s[secindx].s_data;
268
269         /* Enter a loop to process each relocation addend: */
270         while (gelf_getrela(reld, indx++, &rela) != NULL) {
271                 GElf_Sym sym;
272                 Elf64_Xword symindx = ELF64_R_SYM(rela.r_info);
273
274                 if (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data, symindx, &sym) == NULL) {
275                         printf("Couldn't find symbol index %lu for relocation\n",(u_long) symindx);
276                         continue;
277                 }
278
279                 offset = rela.r_offset;
280
281                 dwarf_write(&d, &offset, rela.r_addend, dbg->dbg_offsize);
282         }
283
284         return ret;
285 }
286
287 static int
288 dwarf_relocate(Dwarf_Debug dbg, Dwarf_Error *error)
289 {
290         Elf_Scn *scn = NULL;
291         GElf_Shdr shdr;
292         int i;
293         int ret = DWARF_E_NONE;
294
295         /* Look for sections which relocate the debug sections. */
296         while ((scn = elf_nextscn(dbg->dbg_elf, scn)) != NULL) {
297                 if (gelf_getshdr(scn, &shdr) == NULL) {
298                         DWARF_SET_ELF_ERROR(error, elf_errno());
299                         return DWARF_E_ELF;
300                 }
301
302                 if (shdr.sh_type != SHT_RELA || shdr.sh_size == 0)
303                         continue;
304
305                 for (i = 0; i < DWARF_DEBUG_SNAMES; i++) {
306                         if (dbg->dbg_s[i].s_shnum == shdr.sh_info &&
307                             dbg->dbg_s[DWARF_symtab].s_shnum == shdr.sh_link) {
308                                 Elf_Data *rd;
309
310                                 /* Get the relocation data. */
311                                 if ((rd = elf_getdata(scn, NULL)) == NULL) {
312                                         DWARF_SET_ELF_ERROR(error, elf_errno());
313                                         return DWARF_E_ELF;
314                                 }
315
316                                 /* Apply the relocations. */
317                                 dwarf_apply_relocations(dbg, rd, i);
318                                 break;
319                         }
320                 }
321         }
322
323         return ret;
324 }
325
326 static int
327 dwarf_init_attr(Dwarf_Debug dbg, Elf_Data **dp, uint64_t *offsetp,
328     Dwarf_CU cu, Dwarf_Die die, Dwarf_Attribute at, uint64_t form,
329     Dwarf_Error *error)
330 {
331         int ret = DWARF_E_NONE;
332         struct _Dwarf_AttrValue avref;
333
334         memset(&avref, 0, sizeof(avref));
335         avref.av_attrib = at->at_attrib;
336         avref.av_form   = at->at_form;
337
338         switch (form) {
339         case DW_FORM_addr:
340                 avref.u[0].u64 = dwarf_read(dp, offsetp, cu->cu_pointer_size);
341                 break;
342         case DW_FORM_block:
343                 avref.u[0].u64 = dwarf_read_uleb128(dp, offsetp);
344                 avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64);
345                 break;
346         case DW_FORM_block1:
347                 avref.u[0].u64 = dwarf_read(dp, offsetp, 1);
348                 avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64);
349                 break;
350         case DW_FORM_block2:
351                 avref.u[0].u64 = dwarf_read(dp, offsetp, 2);
352                 avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64);
353                 break;
354         case DW_FORM_block4:
355                 avref.u[0].u64 = dwarf_read(dp, offsetp, 4);
356                 avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64);
357                 break;
358         case DW_FORM_data1:
359         case DW_FORM_flag:
360         case DW_FORM_ref1:
361                 avref.u[0].u64 = dwarf_read(dp, offsetp, 1);
362                 break;
363         case DW_FORM_data2:
364         case DW_FORM_ref2:
365                 avref.u[0].u64 = dwarf_read(dp, offsetp, 2);
366                 break;
367         case DW_FORM_data4:
368         case DW_FORM_ref4:
369                 avref.u[0].u64 = dwarf_read(dp, offsetp, 4);
370                 break;
371         case DW_FORM_data8:
372         case DW_FORM_ref8:
373                 avref.u[0].u64 = dwarf_read(dp, offsetp, 8);
374                 break;
375         case DW_FORM_indirect:
376                 form = dwarf_read_uleb128(dp, offsetp);
377                 return dwarf_init_attr(dbg, dp, offsetp, cu, die, at, form, error);
378         case DW_FORM_ref_addr:
379                 if (cu->cu_version == 2)
380                         avref.u[0].u64 = dwarf_read(dp, offsetp, cu->cu_pointer_size);
381                 else if (cu->cu_version == 3)
382                         avref.u[0].u64 = dwarf_read(dp, offsetp, dbg->dbg_offsize);
383                 break;
384         case DW_FORM_ref_udata:
385         case DW_FORM_udata:
386                 avref.u[0].u64 = dwarf_read_uleb128(dp, offsetp);
387                 break;
388         case DW_FORM_sdata:
389                 avref.u[0].s64 = dwarf_read_sleb128(dp, offsetp);
390                 break;
391         case DW_FORM_string:
392                 avref.u[0].s = dwarf_read_string(dp, offsetp);
393                 break;
394         case DW_FORM_strp:
395                 avref.u[0].u64 = dwarf_read(dp, offsetp, dbg->dbg_offsize);
396                 avref.u[1].s = elf_strptr(dbg->dbg_elf,
397                     dbg->dbg_s[DWARF_debug_str].s_shnum, avref.u[0].u64);
398                 break;
399         default:
400                 DWARF_SET_ERROR(error, DWARF_E_NOT_IMPLEMENTED);
401                 ret = DWARF_E_NOT_IMPLEMENTED;
402                 break;
403         }
404
405         if (ret == DWARF_E_NONE)
406                 ret = dwarf_attrval_add(die, &avref, NULL, error);
407
408         return ret;
409 }
410
411 static int
412 dwarf_init_abbrev(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Error *error)
413 {
414         Dwarf_Abbrev a;
415         Elf_Data *d;
416         int ret = DWARF_E_NONE;
417         uint64_t attr;
418         uint64_t entry;
419         uint64_t form;
420         uint64_t offset;
421         uint64_t tag;
422         u_int8_t children;
423
424         d = dbg->dbg_s[DWARF_debug_abbrev].s_data;
425
426         offset = cu->cu_abbrev_offset;
427
428         while (offset < d->d_size) {
429
430                 entry = dwarf_read_uleb128(&d, &offset);
431
432                 /* Check if this is the end of the data: */
433                 if (entry == 0)
434                         break;
435
436                 tag = dwarf_read_uleb128(&d, &offset);
437
438                 children = dwarf_read(&d, &offset, 1);
439
440                 if ((ret = dwarf_abbrev_add(cu, entry, tag, children, &a, error)) != DWARF_E_NONE)
441                         break;
442
443                 do {
444                         attr = dwarf_read_uleb128(&d, &offset);
445                         form = dwarf_read_uleb128(&d, &offset);
446
447                         if (attr != 0)
448                                 if ((ret = dwarf_attr_add(a, attr, form, NULL, error)) != DWARF_E_NONE)
449                                         return ret;
450                 } while (attr != 0);
451         }
452
453         return ret;
454 }
455
456 static int
457 dwarf_init_info(Dwarf_Debug dbg, Dwarf_Error *error)
458 {
459         Dwarf_CU cu;
460         Elf_Data *d = NULL;
461         Elf_Scn *scn;
462         int i;
463         int level = 0;
464         int relocated = 0;
465         int ret = DWARF_E_NONE;
466         uint64_t length;
467         uint64_t next_offset;
468         uint64_t offset = 0;
469
470         scn = dbg->dbg_s[DWARF_debug_info].s_scn;
471
472         d = dbg->dbg_s[DWARF_debug_info].s_data;
473
474         while (offset < d->d_size) {
475                 /* Allocate memory for the first compilation unit. */
476                 if ((cu = calloc(sizeof(struct _Dwarf_CU), 1)) == NULL) {
477                         DWARF_SET_ERROR(error, DWARF_E_MEMORY);
478                         return DWARF_E_MEMORY;
479                 }
480
481                 /* Save the offet to this compilation unit: */
482                 cu->cu_offset = offset;
483
484                 length = dwarf_read(&d, &offset, 4);
485                 if (length == 0xffffffff) {
486                         length = dwarf_read(&d, &offset, 8);
487                         dbg->dbg_offsize = 8;
488                 } else
489                         dbg->dbg_offsize = 4;
490
491                 /*
492                  * Check if there is enough ELF data for this CU.
493                  * This assumes that libelf gives us the entire
494                  * section in one Elf_Data object.
495                  */
496                 if (length > d->d_size - offset) {
497                         free(cu);
498                         DWARF_SET_ERROR(error, DWARF_E_INVALID_CU);
499                         return DWARF_E_INVALID_CU;
500                 }
501
502                 /* Relocate the DWARF sections if necessary: */
503                 if (!relocated) {
504                         if ((ret = dwarf_relocate(dbg, error)) != DWARF_E_NONE)
505                                 return ret;
506                         relocated = 1;
507                 }
508
509                 /* Compute the offset to the next compilation unit: */
510                 next_offset = offset + length;
511
512                 /* Initialise the compilation unit. */
513                 cu->cu_length           = length;
514                 cu->cu_header_length    = (dbg->dbg_offsize == 4) ? 4 : 12;
515                 cu->cu_version          = dwarf_read(&d, &offset, 2);
516                 cu->cu_abbrev_offset    = dwarf_read(&d, &offset, dbg->dbg_offsize);
517                 cu->cu_pointer_size     = dwarf_read(&d, &offset, 1);
518                 cu->cu_next_offset      = next_offset;
519
520                 /* Initialise the list of abbrevs. */
521                 STAILQ_INIT(&cu->cu_abbrev);
522
523                 /* Initialise the list of dies. */
524                 STAILQ_INIT(&cu->cu_die);
525
526                 /* Initialise the hash table of dies. */
527                 for (i = 0; i < DWARF_DIE_HASH_SIZE; i++)
528                         STAILQ_INIT(&cu->cu_die_hash[i]);
529
530                 /* Add the compilation unit to the list. */
531                 STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next);
532
533                 if (cu->cu_version != 2 && cu->cu_version != 3) {
534                         DWARF_SET_ERROR(error, DWARF_E_CU_VERSION);
535                         ret = DWARF_E_CU_VERSION;
536                         break;
537                 }
538
539                 /* Parse the .debug_abbrev info for this CU: */
540                 if ((ret = dwarf_init_abbrev(dbg, cu, error)) != DWARF_E_NONE)
541                         break;
542
543                 level = 0;
544
545                 while (offset < next_offset && offset < d->d_size) {
546                         Dwarf_Abbrev a;
547                         Dwarf_Attribute at;
548                         Dwarf_Die die;
549                         uint64_t abnum;
550                         uint64_t die_offset = offset;;
551
552                         abnum = dwarf_read_uleb128(&d, &offset);
553
554                         if (abnum == 0) {
555                                 level--;
556                                 continue;
557                         }
558
559                         if ((a = dwarf_abbrev_find(cu, abnum)) == NULL) {
560                                 DWARF_SET_ERROR(error, DWARF_E_MISSING_ABBREV);
561                                 return DWARF_E_MISSING_ABBREV;
562                         }
563
564                         if ((ret = dwarf_die_add(cu, level, die_offset,
565                             abnum, a, &die, error)) != DWARF_E_NONE)
566                                 return ret;
567
568                         STAILQ_FOREACH(at, &a->a_attrib, at_next) {
569                                 if ((ret = dwarf_init_attr(dbg, &d, &offset,
570                                     cu, die, at, at->at_form, error)) != DWARF_E_NONE)
571                                         return ret;
572                         }
573
574                         if (a->a_children == DW_CHILDREN_yes)
575                                 level++;
576                 }
577
578                 offset = next_offset;
579         }
580
581         return ret;
582 }
583
584 static int
585 dwarf_elf_read(Dwarf_Debug dbg, Dwarf_Error *error)
586 {
587         GElf_Shdr shdr;
588         Elf_Scn *scn = NULL;
589         char *sname;
590         int i;
591         int ret = DWARF_E_NONE;
592
593         /* Get a copy of the ELF header. */
594         if (gelf_getehdr(dbg->dbg_elf, &dbg->dbg_ehdr) == NULL) {
595                 DWARF_SET_ELF_ERROR(error, elf_errno());
596                 return DWARF_E_ELF;
597         }
598
599         /* Check the ELF data format: */
600         switch (dbg->dbg_ehdr.e_ident[EI_DATA]) {
601         case ELFDATA2MSB:
602                 dwarf_read = dwarf_read_msb;
603                 dwarf_write = dwarf_write_msb;
604                 break;
605
606         case ELFDATA2LSB:
607         case ELFDATANONE:
608         default:
609                 dwarf_read = dwarf_read_lsb;
610                 dwarf_write = dwarf_write_lsb;
611                 break;
612         }
613
614         /* Get the section index to the string table. */
615         if (elf_getshstrndx(dbg->dbg_elf, &dbg->dbg_stnum) == 0) {
616                 DWARF_SET_ELF_ERROR(error, elf_errno());
617                 return DWARF_E_ELF;
618         }
619
620         /* Look for the debug sections. */
621         while ((scn = elf_nextscn(dbg->dbg_elf, scn)) != NULL) {
622                 /* Get a copy of the section header: */
623                 if (gelf_getshdr(scn, &shdr) == NULL) {
624                         DWARF_SET_ELF_ERROR(error, elf_errno());
625                         return DWARF_E_ELF;
626                 }
627
628                 /* Get a pointer to the section name: */
629                 if ((sname = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, shdr.sh_name)) == NULL) {
630                         DWARF_SET_ELF_ERROR(error, elf_errno());
631                         return DWARF_E_ELF;
632                 }
633
634                 /*
635                  * Look up the section name to check if it's
636                  * one we need for DWARF.
637                  */
638                 for (i = 0; i < DWARF_DEBUG_SNAMES; i++) {
639                         if (strcmp(sname, debug_snames[i]) == 0) {
640                                 dbg->dbg_s[i].s_sname = sname;
641                                 dbg->dbg_s[i].s_shnum = elf_ndxscn(scn);
642                                 dbg->dbg_s[i].s_scn = scn;
643                                 memcpy(&dbg->dbg_s[i].s_shdr, &shdr, sizeof(shdr));
644                                 if ((dbg->dbg_s[i].s_data = elf_getdata(scn, NULL)) == NULL) {
645                                         DWARF_SET_ELF_ERROR(error, elf_errno());
646                                         return DWARF_E_ELF;
647                                 }
648                                 break;
649                         }
650                 }
651         }
652
653         /* Check if any of the required sections are missing: */
654         if (dbg->dbg_s[DWARF_debug_abbrev].s_scn == NULL ||
655             dbg->dbg_s[DWARF_debug_info].s_scn == NULL) {
656                 /* Missing debug information. */
657                 DWARF_SET_ERROR(error, DWARF_E_DEBUG_INFO);
658                 return DWARF_E_DEBUG_INFO;
659         }
660
661         /* Initialise the compilation-units: */
662         ret = dwarf_init_info(dbg, error);
663
664         return ret;
665 }
666
667 int
668 dwarf_elf_init(Elf *elf, int mode, Dwarf_Debug *ret_dbg, Dwarf_Error *error)
669 {
670         Dwarf_Debug dbg;
671         int ret = DWARF_E_NONE;
672
673         if (error == NULL)
674                 /* Can only return a generic error. */
675                 return DWARF_E_ERROR;
676
677         if (elf == NULL || ret_dbg == NULL) {
678                 DWARF_SET_ERROR(error, DWARF_E_ARGUMENT);
679                 ret = DWARF_E_ARGUMENT;
680         } else if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) {
681                 DWARF_SET_ERROR(error, DWARF_E_MEMORY);
682                 ret = DWARF_E_MEMORY;
683         } else {
684                 dbg->dbg_elf            = elf;
685                 dbg->dbg_elf_close      = 0;
686                 dbg->dbg_mode           = mode;
687
688                 STAILQ_INIT(&dbg->dbg_cu);
689
690                 *ret_dbg = dbg;
691
692                 /* Read the ELF sections. */
693                 ret = dwarf_elf_read(dbg, error);
694         }
695
696         return ret;
697 }
698
699 int
700 dwarf_init(int fd, int mode, Dwarf_Debug *ret_dbg, Dwarf_Error *error)
701 {
702         Dwarf_Error lerror;
703         Elf *elf;
704         Elf_Cmd c;
705         int ret;
706
707         if (error == NULL)
708                 /* Can only return a generic error. */
709                 return DWARF_E_ERROR;
710
711         if (fd < 0 || ret_dbg == NULL) {
712                 DWARF_SET_ERROR(error, DWARF_E_ARGUMENT);
713                 return DWARF_E_ERROR;
714         }
715
716         /* Translate the DWARF mode to ELF mode. */
717         switch (mode) {
718         default:
719         case DW_DLC_READ:
720                 c = ELF_C_READ;
721                 break;
722         }
723
724         if (elf_version(EV_CURRENT) == EV_NONE) {
725                 DWARF_SET_ELF_ERROR(error, elf_errno());
726                 return DWARF_E_ERROR;
727         }
728
729         if ((elf = elf_begin(fd, c, NULL)) == NULL) {
730                 DWARF_SET_ELF_ERROR(error, elf_errno());
731                 return DWARF_E_ERROR;
732         }
733
734         ret = dwarf_elf_init(elf, mode, ret_dbg, error);
735
736         if (*ret_dbg != NULL)
737                 /* Remember to close the ELF file. */
738                 (*ret_dbg)->dbg_elf_close = 1;
739
740         if (ret != DWARF_E_NONE) {
741                 if (*ret_dbg != NULL) {
742                         dwarf_finish(ret_dbg, &lerror);
743                 } else
744                         elf_end(elf);
745         }
746
747         return ret;
748 }