]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libdwarf/dwarf_attrval.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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                         *valp = (Dwarf_Bool) av->u[0].u64;
105                         break;
106                 default:
107                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
108                             __func__,__LINE__,get_form_desc(av->av_form),
109                             (u_long) av->av_form);
110                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
111                         ret = DWARF_E_BAD_FORM;
112                 }
113         }
114
115         return ret;
116 }
117
118 int
119 dwarf_attrval_string(Dwarf_Die die, uint64_t attr, const char **strp, Dwarf_Error *err)
120 {
121         Dwarf_AttrValue av;
122         int ret = DWARF_E_NONE;
123
124         if (err == NULL)
125                 return DWARF_E_ERROR;
126
127         if (die == NULL || strp == NULL) {
128                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
129                 return DWARF_E_ARGUMENT;
130         }
131
132         *strp = NULL;
133
134         if (attr == DW_AT_name)
135                 *strp = die->die_name;
136         else if ((av = dwarf_attrval_find(die, attr)) == NULL) {
137                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
138                 ret = DWARF_E_NO_ENTRY;
139         } else {
140                 switch (av->av_form) {
141                 case DW_FORM_strp:
142                         *strp = av->u[1].s;
143                         break;
144                 case DW_FORM_string:
145                         *strp = av->u[0].s;
146                         break;
147                 default:
148                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
149                             __func__,__LINE__,get_form_desc(av->av_form),
150                             (u_long) av->av_form);
151                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
152                         ret = DWARF_E_BAD_FORM;
153                 }
154         }
155
156         return ret;
157 }
158
159 int
160 dwarf_attrval_signed(Dwarf_Die die, uint64_t attr, Dwarf_Signed *valp, Dwarf_Error *err)
161 {
162         Dwarf_AttrValue av;
163         int ret = DWARF_E_NONE;
164
165         if (err == NULL)
166                 return DWARF_E_ERROR;
167
168         if (die == NULL || valp == NULL) {
169                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
170                 return DWARF_E_ARGUMENT;
171         }
172
173         *valp = 0;
174
175         if ((av = dwarf_attrval_find(die, attr)) == NULL) {
176                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
177                 ret = DWARF_E_NO_ENTRY;
178         } else {
179                 switch (av->av_form) {
180                 case DW_FORM_data1:
181                 case DW_FORM_sdata:
182                         *valp = av->u[0].s64;
183                         break;
184                 default:
185                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
186                             __func__,__LINE__,get_form_desc(av->av_form),
187                             (u_long) av->av_form);
188                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
189                         ret = DWARF_E_BAD_FORM;
190                 }
191         }
192
193         return ret;
194 }
195
196 int
197 dwarf_attrval_unsigned(Dwarf_Die die, uint64_t attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
198 {
199         Dwarf_AttrValue av;
200         int ret = DWARF_E_NONE;
201
202         if (err == NULL)
203                 return DWARF_E_ERROR;
204
205         if (die == NULL || valp == NULL) {
206                 DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
207                 return DWARF_E_ARGUMENT;
208         }
209
210         *valp = 0;
211
212         if ((av = dwarf_attrval_find(die, attr)) == NULL && attr != DW_AT_type) {
213                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
214                 ret = DWARF_E_NO_ENTRY;
215         } else if (av == NULL && (av = dwarf_attrval_find(die,
216             DW_AT_abstract_origin)) != NULL) {
217                 Dwarf_Die die1;
218                 Dwarf_Unsigned val;
219
220                 switch (av->av_form) {
221                 case DW_FORM_data1:
222                 case DW_FORM_data2:
223                 case DW_FORM_data4:
224                 case DW_FORM_data8:
225                 case DW_FORM_ref1:
226                 case DW_FORM_ref2:
227                 case DW_FORM_ref4:
228                 case DW_FORM_ref8:
229                 case DW_FORM_ref_udata:
230                         val = av->u[0].u64;
231
232                         if ((die1 = dwarf_die_find(die, val)) == NULL ||
233                             (av = dwarf_attrval_find(die1, attr)) == NULL) {
234                                 DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
235                                 ret = DWARF_E_NO_ENTRY;
236                         }
237                         break;
238                 default:
239                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
240                             __func__,__LINE__,get_form_desc(av->av_form),
241                             (u_long) av->av_form);
242                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
243                         ret = DWARF_E_BAD_FORM;
244                 }
245         }
246
247         if (ret == DWARF_E_NONE) {
248                 switch (av->av_form) {
249                 case DW_FORM_data1:
250                 case DW_FORM_data2:
251                 case DW_FORM_data4:
252                 case DW_FORM_data8:
253                 case DW_FORM_ref1:
254                 case DW_FORM_ref2:
255                 case DW_FORM_ref4:
256                 case DW_FORM_ref8:
257                 case DW_FORM_ref_udata:
258                         *valp = av->u[0].u64;
259                         break;
260                 default:
261                         printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n",
262                             __func__,__LINE__,get_form_desc(av->av_form),
263                             (u_long) av->av_form);
264                         DWARF_SET_ERROR(err, DWARF_E_BAD_FORM);
265                         ret = DWARF_E_BAD_FORM;
266                 }
267         }
268
269         return ret;
270 }