blob: 2e94d2ea844a8734fa6dec84d7a50ea3b8522c21 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return die at given offset.
2 Copyright (C) 2000, 2002 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4
5 This program is Open Source software; you can redistribute it and/or
6 modify it under the terms of the Open Software License version 1.0 as
7 published by the Open Source Initiative.
8
9 You should have received a copy of the Open Software License along
10 with this program; if not, you may obtain a copy of the Open Software
11 License version 1.0 from http://www.opensource.org/licenses/osl.php or
12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13 3001 King Ranch Road, Ukiah, CA 95482. */
14
15#ifdef HAVE_CONFIG_H
16# include <config.h>
17#endif
18
19#include <dwarf.h>
20#include <stdlib.h>
21
22#include <libdwarfP.h>
23
24
25/* XXX This function will have to be optimized. The search is too linear
26 to be performed too often -> O(n²). */
27static Dwarf_CU_Info
28find_cu (Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Error *error)
29{
30 Dwarf_CU_Info cu;
31 Dwarf_Word cu_offset;
32
33 /* Search in the CUs already known. */
34 for (cu = dbg->cu_list; cu != NULL; cu = cu->next)
35 if (cu->offset <= offset
36 && cu->offset + 2 * cu->offset_size - 4 + cu->length > offset)
37 return cu;
38
39 /* The CU is not yet loaded. Do this now. */
40 if (dbg->cu_list_tail == NULL)
41 cu_offset = 0;
42 else
43 cu_offset = (dbg->cu_list_tail->offset
44 + 2 * dbg->cu_list_tail->offset_size - 4
45 + dbg->cu_list_tail->length);
46
47 while (1)
48 {
49 /* Get next CU and add it to the end of the list. */
50 if (__libdwarf_get_cu_at_offset (dbg, cu_offset, &cu, error)
51 != DW_DLV_OK)
52 return NULL;
53
54 /* Offset of next CU. */
55 cu_offset += 2 * cu->offset_size - 4 + cu->length;
56
57 /* If this the CU we are looking for? */
58 if (offset < cu_offset)
59 return cu;
60 }
61}
62
63
64int
65dwarf_offdie (dbg, offset, return_die, error)
66 Dwarf_Debug dbg;
67 Dwarf_Off offset;
68 Dwarf_Die *return_die;
69 Dwarf_Error *error;
70{
71 Dwarf_CU_Info cu;
72 Dwarf_Die new_die;
73 Dwarf_Small *die_addr;
74 Dwarf_Word u128;
75
76 if (offset >= dbg->sections[IDX_debug_info].size)
77 {
78 /* Completely out of bounds. */
79 __libdwarf_error (dbg, error, DW_E_INVALID_OFFSET);
80 return DW_DLV_ERROR;
81 }
82
83 /* Find the compile unit this address belongs to. */
84 cu = find_cu (dbg, offset, error);
85 if (cu == NULL)
86 return DW_DLV_ERROR;
87
88 /* Creata a new die. */
89 new_die = (Dwarf_Die) malloc (sizeof (struct Dwarf_Die_s));
90 if (new_die == NULL)
91 {
92 __libdwarf_error (dbg, error, DW_E_NOMEM);
93 return DW_DLV_ERROR;
94 }
95
96#ifdef DWARF_DEBUG
97 new_die->memtag = DW_DLA_DIE;
98#endif
99
100 /* Remember the address. */
101 die_addr = (Dwarf_Small *) dbg->sections[IDX_debug_info].addr + offset;
102 new_die->addr = die_addr;
103
104 /* And the compile unit. */
105 new_die->cu = cu;
106
107 /* 7.5.2 Debugging Information Entry
108
109 Each debugging information entry begins with an unsigned LEB128
110 number containing the abbreviation code for the entry. */
111 get_uleb128 (u128, die_addr);
112
113 /* Find the abbreviation. */
114 new_die->abbrev = __libdwarf_get_abbrev (dbg, cu, u128, error);
115 if (new_die->abbrev == NULL)
116 {
117 free (new_die);
118 return DW_DLV_ERROR;
119 }
120
121 *return_die = new_die;
122 return DW_DLV_OK;
123}