xref: /freebsd/contrib/elftoolchain/libdwarf/dwarf_attrval.c (revision 554491ffbdcfe51993d5b436a9bbca7aba388dd3)
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 3509 2016-12-29 03:58:41Z 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  	int first;
149  
150  	dbg = die != NULL ? die->die_dbg : NULL;
151  
152  	if (die == NULL || valp == NULL) {
153  		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
154  		return (DW_DLV_ERROR);
155  	}
156  
157  	*valp = 0;
158  
159  	die1 = NULL;
160  	for (;;) {
161  		if ((at = _dwarf_attr_find(die, attr)) != NULL ||
162  		    attr != DW_AT_type)
163  			break;
164  		if ((at = _dwarf_attr_find(die, DW_AT_abstract_origin)) ==
165  		    NULL &&
166  		    (at = _dwarf_attr_find(die, DW_AT_specification)) == NULL)
167  			break;
168  
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  			first = (die1 == NULL);
177  			die1 = _dwarf_die_find(die, val);
178  			if (!first)
179  				dwarf_dealloc(dbg, die, DW_DLA_DIE);
180  			if (die1 == NULL) {
181  				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
182  				return (DW_DLV_NO_ENTRY);
183  			}
184  			die = die1;
185  			break;
186  		default:
187  			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
188  			return (DW_DLV_ERROR);
189  		}
190  	}
191  
192  	if (at == NULL) {
193  		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
194  		return (DW_DLV_NO_ENTRY);
195  	}
196  
197  	switch (at->at_form) {
198  	case DW_FORM_addr:
199  	case DW_FORM_data1:
200  	case DW_FORM_data2:
201  	case DW_FORM_data4:
202  	case DW_FORM_data8:
203  	case DW_FORM_udata:
204  	case DW_FORM_ref1:
205  	case DW_FORM_ref2:
206  	case DW_FORM_ref4:
207  	case DW_FORM_ref8:
208  	case DW_FORM_ref_udata:
209  		*valp = at->u[0].u64;
210  		break;
211  	default:
212  		if (die1 != NULL)
213  			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
214  		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
215  		return (DW_DLV_ERROR);
216  	}
217  
218  	if (die1 != NULL)
219  		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
220  
221  	return (DW_DLV_OK);
222  }
223