Coverage Report

Created: 2023-12-08 06:43

/src/libdwarf/src/lib/libdwarf/dwarf_rnglists.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Copyright (c) 2020, David Anderson
3
All rights reserved.
4
5
Redistribution and use in source and binary forms, with
6
or without modification, are permitted provided that the
7
following conditions are met:
8
9
    Redistributions of source code must retain the above
10
    copyright notice, this list of conditions and the following
11
    disclaimer.
12
13
    Redistributions in binary form must reproduce the above
14
    copyright notice, this list of conditions and the following
15
    disclaimer in the documentation and/or other materials
16
    provided with the distribution.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include <config.h>
34
35
#include <stdlib.h> /* free() malloc() */
36
#include <stdio.h> /* printf */
37
#include <string.h> /* memset() */
38
39
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
40
#include "stdafx.h"
41
#endif /* HAVE_STDAFX_H */
42
43
#include "dwarf.h"
44
#include "libdwarf.h"
45
#include "libdwarf_private.h"
46
#include "dwarf_base_types.h"
47
#include "dwarf_opaque.h"
48
#include "dwarf_alloc.h"
49
#include "dwarf_error.h"
50
#include "dwarf_util.h"
51
#include "dwarf_string.h"
52
#include "dwarf_rnglists.h"
53
54
#define SIZEOFT8 1
55
6.63k
#define SIZEOFT16 2
56
9.48k
#define SIZEOFT32 4
57
#define SIZEOFT64 8
58
59
#if 0
60
static void
61
dump_bytes(const char *msg,Dwarf_Small * start, long len)
62
{
63
    Dwarf_Small *end = start + len;
64
    Dwarf_Small *cur = start;
65
    printf("%s (0x%lx) ",msg,(unsigned long)start);
66
    for (; cur < end; cur++) {
67
        printf("%02x", *cur);
68
    }
69
    printf("\n");
70
}
71
#endif /*0*/
72
#if 0
73
static void
74
dump_rh(const char *msg,
75
    int line,
76
    struct Dwarf_Rnglists_Head_s *head)
77
{
78
    printf("Rnglists_Head: %s  line %d\n",
79
        msg,line);
80
    printf("  count of entries: "
81
        DW_PR_DUu
82
        "  (0x%" DW_PR_DUx ")\n",
83
        head->rh_count,head->rh_count);
84
    printf("  rh_rnglists     : %p\n",(void *)) head->rh_rnglists);
85
    if (head->rh_first) {
86
        printf("  rh_first    : %" DW_PR_DUu "\n", head->rh_first);
87
    if (head->rh_last) {
88
        printf("  rh_last     :  %" DW_PR_DUu "\n",head->rh_last);
89
    }
90
    printf("  rh_bytes total  : %" DW_PR_DUu
91
        "  (0x%" DW_PR_DUx ")\n",head->rh_bytes_total,
92
        head->rh_bytes_total);
93
    printf("  CU Context      : %p",(void *)head->rh_context);
94
    printf("  Rnglists Context:  %p",(void *)head->rh_localcontext);
95
}
96
#endif
97
98
/*  Used in case of error reading the
99
    rnglists headers (not referring to Dwarf_Rnglists_Head
100
    here), to clean up. */
101
static void
102
free_rnglists_chain(Dwarf_Debug dbg, Dwarf_Chain head)
103
2.51k
{
104
2.51k
    Dwarf_Chain cur = head;
105
2.51k
    Dwarf_Chain next = 0;
106
107
2.51k
    if (!head) {
108
2.25k
        return;
109
2.25k
    }
110
1.89k
    for ( ;cur; cur = next) {
111
1.63k
        next = cur->ch_next;
112
1.63k
        if (cur->ch_item) {
113
1.63k
            free(cur->ch_item);
114
1.63k
            cur->ch_item = 0;
115
1.63k
            dwarf_dealloc(dbg,cur,DW_DLA_CHAIN);
116
1.63k
        }
117
1.63k
    }
118
264
}
119
120
static int
121
read_single_rle_entry(Dwarf_Debug dbg,
122
    Dwarf_Small   *data,
123
    Dwarf_Unsigned dataoffset,
124
    Dwarf_Small   *enddata,
125
    unsigned       address_size,
126
    unsigned       *bytes_count_out,
127
    unsigned       *entry_kind,
128
    Dwarf_Unsigned *entry_operand1,
129
    Dwarf_Unsigned *entry_operand2,
130
    Dwarf_Error* error)
131
4.86k
{
132
4.86k
    Dwarf_Unsigned count = 0;
133
4.86k
    unsigned leblen = 0;
134
4.86k
    unsigned code = 0;
135
4.86k
    Dwarf_Unsigned val1 = 0;
136
4.86k
    Dwarf_Unsigned val2 = 0;
137
138
4.86k
    code = *data;
139
4.86k
    ++data;
140
4.86k
    ++count;
141
4.86k
    switch(code) {
142
2.21k
    case DW_RLE_end_of_list: break;
143
824
    case DW_RLE_base_addressx:{
144
824
        DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen,
145
824
            dbg,error,enddata);
146
823
        count += leblen;
147
823
        }
148
0
        break;
149
408
    case DW_RLE_startx_endx:
150
655
    case DW_RLE_startx_length:
151
996
    case DW_RLE_offset_pair: {
152
996
        DECODE_LEB128_UWORD_LEN_CK(data,val1,leblen,
153
996
            dbg,error,enddata);
154
988
        count += leblen;
155
988
        DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen,
156
988
            dbg,error,enddata);
157
979
        count += leblen;
158
979
        }
159
0
        break;
160
277
    case DW_RLE_base_address: {
161
277
        READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
162
277
            data,address_size,error,enddata);
163
274
        data += address_size;
164
274
        count += address_size;
165
274
        }
166
0
        break;
167
229
    case DW_RLE_start_end: {
168
229
        READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
169
229
            data,address_size,error,enddata);
170
225
        data += address_size;
171
225
        count += address_size;
172
225
        READ_UNALIGNED_CK(dbg,val2, Dwarf_Unsigned,
173
225
            data,address_size,error,enddata);
174
221
        data += address_size;
175
221
        count += address_size;
176
221
        }
177
0
        break;
178
273
    case DW_RLE_start_length: {
179
273
        READ_UNALIGNED_CK(dbg,val1, Dwarf_Unsigned,
180
273
            data,address_size,error,enddata);
181
269
        data += address_size;
182
269
        count += address_size;
183
269
        DECODE_LEB128_UWORD_LEN_CK(data,val2,leblen,
184
269
            dbg,error,enddata);
185
266
        count += leblen;
186
266
        }
187
0
        break;
188
53
    default: {
189
53
        dwarfstring m;
190
191
53
        dwarfstring_constructor(&m);
192
53
        dwarfstring_append_printf_u(&m,
193
53
            "DW_DLE_RNGLISTS_ERROR: "
194
53
            "The rangelists entry at .debug_rnglists"
195
53
            " offset 0x%x" ,dataoffset);
196
53
        dwarfstring_append_printf_u(&m,
197
53
            " has code 0x%x which is unknown",code);
198
53
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
199
53
            dwarfstring_string(&m));
200
53
        dwarfstring_destructor(&m);
201
53
        return DW_DLV_ERROR;
202
269
        }
203
0
        break;
204
4.86k
    }
205
4.77k
    *bytes_count_out = count;
206
4.77k
    *entry_kind = code;
207
4.77k
    *entry_operand1 = val1;
208
4.77k
    *entry_operand2 = val2;
209
4.77k
    return DW_DLV_OK;
210
4.86k
}
211
212
/*  Reads the header. Determines the
213
    various offsets, including offset
214
    of the next header. Does no memory
215
    allocations here. */
216
int
217
_dwarf_internal_read_rnglists_header(Dwarf_Debug dbg,
218
    Dwarf_Unsigned contextnum,
219
    Dwarf_Unsigned sectionlength,
220
    Dwarf_Small *data,
221
    Dwarf_Small *end_data,
222
    Dwarf_Unsigned offset,
223
    Dwarf_Rnglists_Context  buildhere,
224
    Dwarf_Unsigned *next_offset,
225
    Dwarf_Error *error)
