1 /*	$NetBSD: dwarf_attrval.c,v 1.3 2015/01/14 09:29:27 martin 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.3 2015/01/14 09:29:27 martin Exp $");
32 ELFTC_VCSID("Id: dwarf_attrval.c 2072 2011-10-27 03:26:49Z jkoshy ");
33 
34 int
dwarf_attrval_flag(Dwarf_Die die,Dwarf_Half attr,Dwarf_Bool * valp,Dwarf_Error * err)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
dwarf_attrval_string(Dwarf_Die die,Dwarf_Half attr,const char ** strp,Dwarf_Error * err)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
dwarf_attrval_signed(Dwarf_Die die,Dwarf_Half attr,Dwarf_Signed * valp,Dwarf_Error * err)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 		break;
132 	case DW_FORM_data8:
133 	case DW_FORM_sdata:
134 		*valp = at->u[0].s64;
135 		break;
136 	default:
137 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
138 		return (DW_DLV_ERROR);
139 	}
140 
141 	return (DW_DLV_OK);
142 }
143 
144 int
dwarf_attrval_unsigned(Dwarf_Die die,Dwarf_Half attr,Dwarf_Unsigned * valp,Dwarf_Error * err)145 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
146 {
147 	Dwarf_Attribute at;
148 	Dwarf_Die die1;
149 	Dwarf_Unsigned val;
150 	Dwarf_Debug dbg;
151 
152 	dbg = die != NULL ? die->die_dbg : NULL;
153 
154 	if (die == NULL || valp == NULL) {
155 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
156 		return (DW_DLV_ERROR);
157 	}
158 
159 	*valp = 0;
160 
161 	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
162 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
163 		return (DW_DLV_NO_ENTRY);
164 	}
165 
166 	die1 = NULL;
167 	if (at == NULL &&
168 	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
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 			if ((die1 = _dwarf_die_find(die, val)) == NULL ||
177 			    (at = _dwarf_attr_find(die1, attr)) == NULL) {
178 				if (die1 != NULL)
179 					dwarf_dealloc(dbg, die1, DW_DLA_DIE);
180 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
181 				return (DW_DLV_NO_ENTRY);
182 			}
183 			break;
184 		default:
185 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
186 			return (DW_DLV_ERROR);
187 		}
188 	}
189 
190 	switch (at->at_form) {
191 	case DW_FORM_addr:
192 	case DW_FORM_data1:
193 	case DW_FORM_data2:
194 	case DW_FORM_data4:
195 	case DW_FORM_data8:
196 	case DW_FORM_udata:
197 	case DW_FORM_ref1:
198 	case DW_FORM_ref2:
199 	case DW_FORM_ref4:
200 	case DW_FORM_ref8:
201 	case DW_FORM_ref_udata:
202 		*valp = at->u[0].u64;
203 		break;
204 	default:
205 		if (die1 != NULL)
206 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
207 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
208 		return (DW_DLV_ERROR);
209 	}
210 
211 	if (die1 != NULL)
212 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
213 
214 	return (DW_DLV_OK);
215 }
216