xref: /trueos/lib/libdwarf/dwarf_die.c (revision 2d50e830b3e79fa42f303add8a99872897abdc2a)
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