226
5.40k
{
227
5.40k
    Dwarf_Small *startdata = data;
228
5.40k
    Dwarf_Unsigned arealen = 0;
229
5.40k
    int offset_size = 0;
230
5.40k
    int exten_size = 0;
231
5.40k
    Dwarf_Unsigned version = 0;
232
5.40k
    unsigned address_size = 0;
233
5.40k
    unsigned segment_selector_size=  0;
234
5.40k
    Dwarf_Unsigned offset_entry_count = 0;
235
5.40k
    Dwarf_Unsigned localoff = 0;
236
5.40k
    Dwarf_Unsigned lists_len = 0;
237
5.40k
    Dwarf_Unsigned secsize_dbg = 0;
238
239
5.40k
    secsize_dbg = dbg->de_debug_rnglists.dss_size;
240
    /*  Sanity checks */
241
5.40k
    if (sectionlength > secsize_dbg) {
242
0
        dwarfstring m;
243
0
        dwarfstring_constructor(&m);
244
0
        dwarfstring_append_printf_u(&m,
245
0
            "DW_DLE_RNGLISTS_ERROR: "
246
0
            " section_length argument (%lu) mismatch vs.",
247
0
            sectionlength);
248
0
        dwarfstring_append_printf_u(&m,
249
0
            ".debug_rnglists"
250
0
            " section length",secsize_dbg);
251
0
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
252
0
            dwarfstring_string(&m));
253
0
        dwarfstring_destructor(&m);
254
0
        return DW_DLV_ERROR;
255
0
    }
256
5.40k
    if (sectionlength > secsize_dbg) {
257
0
        dwarfstring m;
258
0
        dwarfstring_constructor(&m);
259
0
        dwarfstring_append(&m,
260
0
            "DW_DLE_RNGLISTS_ERROR: "
261
0
            " section_length argument mismatch vs. .debug_rnglists"
262
0
            " section length including header.");
263
0
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
264
0
            dwarfstring_string(&m));
265
0
        dwarfstring_destructor(&m);
266
0
        return DW_DLV_ERROR;
267
0
    }
268
5.40k
    buildhere->rc_startaddr = data;
269
5.40k
    READ_AREA_LENGTH_CK(dbg,arealen,Dwarf_Unsigned,
270
5.40k
        data,offset_size,exten_size,
271
5.40k
        error,
272
5.40k
        sectionlength,end_data);
273
3.73k
    if (arealen > sectionlength ||
274
3.73k
        (arealen+offset_size+exten_size) > sectionlength) {
275
30
        dwarfstring m;
276
30
        dwarfstring_constructor(&m);
277
30
        dwarfstring_append_printf_u(&m,
278
30
            "DW_DLE_RNGLISTS_ERROR: A .debug_rnglists "
279
30
            "area size of 0x%x ",arealen);
280
30
        dwarfstring_append_printf_u(&m,
281
30
            "at offset 0x%x ",offset);
282
30
        dwarfstring_append_printf_u(&m,
283
30
            "is larger than the entire section size of "
284
30
            "0x%x. Corrupt DWARF.",sectionlength);
285
30
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
286
30
            dwarfstring_string(&m));
287
30
        dwarfstring_destructor(&m);
288
30
        return DW_DLV_ERROR;
289
30
    }
290
291
3.70k
    localoff = offset_size+exten_size;
292
3.70k
    buildhere->rc_length = arealen + localoff;
293
3.70k
    buildhere->rc_dbg = dbg;
294
3.70k
    buildhere->rc_index = contextnum;
295
3.70k
    buildhere->rc_header_offset = offset;
296
3.70k
    buildhere->rc_offset_size = offset_size;
297
3.70k
    buildhere->rc_extension_size = exten_size;
298
3.70k
    buildhere->rc_magic = RNGLISTS_MAGIC;
299
3.70k
    READ_UNALIGNED_CK(dbg,version,Dwarf_Unsigned,data,
300
3.70k
        SIZEOFT16,error,end_data);
301
3.68k
    if (version != DW_CU_VERSION5) {
302
366
        dwarfstring m;
303
366
        dwarfstring_constructor(&m);
304
366
        dwarfstring_append_printf_u(&m,
305
366
            "DW_DLE_RNGLISTS_ERROR: The version should be 5 "
306
366
            "but we find %u instead.",version);
307
366
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
308
366
            dwarfstring_string(&m));
309
366
        dwarfstring_destructor(&m);
310
366
        return DW_DLV_ERROR;
311
366
    }
312
3.31k
    buildhere->rc_version = version;
313
3.31k
    data += SIZEOFT16;
314
3.31k
    localoff += SIZEOFT16;
315
316
3.31k
    READ_UNALIGNED_CK(dbg,address_size,unsigned,data,
317
3.31k
        SIZEOFT8,error,end_data);
318
3.31k
    if (address_size != 4 && address_size != 8 &&
319
3.31k
        address_size != 2) {
320
99
        dwarfstring m;
321
99
        dwarfstring_constructor(&m);
322
99
        dwarfstring_append_printf_u(&m,
323
99
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists "
324
99
            "The address size "
325
99
            "of %u is not supported.",address_size);
326
99
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
327
99
            dwarfstring_string(&m));
328
99
        dwarfstring_destructor(&m);
329
99
        return DW_DLV_ERROR;
330
99
    }
331
3.21k
    buildhere->rc_address_size = address_size;
332
3.21k
    localoff++;
333
3.21k
    data++;
334
335
3.21k
    READ_UNALIGNED_CK(dbg,segment_selector_size,unsigned,data,
336
3.21k
        SIZEOFT8,error,end_data);
337
3.20k
    buildhere->rc_segment_selector_size = segment_selector_size;
338
3.20k
    data++;
339
3.20k
    localoff++;
340
3.20k
    if (segment_selector_size) {
341
37
        dwarfstring m;
342
37
        dwarfstring_constructor(&m);
343
37
        dwarfstring_append_printf_u(&m,
344
37
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists"
345
37
            " The segment selector size "
346
37
            "of %u is not supported.",address_size);
347
37
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
348
37
            dwarfstring_string(&m));
349
37
        dwarfstring_destructor(&m);
350
37
        return DW_DLV_ERROR;
351
37
    }
352
3.16k
    if ((offset+localoff+SIZEOFT32) > secsize_dbg) {
353
12
        dwarfstring m;
354
12
        dwarfstring_constructor(&m);
355
12
        dwarfstring_append_printf_u(&m,
356
12
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists"
357
12
            " Header runs off the end of the section "
358
12
            " with offset %u",offset+localoff+SIZEOFT32);
359
12
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
360
12
            dwarfstring_string(&m));
361
12
        dwarfstring_destructor(&m);
362
12
        return DW_DLV_ERROR;
363
12
    }
364
365
3.15k
    READ_UNALIGNED_CK(dbg,offset_entry_count,Dwarf_Unsigned,data,
366
3.15k
        SIZEOFT32,error,end_data);
367
3.15k
    buildhere->rc_offset_entry_count = offset_entry_count;
368
3.15k
    data += SIZEOFT32;
369
3.15k
    localoff+= SIZEOFT32;
370
3.15k
    if (offset_entry_count ){
371
1.47k
        buildhere->rc_offsets_array = data;
372
1.47k
    }
373
374
3.15k
    lists_len = offset_size *offset_entry_count;
375
3.15k
    if (offset_entry_count >= secsize_dbg ||
376
3.15k
        lists_len >= secsize_dbg) {
377
170
        dwarfstring m;
378
170
        dwarfstring_constructor(&m);
379
170
        dwarfstring_append_printf_u(&m,
380
170
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists"
381
170
            " offset entry count"
382
170
            " of %u is clearly impossible. Corrupt data",
383
170
            offset_entry_count);
384
170
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
385
170
            dwarfstring_string(&m));
386
170
        dwarfstring_destructor(&m);
387
170
        return DW_DLV_ERROR;
388
170
    }
389
2.98k
    data += lists_len;
390
2.98k
    buildhere->rc_offsets_off_in_sect = offset+localoff;
391
2.98k
    localoff += lists_len;
392
2.98k
    if (localoff > buildhere->rc_length) {
393
81
        dwarfstring m;
394
81
        dwarfstring_constructor(&m);
395
81
        dwarfstring_append_printf_u(&m,
396
81
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists"
397
81
            " length of rnglists header too large at"
398
81
            " of %u is clearly impossible. Corrupt data",
399
81
            localoff);
400
81
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
401
81
            dwarfstring_string(&m));
402
81
        dwarfstring_destructor(&m);
403
81
        return DW_DLV_ERROR;
404
81
    }
405
2.90k
    buildhere->rc_first_rnglist_offset = offset+localoff;
406
2.90k
    buildhere->rc_rnglists_header = startdata;
407
2.90k
    buildhere->rc_endaddr = startdata +buildhere->rc_length;
408
2.90k
    if (buildhere->rc_endaddr > end_data) {
409
19
        dwarfstring m;
410
19
        dwarfstring_constructor(&m);
411
19
        dwarfstring_append_printf_u(&m,
412
19
            " DW_DLE_RNGLISTS_ERROR: .debug_rnglists"
413
19
            " length of rnglists header (%u) "
414
19
            "runs off end of section. Corrupt data",
415
19
            buildhere->rc_length);
416
19
        _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
417
19
            dwarfstring_string(&m));
