1/*
2
3  Copyright (C) 2000,2001,2004,2005 Silicon Graphics, Inc.  All Rights Reserved.
4
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of version 2.1 of the GNU Lesser General Public License
7  as published by the Free Software Foundation.
8
9  This program is distributed in the hope that it would be useful, but
10  WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13  Further, this software is distributed without any warranty that it is
14  free of the rightful claim of any third person regarding infringement
15  or the like.  Any license provided herein, whether implied or
16  otherwise, applies only to this software file.  Patent licenses, if
17  any, provided herein do not apply to combinations of this program with
18  other software, or any other product whatsoever.
19
20  You should have received a copy of the GNU Lesser General Public
21  License along with this program; if not, write the Free Software
22  Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
23  USA.
24
25  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26  Mountain View, CA 94043, or:
27
28  http://www.sgi.com
29
30  For further information regarding this notice, see:
31
32  http://oss.sgi.com/projects/GenInfo/NoticeExplan
33
34*/
35
36
37
38#include "config.h"
39#include "dwarf_incl.h"
40#include <stdio.h>
41#include "dwarf_abbrev.h"
42
43int
44dwarf_get_abbrev(Dwarf_Debug dbg,
45		 Dwarf_Unsigned offset,
46		 Dwarf_Abbrev * returned_abbrev,
47		 Dwarf_Unsigned * length,
48		 Dwarf_Unsigned * abbr_count, Dwarf_Error * error)
49{
50    Dwarf_Small *abbrev_ptr;
51    Dwarf_Small *abbrev_section_end;
52    Dwarf_Half attr;
53    Dwarf_Half attr_form;
54    Dwarf_Abbrev ret_abbrev;
55    Dwarf_Unsigned labbr_count = 0;
56    Dwarf_Unsigned utmp;
57
58
59    if (dbg == NULL) {
60	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
61	return (DW_DLV_ERROR);
62    }
63    if (dbg->de_debug_abbrev == 0) {
64	/* Loads abbrev section (and .debug_info as we do those
65	   together). */
66	int res = _dwarf_load_debug_info(dbg, error);
67
68	if (res != DW_DLV_OK) {
69	    return res;
70	}
71    }
72
73    if (offset >= dbg->de_debug_abbrev_size) {
74	return (DW_DLV_NO_ENTRY);
75    }
76
77
78    ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg, DW_DLA_ABBREV, 1);
79    if (ret_abbrev == NULL) {
80	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
81	return (DW_DLV_ERROR);
82    }
83    ret_abbrev->ab_dbg = dbg;
84    if (returned_abbrev == 0 || abbr_count == 0) {
85	dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
86	_dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL);
87	return (DW_DLV_ERROR);
88    }
89
90
91    *abbr_count = 0;
92    if (length != NULL)
93	*length = 1;
94
95    abbrev_ptr = dbg->de_debug_abbrev + offset;
96    abbrev_section_end =
97	dbg->de_debug_abbrev + dbg->de_debug_abbrev_size;
98
99    DECODE_LEB128_UWORD(abbrev_ptr, utmp);
100    ret_abbrev->ab_code = (Dwarf_Word) utmp;
101    if (ret_abbrev->ab_code == 0) {
102	*returned_abbrev = ret_abbrev;
103	*abbr_count = 0;
104	if (length) {
105	    *length = 1;
106	}
107	return (DW_DLV_OK);
108    }
109
110    DECODE_LEB128_UWORD(abbrev_ptr, utmp);
111    ret_abbrev->ab_tag = utmp;
112    ret_abbrev->ab_has_child = *(abbrev_ptr++);
113    ret_abbrev->ab_abbrev_ptr = abbrev_ptr;
114
115    do {
116	Dwarf_Unsigned utmp2;
117
118	DECODE_LEB128_UWORD(abbrev_ptr, utmp2)
119	    attr = (Dwarf_Half) utmp2;
120	DECODE_LEB128_UWORD(abbrev_ptr, utmp2)
121	    attr_form = (Dwarf_Half) utmp2;
122
123	if (attr != 0)
124	    (labbr_count)++;
125
126    } while (abbrev_ptr < abbrev_section_end &&
127	     (attr != 0 || attr_form != 0));
128
129    if (abbrev_ptr > abbrev_section_end) {
130	dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
131	_dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
132	return (DW_DLV_ERROR);
133    }
134
135    if (length != NULL)
136	*length = abbrev_ptr - dbg->de_debug_abbrev - offset;
137
138    *returned_abbrev = ret_abbrev;
139    *abbr_count = labbr_count;
140    return (DW_DLV_OK);
141}
142
143int
144dwarf_get_abbrev_code(Dwarf_Abbrev abbrev,
145		      Dwarf_Unsigned * returned_code,
146		      Dwarf_Error * error)
147{
148    if (abbrev == NULL) {
149	_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
150	return (DW_DLV_ERROR);
151    }
152
153    *returned_code = abbrev->ab_code;
154    return (DW_DLV_OK);
155}
156
157int
158dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev,
159		     Dwarf_Half * returned_tag, Dwarf_Error * error)
160{
161    if (abbrev == NULL) {
162	_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
163	return (DW_DLV_ERROR);
164    }
165
166    *returned_tag = abbrev->ab_tag;
167    return (DW_DLV_OK);
168}
169
170
171int
172dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev,
173			       Dwarf_Signed * returned_flag,
174			       Dwarf_Error * error)
175{
176    if (abbrev == NULL) {
177	_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
178	return (DW_DLV_ERROR);
179    }
180
181    *returned_flag = abbrev->ab_has_child;
182    return (DW_DLV_OK);
183}
184
185
186int
187dwarf_get_abbrev_entry(Dwarf_Abbrev abbrev,
188		       Dwarf_Signed index,
189		       Dwarf_Half * returned_attr_num,
190		       Dwarf_Signed * form,
191		       Dwarf_Off * offset, Dwarf_Error * error)
192{
193    Dwarf_Byte_Ptr abbrev_ptr;
194    Dwarf_Byte_Ptr abbrev_end;
195    Dwarf_Byte_Ptr mark_abbrev_ptr;
196    Dwarf_Half attr;
197    Dwarf_Half attr_form;
198
199    if (index < 0)
200	return (DW_DLV_NO_ENTRY);
201
202    if (abbrev == NULL) {
203	_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
204	return (DW_DLV_ERROR);
205    }
206
207    if (abbrev->ab_code == 0) {
208	return (DW_DLV_NO_ENTRY);
209    }
210
211    if (abbrev->ab_dbg == NULL) {
212	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
213	return (DW_DLV_ERROR);
214    }
215
216    abbrev_ptr = abbrev->ab_abbrev_ptr;
217    abbrev_end =
218	abbrev->ab_dbg->de_debug_abbrev +
219	abbrev->ab_dbg->de_debug_abbrev_size;
220
221    for (attr = 1, attr_form = 1;
222	 index >= 0 && abbrev_ptr < abbrev_end && (attr != 0 ||
223						   attr_form != 0);
224	 index--) {
225	Dwarf_Unsigned utmp4;
226
227	mark_abbrev_ptr = abbrev_ptr;
228	DECODE_LEB128_UWORD(abbrev_ptr, utmp4)
229	    attr = (Dwarf_Half) utmp4;
230	DECODE_LEB128_UWORD(abbrev_ptr, utmp4)
231	    attr_form = (Dwarf_Half) utmp4;
232    }
233
234    if (abbrev_ptr >= abbrev_end) {
235	_dwarf_error(abbrev->ab_dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
236	return (DW_DLV_ERROR);
237    }
238
239    if (index >= 0) {
240	return (DW_DLV_NO_ENTRY);
241    }
242
243    if (form != NULL)
244	*form = attr_form;
245    if (offset != NULL)
246	*offset = mark_abbrev_ptr - abbrev->ab_dbg->de_debug_abbrev;
247
248    *returned_attr_num = (attr);
249    return DW_DLV_OK;
250}
251