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