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