418
19
        dwarfstring_destructor(&m);
419
19
        return DW_DLV_ERROR;
420
19
    }
421
2.88k
    buildhere->rc_past_last_rnglist_offset =
422
2.88k
        buildhere->rc_header_offset +buildhere->rc_length;
423
2.88k
    *next_offset =  buildhere->rc_past_last_rnglist_offset;
424
2.88k
    return DW_DLV_OK;
425
2.90k
}
426
427
/*  We return a pointer to an array of contexts
428
    (not context pointers) through *cxt if
429
    we succeed and are returning DW_DLV_OK.
430
    We never return DW_DLV_NO_ENTRY here. */
431
static int
432
internal_load_rnglists_contexts(Dwarf_Debug dbg,
433
    Dwarf_Rnglists_Context **cxt,
434
    Dwarf_Unsigned *count,
435
    Dwarf_Error *error)
436
2.65k
{
437
2.65k
    Dwarf_Unsigned offset = 0;
438
2.65k
    Dwarf_Unsigned nextoffset = 0;
439
2.65k
    Dwarf_Small  * data = dbg->de_debug_rnglists.dss_data;
440
2.65k
    Dwarf_Unsigned section_size = dbg->de_debug_rnglists.dss_size;
441
2.65k
    Dwarf_Small  * startdata = data;
442
2.65k
    Dwarf_Small  * end_data = data +section_size;
443
2.65k
    Dwarf_Chain curr_chain = 0;
444
2.65k
    Dwarf_Chain head_chain = 0;
445
2.65k
    Dwarf_Chain *plast = &head_chain;
446
2.65k
    int res = 0;
447
2.65k
    Dwarf_Unsigned chainlength = 0;
448
2.65k
    Dwarf_Rnglists_Context *fullarray = 0;
449
2.65k
    Dwarf_Unsigned i = 0;
450
451
5.53k
    for (i = 0 ; data < end_data ; ++i,data = startdata+nextoffset) {
452
5.40k
        Dwarf_Rnglists_Context newcontext = 0;
453
454
        /* sizeof the context struct, not sizeof a pointer */
455
5.40k
        newcontext = malloc(sizeof(*newcontext));
456
5.40k
        if (!newcontext) {
457
0
            free_rnglists_chain(dbg,head_chain);
458
0
            _dwarf_error_string(dbg,error,
459
0
                DW_DLE_ALLOC_FAIL,
460
0
                "DW_DLE_ALLOC_FAIL: Allocation of "
461
0
                "Rnglists_Context failed");
462
0
            return DW_DLV_ERROR;
463
0
        }
464
5.40k
        memset(newcontext,0,sizeof(*newcontext));
465
5.40k
        newcontext->rc_magic = RNGLISTS_MAGIC;
466
5.40k
        res = _dwarf_internal_read_rnglists_header(dbg,
467
5.40k
            chainlength,
468
5.40k
            section_size,
469
5.40k
            data,end_data,offset,
470
5.40k
            newcontext,&nextoffset,error);
471
5.40k
        if (res == DW_DLV_ERROR) {
472
2.51k
            free(newcontext);
473
2.51k
            newcontext =  0;
474
2.51k
            free_rnglists_chain(dbg,head_chain);
475
2.51k
            return res;
476
2.51k
        }
477
2.88k
        newcontext->rc_magic = RNGLISTS_MAGIC;
478
2.88k
        curr_chain = (Dwarf_Chain)
479
2.88k
            _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
480
2.88k
        if (curr_chain == NULL) {
481
0
            _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
482
0
                "DW_DLE_ALLOC_FAIL: allocating Rnglists_Context"
483
0
                " chain entry");
484
0
            free(newcontext);
485
0
            newcontext =  0;
486
0
            free_rnglists_chain(dbg,head_chain);
487
0
            return DW_DLV_ERROR;
488
0
        }
489
2.88k
        curr_chain->ch_item = newcontext;
490
2.88k
        ++chainlength;
491
2.88k
        (*plast) = curr_chain;
492
2.88k
        plast = &(curr_chain->ch_next);
493
2.88k
        offset = nextoffset;
494
2.88k
        newcontext = 0;
495
2.88k
    }
496
134
    fullarray= (Dwarf_Rnglists_Context *)malloc(
497
134
        chainlength *sizeof(Dwarf_Rnglists_Context /*pointer*/));
498
134
    if (!fullarray) {
499
0
        free_rnglists_chain(dbg,head_chain);
500
0
        _dwarf_error_string(dbg,error,
501
0
            DW_DLE_ALLOC_FAIL,"Allocation of "
502
0
            "Rnglists_Context pointer array failed");
503
0
        return DW_DLV_ERROR;
504
0
    }
505
134
    curr_chain = head_chain;
506
1.38k
    for (i = 0; i < chainlength; ++i) {
507
1.25k
        Dwarf_Chain prev = 0;
508
1.25k
        Dwarf_Rnglists_Context c =
509
1.25k
            (Dwarf_Rnglists_Context)curr_chain->ch_item;
510
1.25k
        fullarray[i] = c;
511
1.25k
        curr_chain->ch_item = 0;
512
1.25k
        prev = curr_chain;
513
1.25k
        curr_chain = curr_chain->ch_next;
514
1.25k
        dwarf_dealloc(dbg, prev, DW_DLA_CHAIN);
515
1.25k
    }
516
    /*  ASSERT: the chain is entirely alloc'd
517
        and the array of pointers points to
518
        individually malloc'd Dwarf_Rnglists_Context_s */
519
134
    *cxt = fullarray;
520
134
    *count = chainlength;
521
134
    return DW_DLV_OK;
522
134
}
523
524
/*  Used by dwarfdump to print raw rnglists data.
525
    Loads all the .debug_rnglists[.dwo]  headers and
526
    returns DW_DLV_NO_ENTRY if the section
527
    is missing or empty.
528
    Intended to be done quite early and
529
    done exactly once.
530
    Harmless to do more than once.
531
    With DW_DLV_OK it returns the number of
532
    rnglists headers in the section through
533
    rnglists_count. */
534
int dwarf_load_rnglists(
535
    Dwarf_Debug dbg,
536
    Dwarf_Unsigned *rnglists_count,
537
    Dwarf_Error *error)
538
18.5k
{
539
18.5k
    int res = DW_DLV_ERROR;
540
18.5k
    Dwarf_Rnglists_Context *cxt = 0;
541
18.5k
    Dwarf_Unsigned count = 0;
542
543
18.5k
    CHECK_DBG(dbg,error,"dwarf_load_rnglists");
544
11.4k
    if (dbg->de_rnglists_context) {
545
0
        if (rnglists_count) {
546
0
            *rnglists_count = dbg->de_rnglists_context_count;
547
0
        }
548
0
        return DW_DLV_OK;
549
0
    }
550
11.4k
    if (!dbg->de_debug_rnglists.dss_size) {
551
        /* nothing there. */
552
8.18k
        return DW_DLV_NO_ENTRY;
553
8.18k
    }
554
3.27k
    if (!dbg->de_debug_rnglists.dss_data) {
555
3.27k
        res = _dwarf_load_section(dbg, &dbg->de_debug_rnglists,
556
3.27k
            error);
557
3.27k
        if (res != DW_DLV_OK) {
558
621
            return res;
559
621
        }
560
3.27k
    }
561
2.65k
    res = internal_load_rnglists_contexts(dbg,&cxt,&count,error);
562
2.65k
    if (res == DW_DLV_ERROR) {
563
2.51k
        return res;
564
2.51k
    }
565
134
    dbg->de_rnglists_context = cxt;
566
134
    dbg->de_rnglists_context_count = count;
567
134
    if (rnglists_count) {
568
110
        *rnglists_count = count;
569
110
    }
570
134
    return DW_DLV_OK;
571
2.65k
}
572
573
/*  Frees the memory in use in all rnglists contexts.
574
    Done by dwarf_finish()  */
