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 "_libdwarf.h"
31
32 int
dwarf_die_add(Dwarf_CU cu,int level,uint64_t offset,uint64_t abnum,Dwarf_Abbrev a,Dwarf_Die * diep,Dwarf_Error * err)33 dwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abbrev a, Dwarf_Die *diep, Dwarf_Error *err)
34 {
35 Dwarf_Die die;
36 uint64_t key;
37 int ret = DWARF_E_NONE;
38
39 if (err == NULL)
40 return DWARF_E_ERROR;
41
42 if (cu == NULL || a == NULL) {
43 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
44 return DWARF_E_ARGUMENT;
45 }
46
47 if ((die = malloc(sizeof(struct _Dwarf_Die))) == NULL) {
48 DWARF_SET_ERROR(err, DWARF_E_MEMORY);
49 return DWARF_E_MEMORY;
50 }
51
52 /* Initialise the abbrev structure. */
53 die->die_level = level;
54 die->die_offset = offset;
55 die->die_abnum = abnum;
56 die->die_a = a;
57 die->die_cu = cu;
58 die->die_name = "";
59
60 /* Initialise the list of attribute values. */
61 STAILQ_INIT(&die->die_attrval);
62
63 /* Add the die to the list in the compilation unit. */
64 STAILQ_INSERT_TAIL(&cu->cu_die, die, die_next);
65
66 /* Add the die to the hash table in the compilation unit. */
67 key = offset % DWARF_DIE_HASH_SIZE;
68 STAILQ_INSERT_TAIL(&cu->cu_die_hash[key], die, die_hash);
69
70 if (diep != NULL)
71 *diep = die;
72
73 return ret;
74 }
75
76 int
dwarf_dieoffset(Dwarf_Die die,Dwarf_Off * ret_offset,Dwarf_Error * err __unused)77 dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *err __unused)
78 {
79 *ret_offset = die->die_offset;
80
81 return DWARF_E_NONE;
82 }
83
84 int
dwarf_child(Dwarf_Die die,Dwarf_Die * ret_die,Dwarf_Error * err)85 dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *err)
86 {
87 Dwarf_Die next;
88 int ret = DWARF_E_NONE;
89
90 if (err == NULL)
91 return DWARF_E_ERROR;
92
93 if (die == NULL || ret_die == NULL) {
94 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
95 return DWARF_E_ARGUMENT;
96 }
97
98 if ((next = STAILQ_NEXT(die, die_next)) == NULL ||
99 next->die_level != die->die_level + 1) {
100 *ret_die = NULL;
101 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
102 ret = DWARF_E_NO_ENTRY;
103 } else
104 *ret_die = next;
105
106 return ret;
107 }
108
109 int
dwarf_tag(Dwarf_Die die,Dwarf_Half * tag,Dwarf_Error * err)110 dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *err)
111 {
112 Dwarf_Abbrev a;
113
114 if (err == NULL)
115 return DWARF_E_ERROR;
116
117 if (die == NULL || tag == NULL || (a = die->die_a) == NULL) {
118 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
119 return DWARF_E_ARGUMENT;
120 }
121
122 *tag = a->a_tag;
123
124 return DWARF_E_NONE;
125 }
126
127 int
dwarf_siblingof(Dwarf_Debug dbg,Dwarf_Die die,Dwarf_Die * caller_ret_die,Dwarf_Error * err)128 dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *caller_ret_die, Dwarf_Error *err)
129 {
130 Dwarf_Die next;
131 Dwarf_CU cu;
132 int ret = DWARF_E_NONE;
133
134 if (err == NULL)
135 return DWARF_E_ERROR;
136
137 if (dbg == NULL || caller_ret_die == NULL) {
138 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
139 return DWARF_E_ARGUMENT;
140 }
141
142 if ((cu = dbg->dbg_cu_current) == NULL) {
143 DWARF_SET_ERROR(err, DWARF_E_CU_CURRENT);
144 return DWARF_E_CU_CURRENT;
145 }
146
147 if (die == NULL) {
148 *caller_ret_die = STAILQ_FIRST(&cu->cu_die);
149
150 if (*caller_ret_die == NULL) {
151 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
152 ret = DWARF_E_NO_ENTRY;
153 }
154 } else {
155 next = die;
156 while ((next = STAILQ_NEXT(next, die_next)) != NULL) {
157 if (next->die_level < die->die_level) {
158 next = NULL;
159 break;
160 }
161 if (next->die_level == die->die_level) {
162 *caller_ret_die = next;
163 break;
164 }
165 }
166
167 if (next == NULL) {
168 *caller_ret_die = NULL;
169 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
170 ret = DWARF_E_NO_ENTRY;
171 }
172 }
173
174 return ret;
175 }
176
177 Dwarf_Die
dwarf_die_find(Dwarf_Die die,Dwarf_Unsigned off)178 dwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off)
179 {
180 Dwarf_CU cu = die->die_cu;
181 Dwarf_Die die1;
182
183 STAILQ_FOREACH(die1, &cu->cu_die, die_next) {
184 if (die1->die_offset == off)
185 return (die1);
186 }
187
188 return (NULL);
189 }
190