1 /*
2 Copyright (C) 2016-2019 David Anderson. All Rights Reserved.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of version 2.1 of the GNU Lesser General Public License
6 as published by the Free Software Foundation.
7
8 This program is distributed in the hope that it would be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
12 Further, this software is distributed without any warranty that it is
13 free of the rightful claim of any third person regarding infringement
14 or the like. Any license provided herein, whether implied or
15 otherwise, applies only to this software file. Patent licenses, if
16 any, provided herein do not apply to combinations of this program with
17 other software, or any other product whatsoever.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this program; if not, write the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
22 USA.
23
24 */
25
26 #include "config.h"
27 #include <stdio.h>
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_MALLOC_H
32 /* Useful include for some Windows compilers. */
33 #include <malloc.h>
34 #endif /* HAVE_MALLOC_H */
35 #include "dwarf_incl.h"
36 #include "dwarf_alloc.h"
37 #include "dwarf_error.h"
38 #include "dwarf_util.h"
39 #include "dwarf_dsc.h"
40
41 #define FALSE 0
42 #define TRUE 1
43
44 /* When called with ary and *arraycount 0
45 this just counts the elements found.
46 Otherwise it records the values in ary and
47 recounts. The arraycount pointer must be
48 passed-in non-null always. */
49 static int
get_dsc_leb_entries(Dwarf_Debug dbg,Dwarf_Small * blockpointer,Dwarf_Unsigned blocklen,int dounsigned,struct Dwarf_Dsc_Entry_s * ary,size_t * arraycount,Dwarf_Error * error)50 get_dsc_leb_entries(Dwarf_Debug dbg,
51 Dwarf_Small * blockpointer,
52 Dwarf_Unsigned blocklen,
53 int dounsigned,
54 struct Dwarf_Dsc_Entry_s *ary,
55 size_t * arraycount,
56 Dwarf_Error * error)
57 {
58 Dwarf_Small *p = blockpointer;
59 Dwarf_Small *endp = blockpointer + blocklen;
60 size_t larraycount = 0;
61 size_t iarraycount = *arraycount;
62
63 if (!ary) {
64 if (iarraycount) {
65 /* Internal botch calling this static function. */
66 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
67 return DW_DLV_ERROR;
68 }
69 } else {
70 if (!iarraycount) {
71 /* Internal botch calling this static function. */
72 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
73 return DW_DLV_ERROR;
74 }
75 }
76 if (dounsigned) {
77 while (p < endp) {
78 Dwarf_Unsigned dsc = 0;
79 Dwarf_Unsigned low = 0;
80 Dwarf_Unsigned high = 0;
81 UNUSEDARG Dwarf_Unsigned leblen = 0;
82
83 if (ary && (larraycount >= iarraycount)) {
84 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
85 return DW_DLV_ERROR;
86 }
87 DECODE_LEB128_UWORD_LEN_CK(p,dsc,
88 leblen,dbg,error,endp);
89 if (!dsc) {
90 DECODE_LEB128_UWORD_LEN_CK(p,low,
91 leblen, dbg,error,endp);
92 } else {
93 DECODE_LEB128_UWORD_LEN_CK(p,low,
94 leblen, dbg,error,endp);
95 DECODE_LEB128_UWORD_LEN_CK(p,high,
96 leblen, dbg,error,endp);
97 }
98 if(ary) {
99 struct Dwarf_Dsc_Entry_s *arye =
100 ary+larraycount;
101
102 /* type reads the same as uleb and leb because
103 it is only zero or one. */
104 arye->dsc_type = dsc;
105 arye->dsc_low_u = low;
106 arye->dsc_high_u = high;
107 }
108 larraycount++;
109 }
110 } else {
111 while (p < endp) {
112 Dwarf_Signed dsc = 0;
113 Dwarf_Signed low = 0;
114 Dwarf_Signed high = 0;
115 UNUSEDARG Dwarf_Unsigned leblen = 0;
116
117 if (ary && (larraycount >= iarraycount)) {
118 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
119 return DW_DLV_ERROR;
120 }
121 DECODE_LEB128_SWORD_LEN_CK(p,dsc,
122 leblen,dbg,error,endp);
123 if (!dsc) {
124 DECODE_LEB128_SWORD_LEN_CK(p,low,
125 leblen,dbg,error,endp);
126 } else {
127 DECODE_LEB128_SWORD_LEN_CK(p,low,
128 leblen,dbg,error,endp);
129 DECODE_LEB128_SWORD_LEN_CK(p,high,
130 leblen,dbg,error,endp);
131 }
132 if(ary) {
133 struct Dwarf_Dsc_Entry_s *arye =
134 ary+larraycount;
135
136 /* type reads the same as uleb and leb because
137 it is only zero or one. */
138 arye->dsc_type = (Dwarf_Unsigned)dsc;
139 arye->dsc_low_s = low;
140 arye->dsc_high_s = high;
141 }
142 larraycount++;
143 }
144 }
145 if (ary) {
146 /* Just verify this recount matches original */
147 if(iarraycount != larraycount) {
148 _dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
149 return DW_DLV_ERROR;
150 }
151 } else {
152 /* This matters for first call with
153 ary 0 and iarraycount 0 as we are generating the
154 count. */
155 *arraycount = larraycount;
156 }
157 return DW_DLV_OK;
158 }
159
160
dwarf_discr_list(Dwarf_Debug dbg,Dwarf_Small * blockpointer,Dwarf_Unsigned blocklen,Dwarf_Dsc_Head * dsc_head_out,Dwarf_Unsigned * dsc_array_length_out,Dwarf_Error * error)161 int dwarf_discr_list(Dwarf_Debug dbg,
162 Dwarf_Small * blockpointer,
163 Dwarf_Unsigned blocklen,
164 Dwarf_Dsc_Head * dsc_head_out,
165 Dwarf_Unsigned * dsc_array_length_out,
166 Dwarf_Error * error)
167 {
168 Dwarf_Dsc_Head h = 0;
169 int res = 0;
170 size_t arraycount = 0;
171 struct Dwarf_Dsc_Entry_s *ary = 0;
172 Dwarf_Small * dscblockp = 0;
173 Dwarf_Unsigned dscblocklen = 0;
174
175 if (!dbg){
176 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); \
177 return DW_DLV_ERROR;
178 }
179 if (blocklen == 0) {
180 return DW_DLV_NO_ENTRY;
181 }
182 dscblockp = (Dwarf_Small *)calloc(blocklen,sizeof(Dwarf_Small));
183 if(!dscblockp) {
184 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
185 return DW_DLV_ERROR;
186 }
187 dscblocklen = blocklen;
188 memcpy(dscblockp,blockpointer,blocklen);
189
190 res = get_dsc_leb_entries(dbg,dscblockp,dscblocklen,
191 /* TRUE or FALSE here is not important, the arraycount
192 returned to us will be identical either way. */
193 FALSE, 0, &arraycount,error);
194 if (res != DW_DLV_OK) {
195 free(dscblockp);
196 return res;
197 }
198
199 h = (Dwarf_Dsc_Head)_dwarf_get_alloc(dbg,DW_DLA_DSC_HEAD,1);
200 if(!h) {
201 free(dscblockp);
202 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
203 return DW_DLV_ERROR;
204 }
205
206 h->dsh_block = dscblockp;
207 h->dsh_block_len = dscblocklen;
208 h->dsh_debug = dbg;
209 /* Now the destructor for h will deal with block malloc space. */
210
211 ary = (struct Dwarf_Dsc_Entry_s *)calloc(arraycount,
212 sizeof(struct Dwarf_Dsc_Entry_s));
213 if(!ary) {
214 dwarf_dealloc(dbg,h,DW_DLA_DSC_HEAD);
215 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
216 return DW_DLV_ERROR;
217 }
218 h->dsh_count = arraycount;
219 h->dsh_array = ary;
220 h->dsh_set_unsigned = 0;
221 h->dsh_set_signed = 0;
222
223 *dsc_head_out = h;
224 *dsc_array_length_out = arraycount;
225 return DW_DLV_OK;
226 }
227
228 /* NEW September 2016. Allows easy access to DW_AT_discr_list
229 entry. Callers must know which is the appropriate
230 one of the following two interfaces, though both
231 will work. */
dwarf_discr_entry_u(Dwarf_Dsc_Head dsh,Dwarf_Unsigned entrynum,Dwarf_Half * out_type,Dwarf_Unsigned * out_discr_low,Dwarf_Unsigned * out_discr_high,UNUSEDARG Dwarf_Error * error)232 int dwarf_discr_entry_u(Dwarf_Dsc_Head dsh ,
233 Dwarf_Unsigned entrynum,
234 Dwarf_Half * out_type,
235 Dwarf_Unsigned * out_discr_low,
236 Dwarf_Unsigned * out_discr_high,
237 UNUSEDARG Dwarf_Error * error)
238 {
239 struct Dwarf_Dsc_Entry_s *dse = 0;
240
241 if (entrynum >= dsh->dsh_count) {
242 return DW_DLV_NO_ENTRY;
243 }
244 if (!dsh->dsh_set_unsigned) {
245 int res =0;
246 int dounsigned = 1;
247 size_t count = dsh->dsh_count;
248
249 res = get_dsc_leb_entries(dsh->dsh_debug,
250 dsh->dsh_block,
251 dsh->dsh_block_len,
252 dounsigned,
253 dsh->dsh_array,
254 &count,
255 error);
256 if (res != DW_DLV_OK) {
257 return res;
258 }
259 dsh->dsh_set_unsigned = TRUE;
260 }
261 if (!dsh->dsh_array) {
262 _dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR);
263 return DW_DLV_ERROR;
264 }
265 dse = dsh->dsh_array + entrynum;
266 *out_type = dse->dsc_type;
267 *out_discr_low = dse->dsc_low_u;
268 *out_discr_high = dse->dsc_high_u;
269 return DW_DLV_OK;
270 }
271
272 /* NEW September 2016. Allows easy access to DW_AT_discr_list
273 entry. */
dwarf_discr_entry_s(Dwarf_Dsc_Head dsh,Dwarf_Unsigned entrynum,Dwarf_Half * out_type,Dwarf_Signed * out_discr_low,Dwarf_Signed * out_discr_high,UNUSEDARG Dwarf_Error * error)274 int dwarf_discr_entry_s(Dwarf_Dsc_Head dsh,
275 Dwarf_Unsigned entrynum,
276 Dwarf_Half * out_type,
277 Dwarf_Signed * out_discr_low,
278 Dwarf_Signed * out_discr_high,
279 UNUSEDARG Dwarf_Error * error)
280 {
281 struct Dwarf_Dsc_Entry_s *dse = 0;
282
283 if (entrynum >= dsh->dsh_count) {
284 return DW_DLV_NO_ENTRY;
285 }
286 if (!dsh->dsh_set_signed) {
287 int res =0;
288 int dounsigned = 0;
289 size_t count = dsh->dsh_count;
290
291 res = get_dsc_leb_entries(dsh->dsh_debug,
292 dsh->dsh_block,
293 dsh->dsh_block_len,
294 dounsigned,
295 dsh->dsh_array,
296 &count,
297 error);
298 if (res != DW_DLV_OK) {
299 return res;
300 }
301 dsh->dsh_set_signed = TRUE;
302 }
303 if (!dsh->dsh_array) {
304 _dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR);
305 return DW_DLV_ERROR;
306 }
307 dse = dsh->dsh_array + entrynum;
308 *out_type = dse->dsc_type;
309 *out_discr_low = dse->dsc_low_s;
310 *out_discr_high = dse->dsc_high_s;
311 return DW_DLV_OK;
312 }
313
314 void
_dwarf_dsc_destructor(void * m)315 _dwarf_dsc_destructor(void *m)
316 {
317 Dwarf_Dsc_Head h = (Dwarf_Dsc_Head) m;
318
319 free(h->dsh_array);
320 h->dsh_array = 0;
321 free(h->dsh_block);
322 h->dsh_block = 0;
323 h->dsh_count = 0;
324 }
325