575
void
576
_dwarf_dealloc_rnglists_context(Dwarf_Debug dbg)
577
143k
{
578
143k
    Dwarf_Unsigned i = 0;
579
143k
    Dwarf_Rnglists_Context * rngcon = 0;
580
581
143k
    if (IS_INVALID_DBG(dbg)) {
582
0
        return;
583
0
    }
584
143k
    if (!dbg->de_rnglists_context) {
585
143k
        return;
586
143k
    }
587
134
    rngcon = dbg->de_rnglists_context;
588
1.38k
    for ( ; i < dbg->de_rnglists_context_count; ++i) {
589
1.25k
        Dwarf_Rnglists_Context con = rngcon[i];
590
1.25k
        con->rc_offsets_array = 0;
591
1.25k
        con->rc_magic = 0;
592
1.25k
        con->rc_offset_entry_count = 0;
593
1.25k
        free(con);
594
1.25k
        rngcon[i] = 0;
595
1.25k
    }
596
134
    free(dbg->de_rnglists_context);
597
134
    dbg->de_rnglists_context = 0;
598
134
    dbg->de_rnglists_context_count = 0;
599
134
}
600
601
/*  Used by dwarfdump to print raw rnglists data. */
602
int
603
dwarf_get_rnglist_offset_index_value(
604
    Dwarf_Debug dbg,
605
    Dwarf_Unsigned context_index,
606
    Dwarf_Unsigned offsetentry_index,
607
    Dwarf_Unsigned * offset_value_out,
608
    Dwarf_Unsigned * global_offset_value_out,
609
    Dwarf_Error *error)
610
3.61k
{
611
3.61k
    Dwarf_Rnglists_Context con = 0;
612
3.61k
    unsigned offset_len = 0;
613
3.61k
    Dwarf_Small *offsetptr = 0;
614
3.61k
    Dwarf_Unsigned targetoffset = 0;
615
3.61k
    Dwarf_Unsigned localoffset = 0;
616
617
3.61k
    CHECK_DBG(dbg,error,"dwarf_get_rnglist_offset_index_value()");
618
3.61k
    if (!dbg->de_rnglists_context) {
619
0
        return DW_DLV_NO_ENTRY;
620
0
    }
621
622
3.61k
    if (!dbg->de_rnglists_context_count) {
623
0
        return DW_DLV_NO_ENTRY;
624
0
    }
625
3.61k
    if (context_index >= dbg->de_rnglists_context_count) {
626
0
        return DW_DLV_NO_ENTRY;
627
0
    }
628
3.61k
    con = dbg->de_rnglists_context[context_index];
629
3.61k
    if (con->rc_magic != RNGLISTS_MAGIC) {
630
0
        _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL,
631
0
            "DW_DLE_DBG_NULL "
632
0
            "rnglists context magic wrong "
633
0
            "not RNGLISTS_MAGIC");
634
0
        return DW_DLV_ERROR;
635
0
    }
636
3.61k
    if (offsetentry_index >= con->rc_offset_entry_count) {
637
0
        return DW_DLV_NO_ENTRY;
638
0
    }
639
3.61k
    offset_len  = con->rc_offset_size;
640
3.61k
    localoffset = offsetentry_index*offset_len;
641
3.61k
    offsetptr   = con->rc_offsets_array + localoffset;
642
3.61k
    if ((con->rc_offsets_off_in_sect +localoffset +
643
3.61k
        offset_len) >
644
3.61k
        con->rc_past_last_rnglist_offset) {
645
0
        dwarfstring m;
646
647
0
        dwarfstring_constructor(&m);
648
0
        dwarfstring_append_printf_u(&m,
649
0
            "DW_DLE_RNGLISTS_ERROR "
650
0
            "dwarf_get_rnglist_offset_index_value() "
651
0
            " Offset for index %u is too large. ",
652
0
            offsetentry_index);
653
0
        _dwarf_error_string(dbg, error,DW_DLE_RNGLISTS_ERROR,
654
0
            dwarfstring_string(&m));
655
0
        dwarfstring_destructor(&m);
656
0
        return DW_DLV_ERROR;
657
658
0
    }
659
3.61k
    READ_UNALIGNED_CK(dbg,targetoffset,Dwarf_Unsigned,
660
3.61k
        offsetptr,
661
3.61k
        offset_len,error,con->rc_endaddr);
662
3.61k
    if (offset_value_out) {
663
3.61k
        *offset_value_out = targetoffset;
664
3.61k
    }
665
3.61k
    if (global_offset_value_out) {
666
3.61k
        *global_offset_value_out = targetoffset +
667
3.61k
            con->rc_offsets_off_in_sect;
668
3.61k
    }
669
3.61k
    return DW_DLV_OK;
670
3.61k
}
671
672
/*  Used by dwarfdump to print basic data from the
673
    data generated to look at a specific rangelist
674
    as returned by  dwarf_rnglists_index_get_rle_head()
675
    or dwarf_rnglists_offset_get_rle_head. */
676
int dwarf_get_rnglist_head_basics(
677
    Dwarf_Rnglists_Head head,
678
    Dwarf_Unsigned * rle_count,
679
    Dwarf_Unsigned * rle_version,
680
    Dwarf_Unsigned * rnglists_index_returned,
681
    Dwarf_Unsigned * bytes_total_in_rle,
682
    Dwarf_Half     * offset_size,
683
    Dwarf_Half     * address_size,
684
    Dwarf_Half     * segment_selector_size,
685
    Dwarf_Unsigned * overall_offset_of_this_context,
686
    Dwarf_Unsigned * total_length_of_this_context,
687
    Dwarf_Unsigned * offset_table_offset,
688
    Dwarf_Unsigned * offset_table_entrycount,
689
    Dwarf_Bool     * rnglists_base_present,
690
    Dwarf_Unsigned * rnglists_base,
691
    Dwarf_Bool     * rnglists_base_address_present,
692
    Dwarf_Unsigned * rnglists_base_address,
693
    Dwarf_Bool     * rnglists_debug_addr_base_present,
694
    Dwarf_Unsigned * rnglists_debug_addr_base,
695
    Dwarf_Error *error)
696
0
{
697
0
    Dwarf_Rnglists_Context rngcontext = 0;
698
699
0
    if (!head || (!head->rh_dbg) ||
700
0
        head->rh_magic != RNGLISTS_MAGIC) {
701
0
        _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL,
702
0
            "DW_DLE_DBG_NULL "
703
0
            "NULL or invalid Dwarf_Rnglists_Head "
704
0
            "argument passed to "
705
0
            "dwarf_get_rnglist_head_basics()");
706
0
        return DW_DLV_ERROR;
707
0
    }
708
0
    *rle_count = head->rh_count;
709
0
    *rle_version = head->rh_version;
710
0
    *rnglists_index_returned = head->rh_index;
711
0
    *bytes_total_in_rle = head->rh_bytes_total;
712
0
    *offset_size = head->rh_offset_size;
713
0
    *address_size = head->rh_address_size;
714
0
    *segment_selector_size = head->rh_segment_selector_size;
715
0
    rngcontext = head->rh_localcontext;
716
0
    if (rngcontext) {
717
0
        *overall_offset_of_this_context =
718
0
            rngcontext->rc_header_offset;
719
0
        *total_length_of_this_context = rngcontext->rc_length;
720
0
        *offset_table_offset = rngcontext->rc_offsets_off_in_sect;
721
0
        *offset_table_entrycount = rngcontext->rc_offset_entry_count;
722
0
    }
723
0
    *rnglists_base_present = head->rh_at_rnglists_base_present;
724
0
    *rnglists_base= head->rh_at_rnglists_base;
725
726
0
    *rnglists_base_address_present = head->rh_cu_base_address_present;
727
0
    *rnglists_base_address= head->rh_cu_base_address;
728
729
0
    *rnglists_debug_addr_base_present = head->rh_cu_addr_base_present;
730
0
    *rnglists_debug_addr_base  = head->rh_cu_addr_base;
731
0
    return DW_DLV_OK;
732
0
}
733
734
/*  Used by dwarfdump to print raw rnglists data.
735
    Enables printing of details about the Range List Table
736
    Headers, one header per call. Index starting at 0.
737
    Returns DW_DLV_NO_ENTRY if index is too high for the table.
738
    A .debug_rnglists section may contain any number
739
    of Range List Table Headers with their details.  */
740
int dwarf_get_rnglist_context_basics(
741
    Dwarf_Debug dbg,
742
    Dwarf_Unsigned context_index,
743
    Dwarf_Unsigned * header_offset,
744
    Dwarf_Small    * offset_size,
745
    Dwarf_Small    * extension_size,
746
    unsigned       * version, /* 5 */
747
    Dwarf_Small    * address_size,
748
    Dwarf_Small    * segment_selector_size,
749
    Dwarf_Unsigned * offset_entry_count,
750
    Dwarf_Unsigned * offset_of_offset_array,
751
    Dwarf_Unsigned * offset_of_first_rangeentry,
752
    Dwarf_Unsigned * offset_past_last_rangeentry,
753
    Dwarf_Error *error)
