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