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 3159 2015-02-15 21:43:27Z 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 
149 	dbg = die != NULL ? die->die_dbg : NULL;
150 
151 	if (die == NULL || valp == NULL) {
152 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
153 		return (DW_DLV_ERROR);
154 	}
155 
156 	*valp = 0;
157 
158 	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
159 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
160 		return (DW_DLV_NO_ENTRY);
161 	}
162 
163 	die1 = NULL;
164 	if (at == NULL &&
165 	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
166 		switch (at->at_form) {
167 		case DW_FORM_ref1:
168 		case DW_FORM_ref2:
169 		case DW_FORM_ref4:
170 		case DW_FORM_ref8:
171 		case DW_FORM_ref_udata:
172 			val = at->u[0].u64;
173 			if ((die1 = _dwarf_die_find(die, val)) == NULL ||
174 			    (at = _dwarf_attr_find(die1, attr)) == NULL) {
175 				if (die1 != NULL)
176 					dwarf_dealloc(dbg, die1, DW_DLA_DIE);
177 				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
178 				return (DW_DLV_NO_ENTRY);
179 			}
180 			break;
181 		default:
182 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
183 			return (DW_DLV_ERROR);
184 		}
185 	}
186 
187 	switch (at->at_form) {
188 	case DW_FORM_addr:
189 	case DW_FORM_data1:
190 	case DW_FORM_data2:
191 	case DW_FORM_data4:
192 	case DW_FORM_data8:
193 	case DW_FORM_udata:
194 	case DW_FORM_ref1:
195 	case DW_FORM_ref2:
196 	case DW_FORM_ref4:
197 	case DW_FORM_ref8:
198 	case DW_FORM_ref_udata:
199 		*valp = at->u[0].u64;
200 		break;
201 	default:
202 		if (die1 != NULL)
203 			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
204 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
205 		return (DW_DLV_ERROR);
206 	}
207 
208 	if (die1 != NULL)
209 		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
210 
211 	return (DW_DLV_OK);
212 }
213