754
709
{
755
709
    Dwarf_Rnglists_Context con = 0;
756
757
709
    CHECK_DBG(dbg,error,"dwarf_get_rnglist_context_basics()");
758
709
    if (!dbg->de_rnglists_context_count) {
759
0
        return DW_DLV_NO_ENTRY;
760
0
    }
761
709
    if (context_index >= dbg->de_rnglists_context_count) {
762
0
        return DW_DLV_NO_ENTRY;
763
0
    }
764
709
    con = dbg->de_rnglists_context[context_index];
765
709
    if (con->rc_magic != RNGLISTS_MAGIC) {
766
0
        _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL,
767
0
            "DW_DLE_DBG_NULL "
768
0
            "rnglists context "
769
0
            "not RNGLISTS_MAGIC "
770
0
            "in dwarf_get_rnglist_context_basics()");
771
0
        return DW_DLV_ERROR;
772
0
    }
773
709
    if (header_offset) {
774
709
        *header_offset = con->rc_header_offset;
775
709
    }
776
709
    if (offset_size) {
777
709
        *offset_size = con->rc_offset_size;
778
709
    }
779
709
    if (extension_size) {
780
709
        *extension_size = con->rc_extension_size;
781
709
    }
782
709
    if (version) {
783
709
        *version = con->rc_version;
784
709
    }
785
709
    if (address_size) {
786
709
        *address_size = con->rc_address_size;
787
709
    }
788
709
    if (segment_selector_size) {
789
709
        *segment_selector_size = con->rc_segment_selector_size;
790
709
    }
791
709
    if (offset_entry_count) {
792
709
        *offset_entry_count = con->rc_offset_entry_count;
793
709
    }
794
709
    if (offset_of_offset_array) {
795
709
        *offset_of_offset_array = con->rc_offsets_off_in_sect;
796
709
    }
797
709
    if (offset_of_first_rangeentry) {
798
709
        *offset_of_first_rangeentry = con->rc_first_rnglist_offset;
799
709
    }
800
709
    if (offset_past_last_rangeentry) {
801
709
        *offset_past_last_rangeentry =
802
709
            con->rc_past_last_rnglist_offset;
803
709
    }
804
709
    return DW_DLV_OK;
805
709
}
806
807
/*  Used by dwarfdump to print raw rnglists data.
808
    entry offset is offset_of_first_rangeentry.
809
    Stop when the returned *next_entry_offset
810
    is == offset_past_last_rangentry (from
811
    dwarf_get_rnglist_context_plus).
812
    This only makes sense within those ranges.
813
    This retrieves raw detail from the section,
814
    no base values or anything are added.
815
    So this returns raw individual entries
816
    for a single rnglist header, meaning a
817
    a single Dwarf_Rnglists_Context.  */
818
int dwarf_get_rnglist_rle(
819
    Dwarf_Debug dbg,
820
    Dwarf_Unsigned contextnumber,
821
    Dwarf_Unsigned entry_offset,
822
    Dwarf_Unsigned endoffset,
823
    unsigned *entrylen,
824
    unsigned *entry_kind,
825
    Dwarf_Unsigned *entry_operand1,
826
    Dwarf_Unsigned *entry_operand2,
827
    Dwarf_Error *error)
828
4.86k
{
829
4.86k
    Dwarf_Rnglists_Context con = 0;
830
4.86k
    Dwarf_Small *data = 0;
831
4.86k
    Dwarf_Small *enddata = 0;
832
4.86k
    int res = 0;
833
4.86k
    unsigned address_size = 0;
834
4.86k
    Dwarf_Unsigned secsize = 0;
835
836
4.86k
    CHECK_DBG(dbg,error,"dwarf_get_rnglist_rle()");
837
4.86k
    secsize = dbg->de_debug_rnglists.dss_size;
838
4.86k
    if (!dbg->de_rnglists_context_count) {
839
0
        return DW_DLV_NO_ENTRY;
840
0
    }
841
4.86k
    if (!dbg->de_rnglists_context_count) {
842
0
        return DW_DLV_NO_ENTRY;
843
0
    }
844
4.86k
    if (contextnumber >= dbg->de_rnglists_context_count) {
845
0
        return DW_DLV_NO_ENTRY;
846
0
    }
847
4.86k
    if (entry_offset >= secsize) {
848
0
        return DW_DLV_NO_ENTRY;
849
0
    }
850
4.86k
    if (endoffset > secsize) {
851
0
        _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR,
852
0
            " DW_DLE_RNGLISTS_ERROR "
853
0
            "The end offset to "
854
0
            "dwarf_get_rnglist_rle() is "
855
0
            "too large for the section");
856
0
        return DW_DLV_ERROR;
857
0
    }
858
4.86k
    if (endoffset <= entry_offset) {
859
0
        _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR,
860
0
            " DW_DLE_RNGLISTS_ERROR "
861
0
            "The end offset to "
862
0
            "dwarf_get_rnglist_rle() is smaller than "
863
0
            "the entry offset! Corrupt data");
864
0
        return DW_DLV_ERROR;
865
0
    }
866
4.86k
    if ((entry_offset +1) > endoffset) {
867
        /*  The read_single_rle_entry call will need
868
            at least 1 byte as it reads at least one
869
            ULEB */
870
0
        dwarfstring m;
871
0
        dwarfstring_constructor(&m);
872
0
        dwarfstring_append_printf_u(&m,
873
0
            " DW_DLE_RNGLISTS_ERROR "
874
0
            "The entry offset+1 (%lu) "
875
0
            "dwarf_get_rnglist_rle() is too close to the"
876
0
            " end",entry_offset+1);
877
0
        dwarfstring_append_printf_u(&m,
878
0
            " of the offset of the end of the entry (%lu)"
879
0
            " Apparently corrupt Dwarf",endoffset);
880
0
        _dwarf_error_string(dbg, error, DW_DLE_RNGLISTS_ERROR,
881
0
            dwarfstring_string(&m));
882
0
        dwarfstring_destructor(&m);
883
0
        return DW_DLV_ERROR;
884
0
    }
885
4.86k
    data = dbg->de_debug_rnglists.dss_data +
886
4.86k
        entry_offset;
887
4.86k
    enddata = dbg->de_debug_rnglists.dss_data +
888
4.86k
        endoffset;
889
890
4.86k
    con = dbg->de_rnglists_context[contextnumber];
891
4.86k
    address_size = con->rc_address_size;
892
4.86k
    res = read_single_rle_entry(dbg,
893
4.86k
        data,entry_offset,enddata,
894
4.86k
        address_size,entrylen,
895
4.86k
        entry_kind, entry_operand1, entry_operand2,
896
4.86k
        error);
897
4.86k
    return res;
898
4.86k
}
899
900
static int
901
_dwarf_which_rnglists_context(Dwarf_Debug dbg,
902
    Dwarf_CU_Context ctx,
903
    Dwarf_Unsigned rnglist_offset,
904
    Dwarf_Unsigned *index,
905
    Dwarf_Error *error)
