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 3509 2016-12-29 03:58:41Z emaste $");
30 
31 int
dwarf_attrval_flag(Dwarf_Die die,Dwarf_Half attr,Dwarf_Bool * valp,Dwarf_Error * err)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
dwarf_attrval_string(Dwarf_Die die,Dwarf_Half attr,const char ** strp,Dwarf_Error * err)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
dwarf_attrval_signed(Dwarf_Die die,Dwarf_Half attr,Dwarf_Signed * valp,Dwarf_Error * err)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 		break;
129 	case DW_FORM_data8:
130 	case DW_FORM_sdata:
131 		*valp = at->u[0].s64;
132 		break;
133 	default:
134 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
135 		return (DW_DLV_ERROR);
136 	}
137 
138 	return (DW_DLV_OK);
139 }
140 
141 int
dwarf_attrval_unsigned(Dwarf_Die die,Dwarf_Half attr,Dwarf_Unsigned * valp,Dwarf_Error * err)142 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
143 {
144 	Dwarf_Attribute at;
145 	Dwarf_Die die1;
146 	Dwarf_Unsigned val;
147 	Dwarf_Debug dbg;
148 	int first;
149 
150 	dbg = die != NULL ? die->die_dbg : NULL;
151 
152 	if (die == NULL || valp == NULL) {
153 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
154 		return (DW_DLV_ERROR);
155 	}
156 
157 	*valp = 0;
158 
159 	die1 = NULL;
160 	for (;;) {
161 		if ((at = _dwarf_attr_find(die, attr)) != NULL ||
162 		    attr != DW_AT_type)
163 			break;
164 		if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
165 		    NULL &&
166 		    (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
167 			break;
168 
169 		switch (at->at_form) {
170 		case DW_FORM_ref1:
171 		case DW_FORM_ref2:
172 		case DW_FORM_ref4:
173 		case DW_FORM_ref8:
174 		case DW_FORM_ref_udata:
175 			val = at->u[0].u64;
176 			first = (die1 == NULL);
177 			die1 = _dwarf_die_find(die, val);
178 			if (!first)
179 				dwarf_dealloc(dbg, die, DW_DLA_DIE);
180 			if (die1 == NULL) {
181 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
182 				return (DW_DLV_NO_ENTRY);
183 			}
184 			die = die1;
185 			break;
186 		default:
187 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
188 			return (DW_DLV_ERROR);
189 		}
190 	}
191 
192 	if (at == NULL) {
193 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
194 		return (DW_DLV_NO_ENTRY);
195 	}
196 
197 	switch (at->at_form) {
198 	case DW_FORM_addr:
199 	case DW_FORM_data1:
200 	case DW_FORM_data2:
201 	case DW_FORM_data4:
202 	case DW_FORM_data8:
203 	case DW_FORM_udata:
204 	case DW_FORM_ref1:
205 	case DW_FORM_ref2:
206 	case DW_FORM_ref4:
207 	case DW_FORM_ref8:
208 	case DW_FORM_ref_udata:
209 		*valp = at->u[0].u64;
210 		break;
211 	default:
212 		if (die1 != NULL)
213 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
214 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
215 		return (DW_DLV_ERROR);
216 	}
217 
218 	if (die1 != NULL)
219 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
220 
221 	return (DW_DLV_OK);
222 }
223