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. */
49static int
50get_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
161int 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. */
232int 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. */
274int 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
314void
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