906
0
{
907
0
    Dwarf_Unsigned count;
908
0
    Dwarf_Rnglists_Context *array;
909
0
    Dwarf_Unsigned i = 0;
910
911
0
    array = dbg->de_rnglists_context;
912
0
    count = dbg->de_rnglists_context_count;
913
    /*  Using the slow way, a simple linear search. */
914
0
    if (!ctx->cc_rnglists_base_present) {
915
        /* We look at the location of each rnglist context
916
            to find one with the offset the DIE gave us. */
917
0
        for ( i = 0 ; i < count; ++i) {
918
0
            Dwarf_Rnglists_Context rcx = array[i];
919
0
            Dwarf_Unsigned rcxoff = rcx->rc_header_offset;
920
0
            Dwarf_Unsigned rcxend = rcxoff +
921
0
                rcx->rc_length;
922
923
0
            if (rnglist_offset < rcxoff){
924
0
                continue;
925
0
            }
926
0
            if (rnglist_offset < rcxend ){
927
0
                *index = i;
928
0
                return DW_DLV_OK;
929
0
            }
930
0
        }
931
0
        {
932
0
            dwarfstring m;
933
934
0
            dwarfstring_constructor(&m);
935
0
            dwarfstring_append_printf_u(&m,
936
0
                "DW_DLE_RNGLISTS_ERROR: rnglist ran off end "
937
0
                " finding target offset of"
938
0
                " 0x%" DW_PR_XZEROS DW_PR_DUx ,rnglist_offset);
939
0
            dwarfstring_append(&m,
940
0
                " Not found anywhere in .debug_rnglists "
941
0
                "data. Corrupted data?");
942
0
            _dwarf_error_string(dbg,error,
943
0
                DW_DLE_RNGLISTS_ERROR,
944
0
                dwarfstring_string(&m));
945
0
            dwarfstring_destructor(&m);
946
0
            return DW_DLV_ERROR;
947
0
        }
948
0
    } else {
949
        /*  We have a DW_AT_rnglists_base (cc_rangelists_base),
950
            let's use it. */
951
0
        Dwarf_Unsigned lookfor = 0;;
952
953
0
        lookfor = ctx->cc_rnglists_base;
954
0
        for ( i = 0 ; i < count; ++i) {
955
0
            dwarfstring m;
956
957
0
            Dwarf_Rnglists_Context rcx = array[i];
958
0
            if (rcx->rc_offsets_off_in_sect == lookfor){
959
0
                *index = i;
960
0
                return DW_DLV_OK;
961
0
            }
962
0
            if (rcx->rc_offsets_off_in_sect < lookfor){
963
0
                continue;
964
0
            }
965
966
0
            dwarfstring_constructor(&m);
967
0
            dwarfstring_append_printf_u(&m,
968
0
                "DW_DLE_RNGLISTS_ERROR: rnglists base of "
969
0
                " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor);
970
0
            dwarfstring_append_printf_u(&m,
971
0
                " was not found though we are now at base "
972
0
                " 0x%" DW_PR_XZEROS DW_PR_DUx ,
973
0
                rcx->rc_offsets_off_in_sect);
974
0
            _dwarf_error_string(dbg,error,
975
0
                DW_DLE_RNGLISTS_ERROR,
976
0
                dwarfstring_string(&m));
977
0
            dwarfstring_destructor(&m);
978
0
            return DW_DLV_ERROR;
979
0
        }
980
0
        {
981
0
            dwarfstring m;
982
983
0
            dwarfstring_constructor(&m);
984
0
            dwarfstring_append_printf_u(&m,
985
0
                "DW_DLE_RNGLISTS_ERROR: rnglist base of "
986
0
                " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor);
987
0
            dwarfstring_append(&m,
988
0
                " was not found anywhere in .debug_rnglists "
989
0
                "data. Corrupted data?");
990
0
            _dwarf_error_string(dbg,error,
991
0
                DW_DLE_RNGLISTS_ERROR,
992
0
                dwarfstring_string(&m));
993
0
            dwarfstring_destructor(&m);
994
0
            return DW_DLV_ERROR;
995
0
        }
996
0
    }
997
    /*  ASSERT: This line cannot be reached. */
998
0
}
999
1000
void
1001
dwarf_dealloc_rnglists_head(Dwarf_Rnglists_Head h)
1002
0
{
1003
0
    Dwarf_Debug dbg = 0;
1004
1005
0
    if (!h || !h->rh_dbg || h->rh_magic != RNGLISTS_MAGIC) {
1006
0
        return;
1007
0
    }
1008
0
    dbg = h->rh_dbg;
1009
0
    h->rh_magic = 0;
1010
0
    dwarf_dealloc(dbg,h,DW_DLA_RNGLISTS_HEAD);
1011
0
    return;
1012
0
}
1013
1014
/*  Caller will eventually free as appropriate. */
1015
static int
1016
alloc_rle_and_append_to_list(Dwarf_Debug dbg,
1017
    Dwarf_Rnglists_Head rctx,
1018
    Dwarf_Rnglists_Entry *e_out,
1019
    Dwarf_Error *error)
1020
0
{
1021
0
    Dwarf_Rnglists_Entry e = 0;
1022
1023
0
    e = malloc(sizeof(struct Dwarf_Rnglists_Entry_s));
1024
0
    if (!e) {
1025
0
        _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
1026
0
            "DW_DLE_ALLOC_FAIL: Out of memory in "
1027
0
            "building list of rnglists entries on a DIE.");
1028
0
        return DW_DLV_ERROR;
1029
0
    }
1030
0
    memset(e,0,sizeof(struct Dwarf_Rnglists_Entry_s));
1031
0
    if (rctx->rh_first) {
1032
0
        rctx->rh_last->rle_next = e;
1033
0
        rctx->rh_last = e;
1034
0
    } else {
1035
0
        rctx->rh_first = e;
1036
0
        rctx->rh_last = e;
1037
0
    }
1038
0
    rctx->rh_count++;
1039
0
    *e_out = e;
1040
0
    return DW_DLV_OK;
1041
0
}
1042
1043
/*  Read the group of rangelists entries, and
1044
    finally build an array of Dwarf_Rnglists_Entry
1045
    records. Attach to rctx here.
1046
    Since on error the caller will destruct the rctx
1047
    and we ensure to attach allocations there
1048
    the caller will destruct the allocations here
1049
    in case we return DW_DLV_ERROR*/
1050
static int
1051
build_array_of_rle(Dwarf_Debug dbg,
1052
    Dwarf_Rnglists_Head rctx,
1053
    Dwarf_Error *error)
1054
0
{
1055
0
    int res = 0;
1056
0
    Dwarf_Small * data        = rctx->rh_rlepointer;
1057
0
    Dwarf_Unsigned dataoffset = rctx->rh_rlearea_offset;
1058
0
    Dwarf_Small *enddata      = rctx->rh_end_data_area;
1059
0
    unsigned address_size     = rctx->rh_address_size;
1060
0
    Dwarf_Unsigned bytescounttotal= 0;
1061
0
    Dwarf_Unsigned latestbaseaddr = 0;
1062
0
    Dwarf_Bool foundbaseaddr        = FALSE;
1063
0
    int done = FALSE;
1064
0
    Dwarf_Bool no_debug_addr_available = FALSE;
1065
1066
0
    if (rctx->rh_cu_base_address_present) {
1067
        /*  The CU DIE had DW_AT_low_pc
1068
            and it is a base address. */
1069
0
        latestbaseaddr = rctx->rh_cu_base_address;
1070
0
        foundbaseaddr  = TRUE;
1071
0
    }
1072
0
    for ( ; !done  ; ) {
1073
0
        unsigned entrylen = 0;
1074
0
        unsigned code = 0;
1075
0
        Dwarf_Unsigned val1 = 0;
1076
0
        Dwarf_Unsigned val2 = 0;
1077
0
        Dwarf_Addr addr1= 0;
1078
0
        Dwarf_Addr addr2 = 0;
1079
0
        Dwarf_Rnglists_Entry e = 0;
1080
1081
0
        res = read_single_rle_entry(dbg,
1082
0
            data,dataoffset, enddata,
1083
0
            address_size,&entrylen,
1084
0
            &code,&val1, &val2,error);
1085
0
        if (res != DW_DLV_OK) {
1086
0
            return res;
1087
0
        }
1088
0
        res = alloc_rle_and_append_to_list(dbg,rctx,&e,error);
1089
0
        if (res != DW_DLV_OK) {
1090
0
            return res;
1091
0
        }
1092
0
        e->rle_code = code,
1093
0
        e->rle_entrylen = entrylen;
1094
0
        e->rle_raw1 = val1;
1095
0
        e->rle_raw2 = val2;
1096
0
        bytescounttotal += entrylen;
1097
0
        data += entrylen;
1098
0
        if (code == DW_RLE_end_of_list) {
1099
0
            done = TRUE;
1100
0
            break;
1101
0
        }
1102
0
        switch(code) {
1103
0
        case DW_RLE_base_addressx:
1104
0
            if (no_debug_addr_available) {
1105
0
                res = DW_DLV_NO_ENTRY;
1106
0
            } else {
1107
0
                res = _dwarf_look_in_local_and_tied_by_index(
1108
0
                    dbg,rctx->rh_context,val1,&addr1,
1109
0
                    error);
1110
0
            }
1111
0
            if (res != DW_DLV_OK) {
1112
0
                no_debug_addr_available = TRUE;
1113
0
                e->rle_index_failed = TRUE;
1114
0
                e->rle_cooked1 = 0;
1115
0
                foundbaseaddr = FALSE;
1116
0
            } else {
1117
0
                foundbaseaddr = TRUE;
1118
0
                e->rle_cooked1 = addr1;
1119
0
                latestbaseaddr = addr1;
1120
0
            }
1121
0
            break;
1122
0
        case DW_RLE_startx_endx:
1123
0
            if (no_debug_addr_available) {
1124
0
                res = DW_DLV_NO_ENTRY;
1125
0
            } else {
1126
0
                res = _dwarf_look_in_local_and_tied_by_index(
1127
0
                    dbg,rctx->rh_context,val1,&addr1,
1128
0
                    error);
1129
0
            }
1130
0
            if (res != DW_DLV_OK) {
1131
0
                no_debug_addr_available = TRUE;
1132
0
                e->rle_index_failed = TRUE;
1133
0
                e->rle_cooked1 = 0;
1134
0
            } else {
1135
0
                e->rle_cooked1 = addr1;
1136
0
            }
1137
0
            if (no_debug_addr_available) {
1138
0
                res = DW_DLV_NO_ENTRY;
1139
0
            } else {
1140
0
                res = _dwarf_look_in_local_and_tied_by_index(
1141
0
                    dbg,rctx->rh_context,val2,&addr2,
1142
0
                    error);
1143
0
            }
1144
0
            if (res != DW_DLV_OK) {
1145
0
                no_debug_addr_available = TRUE;
1146
0
                e->rle_index_failed = TRUE;
1147
0
                e->rle_cooked2 = 0;
1148
0
                return res;
1149
0
            } else {
1150
0
                e->rle_cooked2 = addr2;
1151
0
            }
1152
0
            break;
1153
0
        case DW_RLE_startx_length:
1154
0
            if (no_debug_addr_available) {
1155
0
                res = DW_DLV_NO_ENTRY;
1156
0
            } else {
1157
0
                res = _dwarf_look_in_local_and_tied_by_index(
1158
0
                    dbg,rctx->rh_context,val1,&addr1,
1159
0
                    error);
1160
0
            }
1161
0
            if (res != DW_DLV_OK) {
1162
0
                no_debug_addr_available = TRUE;
1163
0
                e->rle_index_failed = TRUE;
1164
0
                e->rle_cooked2 = 0;
1165
0
                e->rle_cooked1 = 0;
1166
0
                return res;
1167
1168
0
            } else {
1169
0
                e->rle_cooked1 = addr1;
1170
0
                e->rle_cooked2 = val2+addr1;
1171
0
            }
1172
0
            break;
1173
0
        case DW_RLE_offset_pair:
1174
0
            if (foundbaseaddr) {
1175
0
                e->rle_cooked1 = val1+latestbaseaddr;
1176
0
                e->rle_cooked2 = val2+latestbaseaddr;
1177
0
            } else {
1178
                /*  Well, something failed, could be
1179
                    missing debug_addr. */
1180
0
                e->rle_index_failed = TRUE;
1181
0
                e->rle_cooked2 = 0;
1182
0
                e->rle_cooked1 = 0;
1183
0
            }
1184
0
            break;
1185
0
        case DW_RLE_base_address:
1186
0
            foundbaseaddr = TRUE;
1187
0
            latestbaseaddr = val1;
1188
0
            e->rle_cooked1 = val1;
1189
0
            break;
1190
0
        case DW_RLE_start_end:
1191
0
            e->rle_cooked1 = val1;
1192
0
            e->rle_cooked2 = val2;
1193
0
            break;
1194
0
        case DW_RLE_start_length:
1195
0
            e->rle_cooked1 = val1;
1196
0
            e->rle_cooked2 = val2+val1;
1197
0
            break;
1198
0
        default: {
1199
0
            dwarfstring m;
1200
1201
0
            dwarfstring_constructor(&m);
1202
0
            dwarfstring_append_printf_u(&m,
1203
0
                " DW_DLE_RNGLISTS_ERROR: "
1204
0
                " The .debug_rnglists "
1205
0
                " rangelist code 0x%x is unknown, "
1206
0
                " DWARF5 is corrupted.",code);
1207
0
            _dwarf_error_string(dbg, error,
1208
0
                DW_DLE_RNGLISTS_ERROR,
1209
0
                dwarfstring_string(&m));
1210
0
            dwarfstring_destructor(&m);
1211
0
            return DW_DLV_ERROR;
1212
0
        }
1213
0
        }
1214
0
    }
1215
0
    if (rctx->rh_count > 0) {
1216
0
        Dwarf_Rnglists_Entry* array = 0;
1217
0
        Dwarf_Rnglists_Entry cur = 0;
1218
0
        Dwarf_Unsigned i = 0;
1219
1220
        /*  Creating an array of pointers. */
1221
0
        array = (Dwarf_Rnglists_Entry*)malloc(
1222
0
            rctx->rh_count *sizeof(Dwarf_Rnglists_Entry));
1223
0
        if (!array) {
1224
0
            _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
1225
0
                "DW_DLE_ALLOC_FAIL: Out of memory in "
1226
0
                "turning list of rnglists entries on a DIE"
1227
0
                "into a pointer array");
1228
0
            return DW_DLV_ERROR;
1229
0
        }
1230
0
        cur = rctx->rh_first;
1231
0
        for ( ; i < rctx->rh_count; ++i) {
1232
0
            array[i] = cur;
1233
0
            cur = cur->rle_next;
1234
0
        }
1235
0
        rctx->rh_rnglists = array;
1236
0
        rctx->rh_first = 0;
1237
0
        rctx->rh_last = 0;
1238
0
    }
1239
0
    rctx->rh_bytes_total = bytescounttotal;
1240
0
    return DW_DLV_OK;
1241
0
}
1242
1243
/*  Build a head with all the relevent Entries
1244
    attached.
1245
*/
1246
int
1247
dwarf_rnglists_get_rle_head(
1248
    Dwarf_Attribute attr,
1249
    Dwarf_Half     theform,
1250
    /*  attr_val is either an offset
1251
        (theform == DW_FORM_sec_offset)
1252
        or an index DW_FORM_rnglistx. */
1253
    Dwarf_Unsigned attr_val,
1254
    Dwarf_Rnglists_Head *head_out,
1255
    Dwarf_Unsigned      *entries_count_out,
1256
    Dwarf_Unsigned      *global_offset_of_rle_set,
1257
    Dwarf_Error         *error)
