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