xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/dwarf_attrval.c (revision 6cf6fe02a981b55727c49c3d37b0d8191a98c0ee)
1 /*	$NetBSD: dwarf_attrval.c,v 1.2 2014/03/09 16:58:03 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include "_libdwarf.h"
30 
31 __RCSID("$NetBSD: dwarf_attrval.c,v 1.2 2014/03/09 16:58:03 christos Exp $");
32 ELFTC_VCSID("Id: dwarf_attrval.c 2072 2011-10-27 03:26:49Z jkoshy ");
33 
34 int
35 dwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
36 {
37 	Dwarf_Attribute at;
38 	Dwarf_Debug dbg;
39 
40 	dbg = die != NULL ? die->die_dbg : NULL;
41 
42 	if (die == NULL || valp == NULL) {
43 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
44 		return (DW_DLV_ERROR);
45 	}
46 
47 	*valp = 0;
48 
49 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
50 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
51 		return (DW_DLV_NO_ENTRY);
52 	}
53 
54 	switch (at->at_form) {
55 	case DW_FORM_flag:
56 	case DW_FORM_flag_present:
57 		*valp = (Dwarf_Bool) (!!at->u[0].u64);
58 		break;
59 	default:
60 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
61 		return (DW_DLV_ERROR);
62 	}
63 
64 	return (DW_DLV_OK);
65 }
66 
67 int
68 dwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
69 {
70 	Dwarf_Attribute at;
71 	Dwarf_Debug dbg;
72 
73 	dbg = die != NULL ? die->die_dbg : NULL;
74 
75 	if (die == NULL || strp == NULL) {
76 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
77 		return (DW_DLV_ERROR);
78 	}
79 
80 	*strp = NULL;
81 
82 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
83 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
84 		return (DW_DLV_NO_ENTRY);
85 	}
86 
87 	switch (at->at_form) {
88 	case DW_FORM_strp:
89 		*strp = at->u[1].s;
90 		break;
91 	case DW_FORM_string:
92 		*strp = at->u[0].s;
93 		break;
94 	default:
95 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
96 		return (DW_DLV_ERROR);
97 	}
98 
99 	return (DW_DLV_OK);
100 }
101 
102 int
103 dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
104 {
105 	Dwarf_Attribute at;
106 	Dwarf_Debug dbg;
107 
108 	dbg = die != NULL ? die->die_dbg : NULL;
109 
110 	if (die == NULL || valp == NULL) {
111 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
112 		return (DW_DLV_ERROR);
113 	}
114 
115 	*valp = 0;
116 
117 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
118 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
119 		return (DW_DLV_NO_ENTRY);
120 	}
121 
122 	switch (at->at_form) {
123 	case DW_FORM_data1:
124 		*valp = (int8_t) at->u[0].s64;
125 		break;
126 	case DW_FORM_data2:
127 		*valp = (int16_t) at->u[0].s64;
128 		break;
129 	case DW_FORM_data4:
130 		*valp = (int32_t) at->u[0].s64;
131 	case DW_FORM_data8:
132 	case DW_FORM_sdata:
133 		*valp = at->u[0].s64;
134 		break;
135 	default:
136 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
137 		return (DW_DLV_ERROR);
138 	}
139 
140 	return (DW_DLV_OK);
141 }
142 
143 int
144 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
145 {
146 	Dwarf_Attribute at;
147 	Dwarf_Die die1;
148 	Dwarf_Unsigned val;
149 	Dwarf_Debug dbg;
150 
151 	dbg = die != NULL ? die->die_dbg : NULL;
152 
153 	if (die == NULL || valp == NULL) {
154 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
155 		return (DW_DLV_ERROR);
156 	}
157 
158 	*valp = 0;
159 
160 	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
161 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
162 		return (DW_DLV_NO_ENTRY);
163 	}
164 
165 	die1 = NULL;
166 	if (at == NULL &&
167 	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
168 		switch (at->at_form) {
169 		case DW_FORM_ref1:
170 		case DW_FORM_ref2:
171 		case DW_FORM_ref4:
172 		case DW_FORM_ref8:
173 		case DW_FORM_ref_udata:
174 			val = at->u[0].u64;
175 			if ((die1 = _dwarf_die_find(die, val)) == NULL ||
176 			    (at = _dwarf_attr_find(die1, attr)) == NULL) {
177 				if (die1 != NULL)
178 					dwarf_dealloc(dbg, die1, DW_DLA_DIE);
179 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
180 				return (DW_DLV_NO_ENTRY);
181 			}
182 			break;
183 		default:
184 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
185 			return (DW_DLV_ERROR);
186 		}
187 	}
188 
189 	switch (at->at_form) {
190 	case DW_FORM_addr:
191 	case DW_FORM_data1:
192 	case DW_FORM_data2:
193 	case DW_FORM_data4:
194 	case DW_FORM_data8:
195 	case DW_FORM_udata:
196 	case DW_FORM_ref1:
197 	case DW_FORM_ref2:
198 	case DW_FORM_ref4:
199 	case DW_FORM_ref8:
200 	case DW_FORM_ref_udata:
201 		*valp = at->u[0].u64;
202 		break;
203 	default:
204 		if (die1 != NULL)
205 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
206 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
207 		return (DW_DLV_ERROR);
208 	}
209 
210 	if (die1 != NULL)
211 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
212 
213 	return (DW_DLV_OK);
214 }
215