1258
0
{
1259
0
    int res = 0;
1260
0
    Dwarf_Unsigned rnglists_contextnum = 0;
1261
0
    Dwarf_Small *table_base = 0;
1262
0
    Dwarf_Small *table_entry = 0;
1263
0
    Dwarf_Small *enddata = 0;
1264
0
    Dwarf_Rnglists_Context *array = 0;
1265
0
    Dwarf_Rnglists_Context rctx = 0;
1266
0
    Dwarf_Unsigned entrycount = 0;
1267
0
    unsigned offsetsize = 0;
1268
0
    Dwarf_Unsigned rle_global_offset = 0;
1269
0
    Dwarf_Rnglists_Head lhead = 0;
1270
0
    Dwarf_CU_Context ctx = 0;
1271
0
    struct Dwarf_Rnglists_Head_s shead;
1272
0
    Dwarf_Unsigned offset_in_rnglists = 0;
1273
0
    Dwarf_Debug dbg = 0;
1274
0
    Dwarf_Bool is_rnglistx = FALSE;
1275
1276
0
    if (!attr) {
1277
0
        _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL,
1278
0
            "DW_DLE_DBG_NULL "
1279
0
            "NULL attribute "
1280
0
            "argument passed to "
1281
0
            "dwarf_rnglists_get_rle_head()");
1282
0
        return DW_DLV_ERROR;
1283
0
    }
1284
0
    memset(&shead,0,sizeof(shead));
1285
0
    ctx = attr->ar_cu_context;
1286
0
    dbg = ctx->cc_dbg;
1287
0
    CHECK_DBG(dbg,error,
1288
0
        "dwarf_rnglists_get_rle_head() via attribute");
1289
0
    array = dbg->de_rnglists_context;
1290
0
    if (theform == DW_FORM_rnglistx) {
1291
0
        is_rnglistx = TRUE;
1292
0
    }
1293
    /*  ASSERT:  the 3 pointers just set are non-null */
1294
    /*  the context cc_rnglists_base gives the offset
1295
        of the array. of offsets (if cc_rnglists_base_present) */
1296
0
            offset_in_rnglists = attr_val;
1297
0
    if (is_rnglistx) {
1298
0
        if (ctx->cc_rnglists_base_present) {
1299
0
            offset_in_rnglists = ctx->cc_rnglists_base;
1300
1301
0
        } else {
1302
            /* FIXME: check in tied file for a cc_rnglists_base */
1303
0
            dwarfstring m;
1304
1305
0
            dwarfstring_constructor(&m);
1306
0
            dwarfstring_append_printf_u(&m,
1307
0
                "DW_DLE_RNGLISTS_ERROR: rnglists table index of"
1308
0
                " %u"  ,attr_val);
1309
0
            dwarfstring_append(&m,
1310
0
                " is unusable unless it is in a tied file."
1311
0
                " Possibly libdwarf is incomplete.FIXME");
1312
0
            _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
1313
0
                dwarfstring_string(&m));
1314
0
            dwarfstring_destructor(&m);
1315
0
            return DW_DLV_ERROR;
1316
0
        }
1317
0
    } else {
1318
0
        offset_in_rnglists = attr_val;
1319
0
    }
1320
0
    res = _dwarf_which_rnglists_context(dbg,ctx,
1321
0
        offset_in_rnglists,
1322
0
        &rnglists_contextnum,error);
