]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - lib/libdwarf/dwarf_die.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 int
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
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
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
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
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
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 }