]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - lib/libdwarf/dwarf_attrval.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / lib / libdwarf / dwarf_attrval.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 <string.h>
31 #include <unistd.h>
32 #include "_libdwarf.h"
33
34 Dwarf_AttrValue
35 dwarf_attrval_find(Dwarf_Die die, Dwarf_Half attr)
36 {
37         Dwarf_AttrValue av;
38
39         STAILQ_FOREACH(av, &die->die_attrval, av_next) {
40                 if (av->av_attrib == attr)
41                         break;
42         }
43
44         return av;
45 }
46
47 int
48 dwarf_attrval_add(Dwarf_Die die, Dwarf_AttrValue avref, Dwarf_AttrValue *avp, Dwarf_Error *error)
49 {
50         Dwarf_AttrValue av;
51         int ret = DWARF_E_NONE;
52
53         if ((av = malloc(sizeof(struct _Dwarf_AttrValue))) == NULL) {
54                 DWARF_SET_ERROR(error, DWARF_E_MEMORY);
55                 return DWARF_E_MEMORY;
56         }
57
58         memcpy(av, avref, sizeof(struct _Dwarf_AttrValue));
59
60         /* Add the attribute value to the list in the die. */
61         STAILQ_INSERT_TAIL(&die->die_attrval, av, av_next);
62
63         /* Save a pointer to the attribute name if this is one. */
64         if (av->av_attrib == DW_AT_name)
65                 switch (av->av_form) {
66                 case DW_FORM_strp:
67                         die->die_name = av->u[1].s;
68                         break;
69                 case DW_FORM_string:
70                         die->die_name = av->u[0].s;
71                         break;
72                 default:
73                         break;
74                 }
75
76         if (avp != NULL)
77                 *avp = av;
78
79         return ret;
80 }
81
82 int
83 dwarf_attrval_flag(Dwarf_Die die, uint64_t attr, Dwarf_Bool *valp, Dwarf_Error *err)
84 {
85         Dwarf_AttrValue av;
86         int ret = DWARF_E_NONE;
87
88         if (err == NULL)
89                 return DWARF_E_ERROR;
90
91         if (die == NULL || valp == NULL) {
92                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
93                 return DWARF_E_ARGUMENT;
94         }
95
96         *valp = 0;
97
98         if ((av = dwarf_attrval_find(die, attr)) == NULL) {
99                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
100                 ret = DWARF_E_NO_ENTRY;
101         } else {
102                 switch (av->av_form) {
103                 case DW_FORM_flag:
104                 case DW_FORM_flag_present:
105                         *valp = (Dwarf_Bool) av->u[0].u64;
106                         break;
107                 default:
108                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
109                             __func__,__LINE__,get_form_desc(av->av_form),
110                             (u_long) av->av_form);
111                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
112                         ret = DWARF_E_BAD_FORM;
113                 }
114         }
115
116         return ret;
117 }
118
119 int
120 dwarf_attrval_string(Dwarf_Die die, uint64_t attr, const char **strp, Dwarf_Error *err)
121 {
122         Dwarf_AttrValue av;
123         int ret = DWARF_E_NONE;
124
125         if (err == NULL)
126                 return DWARF_E_ERROR;
127
128         if (die == NULL || strp == NULL) {
129                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
130                 return DWARF_E_ARGUMENT;
131         }
132
133         *strp = NULL;
134
135         if (attr == DW_AT_name)
136                 *strp = die->die_name;
137         else if ((av = dwarf_attrval_find(die, attr)) == NULL) {
138                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
139                 ret = DWARF_E_NO_ENTRY;
140         } else {
141                 switch (av->av_form) {
142                 case DW_FORM_strp:
143                         *strp = av->u[1].s;
144                         break;
145                 case DW_FORM_string:
146                         *strp = av->u[0].s;
147                         break;
148                 default:
149                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
150                             __func__,__LINE__,get_form_desc(av->av_form),
151                             (u_long) av->av_form);
152                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
153                         ret = DWARF_E_BAD_FORM;
154                 }
155         }
156
157         return ret;
158 }
159
160 int
161 dwarf_attrval_signed(Dwarf_Die die, uint64_t attr, Dwarf_Signed *valp, Dwarf_Error *err)
162 {
163         Dwarf_AttrValue av;
164         int ret = DWARF_E_NONE;
165
166         if (err == NULL)
167                 return DWARF_E_ERROR;
168
169         if (die == NULL || valp == NULL) {
170                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
171                 return DWARF_E_ARGUMENT;
172         }
173
174         *valp = 0;
175
176         if ((av = dwarf_attrval_find(die, attr)) == NULL) {
177                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
178                 ret = DWARF_E_NO_ENTRY;
179         } else {
180                 switch (av->av_form) {
181                 case DW_FORM_data1:
182                 case DW_FORM_sdata:
183                         *valp = av->u[0].s64;
184                         break;
185                 default:
186                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
187                             __func__,__LINE__,get_form_desc(av->av_form),
188                             (u_long) av->av_form);
189                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
190                         ret = DWARF_E_BAD_FORM;
191                 }
192         }
193
194         return ret;
195 }
196
197 int
198 dwarf_attrval_unsigned(Dwarf_Die die, uint64_t attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
199 {
200         Dwarf_AttrValue av;
201         int ret = DWARF_E_NONE;
202
203         if (err == NULL)
204                 return DWARF_E_ERROR;
205
206         if (die == NULL || valp == NULL) {
207                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
208                 return DWARF_E_ARGUMENT;
209         }
210
211         *valp = 0;
212
213         if ((av = dwarf_attrval_find(die, attr)) == NULL && attr != DW_AT_type) {
214                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
215                 ret = DWARF_E_NO_ENTRY;
216         } else if (av == NULL && (av = dwarf_attrval_find(die,
217             DW_AT_abstract_origin)) != NULL) {
218                 Dwarf_Die die1;
219                 Dwarf_Unsigned val;
220
221                 switch (av->av_form) {
222                 case DW_FORM_data1:
223                 case DW_FORM_data2:
224                 case DW_FORM_data4:
225                 case DW_FORM_data8:
226                 case DW_FORM_ref1:
227                 case DW_FORM_ref2:
228                 case DW_FORM_ref4:
229                 case DW_FORM_ref8:
230                 case DW_FORM_ref_udata:
231                         val = av->u[0].u64;
232
233                         if ((die1 = dwarf_die_find(die, val)) == NULL ||
234                             (av = dwarf_attrval_find(die1, attr)) == NULL) {
235                                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
236                                 ret = DWARF_E_NO_ENTRY;
237                         }
238                         break;
239                 default:
240                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
241                             __func__,__LINE__,get_form_desc(av->av_form),
242                             (u_long) av->av_form);
243                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
244                         ret = DWARF_E_BAD_FORM;
245                 }
246         }
247
248         if (ret == DWARF_E_NONE) {
249                 switch (av->av_form) {
250                 case DW_FORM_data1:
251                 case DW_FORM_data2:
252                 case DW_FORM_data4:
253                 case DW_FORM_data8:
254                 case DW_FORM_ref1:
255                 case DW_FORM_ref2:
256                 case DW_FORM_ref4:
257                 case DW_FORM_ref8:
258                 case DW_FORM_ref_udata:
259                         *valp = av->u[0].u64;
260                         break;
261                 default:
262                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
263                             __func__,__LINE__,get_form_desc(av->av_form),
264                             (u_long) av->av_form);
265                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
266                         ret = DWARF_E_BAD_FORM;
267                 }
268         }
269
270         return ret;
271 }