1323
0
    if (res != DW_DLV_OK) {
1324
0
        return res;
1325
0
    }
1326
0
    rctx = array[rnglists_contextnum];
1327
0
    table_base = rctx->rc_offsets_array;
1328
0
    entrycount = rctx->rc_offset_entry_count;
1329
0
    offsetsize = rctx->rc_offset_size;
1330
0
    enddata = rctx->rc_endaddr;
1331
1332
0
    if (is_rnglistx && attr_val >= entrycount) {
1333
0
        dwarfstring m;
1334
1335
0
        dwarfstring_constructor(&m);
1336
0
        dwarfstring_append_printf_u(&m,
1337
0
            "DW_DLE_RNGLISTS_ERROR: rnglists table index of"
1338
0
            " %u"  ,attr_val);
1339
0
        dwarfstring_append_printf_u(&m,
1340
0
            " too large for table of %u "
1341
0
            "entries.",entrycount);
1342
0
        _dwarf_error_string(dbg,error,
1343
0
            DW_DLE_RNGLISTS_ERROR,
1344
0
            dwarfstring_string(&m));
1345
0
        dwarfstring_destructor(&m);
1346
0
        return DW_DLV_ERROR;
1347
0
    }
1348
0
    shead.rh_context = ctx;
1349
0
    shead.rh_magic = RNGLISTS_MAGIC;
1350
0
    shead.rh_localcontext = rctx;
1351
0
    shead.rh_index = rnglists_contextnum;
1352
0
    shead.rh_version = rctx->rc_version;
1353
0
    shead.rh_offset_size = offsetsize;
1354
0
    shead.rh_address_size  = rctx->rc_address_size;
1355
0
    shead.rh_segment_selector_size =
1356
0
        rctx->rc_segment_selector_size;
1357
1358
    /*  DW_AT_rnglists_base from CU */
1359
0
    shead.rh_at_rnglists_base_present =
1360
0
        ctx->cc_rnglists_base_present;
1361
0
    shead.rh_at_rnglists_base =  ctx->cc_rnglists_base;
1362
1363
    /*  DW_AT_low_pc, if present.  From CU */
1364
0
    shead.rh_cu_base_address_present = ctx->cc_low_pc_present;
1365
0
    shead.rh_cu_base_address = ctx->cc_low_pc;
1366
1367
    /*  base address DW_AT_addr_base of our part of
1368
        .debug_addr, from CU */
1369
0
    shead.rh_cu_addr_base = ctx->cc_addr_base;
1370
0
    shead.rh_cu_addr_base_present = ctx->cc_addr_base_present;
1371
0
    if (is_rnglistx) {
1372
0
        Dwarf_Unsigned table_entryval = 0;
1373
1374
0
        table_entry = attr_val*offsetsize + table_base;
1375
        /*  No malloc here yet so no leak if the macro returns
1376
            DW_DLV_ERROR */
1377
0
        READ_UNALIGNED_CK(dbg,table_entryval, Dwarf_Unsigned,
1378
0
            table_entry,offsetsize,error,enddata);
1379
0
        rle_global_offset = rctx->rc_offsets_off_in_sect +
1380
0
            table_entryval;
1381
0
    } else {
1382
0
        rle_global_offset = attr_val;
1383
0
    }
1384
1385
0
    shead.rh_end_data_area = enddata;
1386
0
    shead.rh_rlearea_offset = rle_global_offset;
1387
0
    shead.rh_rlepointer = rle_global_offset +
1388
0
        dbg->de_debug_rnglists.dss_data;
1389
0
    lhead = (Dwarf_Rnglists_Head)
1390
0
        _dwarf_get_alloc(dbg,DW_DLA_RNGLISTS_HEAD,1);
1391
0
    if (!lhead) {
1392
0
        _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
1393
0
            "Allocating a Dwarf_Rnglists_Head struct fails"
1394
0
            " in libdwarf function "
1395
0
            "dwarf_rnglists_index_get_rle_head()");
1396
0
        return DW_DLV_ERROR;
1397
0
    }
1398
0
    shead.rh_dbg = dbg;
1399
0
    *lhead = shead;
1400
0
    res = build_array_of_rle(dbg,lhead,error);
1401
0
    if (res != DW_DLV_OK) {
1402
0
        dwarf_dealloc(dbg,lhead,DW_DLA_RNGLISTS_HEAD);
1403
0
        return res;
1404
0
    }
1405
0
    if (global_offset_of_rle_set) {
1406
0
        *global_offset_of_rle_set = rle_global_offset;
1407
0
    }
1408
    /*  Caller needs the head pointer else there will be leaks. */
1409
0
    *head_out = lhead;
1410
0
    if (entries_count_out) {
1411
0
        *entries_count_out = lhead->rh_count;
1412
0
    }
1413
0
    return DW_DLV_OK;
1414
0
}
1415
1416
/*  As of 18 Aug 2020
1417
    this ignores null pointer inputs for the various
1418
    pointers-returning-values (rle_value_out etc)
1419
    for the convenience of callers.  */
1420
int
1421
dwarf_get_rnglists_entry_fields_a(
1422
    Dwarf_Rnglists_Head head,
1423
    Dwarf_Unsigned  entrynum,
1424
    unsigned       *entrylen,
1425
    unsigned       *rle_value_out,
1426
    Dwarf_Unsigned *raw1,
1427
    Dwarf_Unsigned *raw2,
1428
    Dwarf_Bool     *debug_addr_unavailable,
1429
    Dwarf_Unsigned *cooked1,
1430
    Dwarf_Unsigned *cooked2,
1431
    Dwarf_Error *error)
1432
0
{
1433
0
    Dwarf_Rnglists_Entry e = 0;
1434
1435
0
    if (!head || !head->rh_dbg || head->rh_magic != RNGLISTS_MAGIC) {
1436
0
        _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL,
1437
0
            "DW_DLE_DBG_NULL "
1438
0
            "NULL or invalid Dwarf_Rnglists_Head "
1439
0
            "argument passed to "
1440
0
            "dwarf_get_rnglists_entry_fields_a()");
1441
0
        return DW_DLV_ERROR;
1442
0
    }
1443
0
    if (entrynum >= head->rh_count) {
1444
0
        return DW_DLV_NO_ENTRY;
1445
0
    }
1446
0
    e = head->rh_rnglists[entrynum];
1447
0
    if (entrylen) {
1448
0
        *entrylen  = e->rle_entrylen;
1449
0
    }
1450
0
    if (rle_value_out) {
1451
0
        *rle_value_out = e->rle_code;
1452
0
    }
1453
0
    if (raw1) {
1454
0
        *raw1      = e->rle_raw1;
1455
0
    }
1456
0
    if (raw2) {
1457
0
        *raw2      = e->rle_raw2;
1458
0
    }
1459
0
    if (debug_addr_unavailable) {
1460
0
        *debug_addr_unavailable = e->rle_index_failed;
1461
0
    }
1462
0
    if (cooked1) {
1463
0
        *cooked1   = e->rle_cooked1;
1464
0
    }
1465
0
    if (cooked2) {
1466
0
        *cooked2   = e->rle_cooked2;
1467
0
    }
1468
0
    return DW_DLV_OK;
1469
0
}
1470
1471
/*  Deals with both fully and partially build head */
1472
static void
1473
_dwarf_free_rnglists_head(Dwarf_Rnglists_Head head)
1474
0
{
1475
0
    if (head->rh_first) {
1476
        /* partially built head. */
1477
        /*  ASSERT: rh_rnglists is NULL */
1478
0
        Dwarf_Rnglists_Entry cur = head->rh_first;
1479
0
        Dwarf_Rnglists_Entry next = 0;
1480
1481
0
        for ( ; cur ; cur = next) {
1482
0
            next = cur->rle_next;
1483
0
            free(cur);
1484
0
        }
1485
0
        head->rh_first = 0;
1486
0
        head->rh_last = 0;
1487
0
        head->rh_count = 0;
1488
0
    } else {
1489
        /*  ASSERT: rh_first and rh_last are NULL */
1490
        /* fully built head. */
1491
0
        Dwarf_Unsigned i = 0;
1492
1493
        /* Deal with the array form. */
1494
0
        for ( ; i < head->rh_count; ++i) {
1495
0
            free(head->rh_rnglists[i]);
1496
0
        }
1497
0
        free(head->rh_rnglists);
1498
0
        head->rh_rnglists = 0;
1499
0
    }
1500
0
}
1501
1502
void
1503
_dwarf_rnglists_head_destructor(void *head)
1504
0
{
1505
0
    Dwarf_Rnglists_Head h = head;
1506
1507
0
    _dwarf_free_rnglists_head(h);
1508
0
}