xref: /freebsd/contrib/elftoolchain/libdwarf/dwarf_attrval.c (revision 3a92d97ff0f22d21608e1c19b83104c4937523b6)
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 
27 #include "_libdwarf.h"
28 
29 ELFTC_VCSID("$Id: dwarf_attrval.c 2072 2011-10-27 03:26:49Z jkoshy $");
30 
31 int
32 dwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
33 {
34 	Dwarf_Attribute at;
35 	Dwarf_Debug dbg;
36 
37 	dbg = die != NULL ? die->die_dbg : NULL;
38 
39 	if (die == NULL || valp == NULL) {
40 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
41 		return (DW_DLV_ERROR);
42 	}
43 
44 	*valp = 0;
45 
46 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
47 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
48 		return (DW_DLV_NO_ENTRY);
49 	}
50 
51 	switch (at->at_form) {
52 	case DW_FORM_flag:
53 	case DW_FORM_flag_present:
54 		*valp = (Dwarf_Bool) (!!at->u[0].u64);
55 		break;
56 	default:
57 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
58 		return (DW_DLV_ERROR);
59 	}
60 
61 	return (DW_DLV_OK);
62 }
63 
64 int
65 dwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
66 {
67 	Dwarf_Attribute at;
68 	Dwarf_Debug dbg;
69 
70 	dbg = die != NULL ? die->die_dbg : NULL;
71 
72 	if (die == NULL || strp == NULL) {
73 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
74 		return (DW_DLV_ERROR);
75 	}
76 
77 	*strp = NULL;
78 
79 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
80 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
81 		return (DW_DLV_NO_ENTRY);
82 	}
83 
84 	switch (at->at_form) {
85 	case DW_FORM_strp:
86 		*strp = at->u[1].s;
87 		break;
88 	case DW_FORM_string:
89 		*strp = at->u[0].s;
90 		break;
91 	default:
92 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
93 		return (DW_DLV_ERROR);
94 	}
95 
96 	return (DW_DLV_OK);
97 }
98 
99 int
100 dwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
101 {
102 	Dwarf_Attribute at;
103 	Dwarf_Debug dbg;
104 
105 	dbg = die != NULL ? die->die_dbg : NULL;
106 
107 	if (die == NULL || valp == NULL) {
108 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
109 		return (DW_DLV_ERROR);
110 	}
111 
112 	*valp = 0;
113 
114 	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
115 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
116 		return (DW_DLV_NO_ENTRY);
117 	}
118 
119 	switch (at->at_form) {
120 	case DW_FORM_data1:
121 		*valp = (int8_t) at->u[0].s64;
122 		break;
123 	case DW_FORM_data2:
124 		*valp = (int16_t) at->u[0].s64;
125 		break;
126 	case DW_FORM_data4:
127 		*valp = (int32_t) at->u[0].s64;
128 	case DW_FORM_data8:
129 	case DW_FORM_sdata:
130 		*valp = at->u[0].s64;
131 		break;
132 	default:
133 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
134 		return (DW_DLV_ERROR);
135 	}
136 
137 	return (DW_DLV_OK);
138 }
139 
140 int
141 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
142 {
143 	Dwarf_Attribute at;
144 	Dwarf_Die die1;
145 	Dwarf_Unsigned val;
146 	Dwarf_Debug dbg;
147 
148 	dbg = die != NULL ? die->die_dbg : NULL;
149 
150 	if (die == NULL || valp == NULL) {
151 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
152 		return (DW_DLV_ERROR);
153 	}
154 
155 	*valp = 0;
156 
157 	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
158 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
159 		return (DW_DLV_NO_ENTRY);
160 	}
161 
162 	die1 = NULL;
163 	if (at == NULL &&
164 	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
165 		switch (at->at_form) {
166 		case DW_FORM_ref1:
167 		case DW_FORM_ref2:
168 		case DW_FORM_ref4:
169 		case DW_FORM_ref8:
170 		case DW_FORM_ref_udata:
171 			val = at->u[0].u64;
172 			if ((die1 = _dwarf_die_find(die, val)) == NULL ||
173 			    (at = _dwarf_attr_find(die1, attr)) == NULL) {
174 				if (die1 != NULL)
175 					dwarf_dealloc(dbg, die1, DW_DLA_DIE);
176 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
177 				return (DW_DLV_NO_ENTRY);
178 			}
179 			break;
180 		default:
181 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
182 			return (DW_DLV_ERROR);
183 		}
184 	}
185 
186 	switch (at->at_form) {
187 	case DW_FORM_addr:
188 	case DW_FORM_data1:
189 	case DW_FORM_data2:
190 	case DW_FORM_data4:
191 	case DW_FORM_data8:
192 	case DW_FORM_udata:
193 	case DW_FORM_ref1:
194 	case DW_FORM_ref2:
195 	case DW_FORM_ref4:
196 	case DW_FORM_ref8:
197 	case DW_FORM_ref_udata:
198 		*valp = at->u[0].u64;
199 		break;
200 	default:
201 		if (die1 != NULL)
202 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
203 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
204 		return (DW_DLV_ERROR);
205 	}
206 
207 	if (die1 != NULL)
208 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
209 
210 	return (DW_DLV_OK);
211 }
212