dwarf_attrval.c revision 260684
1246145Shselasky/*-
2246145Shselasky * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3246145Shselasky * All rights reserved.
4246145Shselasky *
5246145Shselasky * Redistribution and use in source and binary forms, with or without
6246145Shselasky * modification, are permitted provided that the following conditions
7246145Shselasky * are met:
8246145Shselasky * 1. Redistributions of source code must retain the above copyright
9246145Shselasky *    notice, this list of conditions and the following disclaimer.
10246145Shselasky * 2. Redistributions in binary form must reproduce the above copyright
11246145Shselasky *    notice, this list of conditions and the following disclaimer in the
12246145Shselasky *    documentation and/or other materials provided with the distribution.
13246145Shselasky *
14246145Shselasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15246145Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16246145Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17246145Shselasky * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18246145Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19246145Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20246145Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21246145Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22246145Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23246145Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24246145Shselasky * SUCH DAMAGE.
25246145Shselasky */
26246145Shselasky
27246145Shselasky#include "_libdwarf.h"
28246145Shselasky
29246145ShselaskyELFTC_VCSID("$Id: dwarf_attrval.c 2072 2011-10-27 03:26:49Z jkoshy $");
30246145Shselasky
31246145Shselaskyint
32246145Shselaskydwarf_attrval_flag(Dwarf_Die die, Dwarf_Half attr, Dwarf_Bool *valp, Dwarf_Error *err)
33246145Shselasky{
34246145Shselasky	Dwarf_Attribute at;
35246145Shselasky	Dwarf_Debug dbg;
36246145Shselasky
37246145Shselasky	dbg = die != NULL ? die->die_dbg : NULL;
38246145Shselasky
39246145Shselasky	if (die == NULL || valp == NULL) {
40246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
41246145Shselasky		return (DW_DLV_ERROR);
42246145Shselasky	}
43246145Shselasky
44246145Shselasky	*valp = 0;
45246145Shselasky
46246145Shselasky	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
47246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
48246145Shselasky		return (DW_DLV_NO_ENTRY);
49246145Shselasky	}
50246145Shselasky
51246145Shselasky	switch (at->at_form) {
52246145Shselasky	case DW_FORM_flag:
53246145Shselasky		*valp = (Dwarf_Bool) (!!at->u[0].u64);
54246145Shselasky		break;
55246145Shselasky	default:
56246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
57246145Shselasky		return (DW_DLV_ERROR);
58246145Shselasky	}
59246145Shselasky
60246145Shselasky	return (DW_DLV_OK);
61246145Shselasky}
62246145Shselasky
63246145Shselaskyint
64246145Shselaskydwarf_attrval_string(Dwarf_Die die, Dwarf_Half attr, const char **strp, Dwarf_Error *err)
65246145Shselasky{
66246145Shselasky	Dwarf_Attribute at;
67246145Shselasky	Dwarf_Debug dbg;
68246145Shselasky
69246145Shselasky	dbg = die != NULL ? die->die_dbg : NULL;
70246145Shselasky
71246145Shselasky	if (die == NULL || strp == NULL) {
72246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
73246145Shselasky		return (DW_DLV_ERROR);
74246145Shselasky	}
75246145Shselasky
76246145Shselasky	*strp = NULL;
77246145Shselasky
78246145Shselasky	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
79246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
80246145Shselasky		return (DW_DLV_NO_ENTRY);
81246145Shselasky	}
82246145Shselasky
83246145Shselasky	switch (at->at_form) {
84246145Shselasky	case DW_FORM_strp:
85246145Shselasky		*strp = at->u[1].s;
86246145Shselasky		break;
87246145Shselasky	case DW_FORM_string:
88246145Shselasky		*strp = at->u[0].s;
89246145Shselasky		break;
90246145Shselasky	default:
91246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
92246145Shselasky		return (DW_DLV_ERROR);
93246145Shselasky	}
94246145Shselasky
95246145Shselasky	return (DW_DLV_OK);
96246145Shselasky}
97246145Shselasky
98246145Shselaskyint
99246145Shselaskydwarf_attrval_signed(Dwarf_Die die, Dwarf_Half attr, Dwarf_Signed *valp, Dwarf_Error *err)
100246145Shselasky{
101246145Shselasky	Dwarf_Attribute at;
102246145Shselasky	Dwarf_Debug dbg;
103246145Shselasky
104246145Shselasky	dbg = die != NULL ? die->die_dbg : NULL;
105246145Shselasky
106246145Shselasky	if (die == NULL || valp == NULL) {
107246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
108246145Shselasky		return (DW_DLV_ERROR);
109246145Shselasky	}
110246145Shselasky
111246145Shselasky	*valp = 0;
112246145Shselasky
113246145Shselasky	if ((at = _dwarf_attr_find(die, attr)) == NULL) {
114246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
115246145Shselasky		return (DW_DLV_NO_ENTRY);
116246145Shselasky	}
117246145Shselasky
118246145Shselasky	switch (at->at_form) {
119246145Shselasky	case DW_FORM_data1:
120246145Shselasky		*valp = (int8_t) at->u[0].s64;
121246145Shselasky		break;
122246145Shselasky	case DW_FORM_data2:
123246145Shselasky		*valp = (int16_t) at->u[0].s64;
124246145Shselasky		break;
125246145Shselasky	case DW_FORM_data4:
126246145Shselasky		*valp = (int32_t) at->u[0].s64;
127246145Shselasky	case DW_FORM_data8:
128246145Shselasky	case DW_FORM_sdata:
129246145Shselasky		*valp = at->u[0].s64;
130246145Shselasky		break;
131246145Shselasky	default:
132246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
133246145Shselasky		return (DW_DLV_ERROR);
134246145Shselasky	}
135246145Shselasky
136246145Shselasky	return (DW_DLV_OK);
137246145Shselasky}
138246145Shselasky
139246145Shselaskyint
140246145Shselaskydwarf_attrval_unsigned(Dwarf_Die die, Dwarf_Half attr, Dwarf_Unsigned *valp, Dwarf_Error *err)
141246145Shselasky{
142246145Shselasky	Dwarf_Attribute at;
143246145Shselasky	Dwarf_Die die1;
144246145Shselasky	Dwarf_Unsigned val;
145246145Shselasky	Dwarf_Debug dbg;
146246145Shselasky
147246145Shselasky	dbg = die != NULL ? die->die_dbg : NULL;
148246145Shselasky
149246145Shselasky	if (die == NULL || valp == NULL) {
150246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ARGUMENT);
151246145Shselasky		return (DW_DLV_ERROR);
152246145Shselasky	}
153246145Shselasky
154246145Shselasky	*valp = 0;
155246145Shselasky
156246145Shselasky	if ((at = _dwarf_attr_find(die, attr)) == NULL && attr != DW_AT_type) {
157246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
158246145Shselasky		return (DW_DLV_NO_ENTRY);
159246145Shselasky	}
160246145Shselasky
161246145Shselasky	die1 = NULL;
162246145Shselasky	if (at == NULL &&
163246145Shselasky	    (at = _dwarf_attr_find(die, DW_AT_abstract_origin)) != NULL) {
164246145Shselasky		switch (at->at_form) {
165246145Shselasky		case DW_FORM_ref1:
166246145Shselasky		case DW_FORM_ref2:
167246145Shselasky		case DW_FORM_ref4:
168246145Shselasky		case DW_FORM_ref8:
169246145Shselasky		case DW_FORM_ref_udata:
170246145Shselasky			val = at->u[0].u64;
171246145Shselasky			if ((die1 = _dwarf_die_find(die, val)) == NULL ||
172246145Shselasky			    (at = _dwarf_attr_find(die1, attr)) == NULL) {
173246145Shselasky				if (die1 != NULL)
174246145Shselasky					dwarf_dealloc(dbg, die1, DW_DLA_DIE);
175246145Shselasky				DWARF_SET_ERROR(dbg, err, DW_DLE_NO_ENTRY);
176246145Shselasky				return (DW_DLV_NO_ENTRY);
177246145Shselasky			}
178246145Shselasky			break;
179246145Shselasky		default:
180246145Shselasky			DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
181246145Shselasky			return (DW_DLV_ERROR);
182246145Shselasky		}
183246145Shselasky	}
184246145Shselasky
185246145Shselasky	switch (at->at_form) {
186246145Shselasky	case DW_FORM_addr:
187246145Shselasky	case DW_FORM_data1:
188246145Shselasky	case DW_FORM_data2:
189246145Shselasky	case DW_FORM_data4:
190246145Shselasky	case DW_FORM_data8:
191246145Shselasky	case DW_FORM_udata:
192246145Shselasky	case DW_FORM_ref1:
193246145Shselasky	case DW_FORM_ref2:
194246145Shselasky	case DW_FORM_ref4:
195246145Shselasky	case DW_FORM_ref8:
196246145Shselasky	case DW_FORM_ref_udata:
197246145Shselasky		*valp = at->u[0].u64;
198246145Shselasky		break;
199246145Shselasky	default:
200246145Shselasky		if (die1 != NULL)
201246145Shselasky			dwarf_dealloc(dbg, die1, DW_DLA_DIE);
202246145Shselasky		DWARF_SET_ERROR(dbg, err, DW_DLE_ATTR_FORM_BAD);
203246145Shselasky		return (DW_DLV_ERROR);
204246145Shselasky	}
205246145Shselasky
206246145Shselasky	if (die1 != NULL)
207246145Shselasky		dwarf_dealloc(dbg, die1, DW_DLA_DIE);
208246145Shselasky
209246145Shselasky	return (DW_DLV_OK);
210246145Shselasky}
211246145Shselasky