xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/dwarf_attrval.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /*	$NetBSD: dwarf_attrval.c,v 1.8 2016/03/31 15:53:33 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.8 2016/03/31 15:53:33 christos Exp $");
32 ELFTC_VCSID("Id: dwarf_attrval.c 3159 2015-02-15 21:43:27Z emaste ");
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 		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 static Dwarf_Attribute
145 dwarf_indirect_find(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attr,
146     Dwarf_Unsigned val)
147 {
148 	Dwarf_Die die1;
149 
150 	if ((die1 = _dwarf_die_find(die, val)) == NULL)
151 		return NULL;
152 
153 	return _dwarf_attr_find(die1, attr);
154 }
155 
156 int
157 dwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
158 {
159 	Dwarf_Attribute at;
160 	Dwarf_Debug dbg;
161 
162 	dbg = die != NULL ? die->die_dbg : NULL;
163 
164 	if (die == NULL || valp == NULL) {
165 		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
166 		return (DW_DLV_ERROR);
167 	}
168 
169 	*valp = 0;
170 
171 	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
172 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
173 		return (DW_DLV_NO_ENTRY);
174 	}
175 
176 	if (at == NULL &&
177 	    ((at = _dwarf_attr_find(die, DW_AT_specification)) != NULL ||
178 	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL)) {
179 		switch (at->at_form) {
180 		case DW_FORM_ref1:
181 		case DW_FORM_ref2:
182 		case DW_FORM_ref4:
183 		case DW_FORM_ref8:
184 		case DW_FORM_ref_udata:
185 			at = dwarf_indirect_find(dbg, die, attr, at->u[0].u64);
186 			break;
187 		default:
188 			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
189 			return (DW_DLV_ERROR);
190 		}
191 	}
192 
193 	if (at == NULL)  {
194 		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
195 		return (DW_DLV_NO_ENTRY);
196 	}
197 
198 	switch (at->at_form) {
199 	case DW_FORM_addr:
200 	case DW_FORM_data1:
201 	case DW_FORM_data2:
202 	case DW_FORM_data4:
203 	case DW_FORM_data8:
204 	case DW_FORM_udata:
205 	case DW_FORM_ref1:
206 	case DW_FORM_ref2:
207 	case DW_FORM_ref4:
208 	case DW_FORM_ref8:
209 	case DW_FORM_ref_udata:
210 		*valp = at->u[0].u64;
211 		break;
212 	default:
213 		if (at->at_die != die)
214 			dwarf_dealloc(dbg, at->at_die, DW_DLA_DIE);
215 		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
216 		return (DW_DLV_ERROR);
217 	}
218 
219 	if (at->at_die != die)
220 		dwarf_dealloc(dbg, at->at_die, DW_DLA_DIE);
221 	return (DW_DLV_OK);
222 }
223