File: print_loclists.c

package info (click to toggle)
dwarfutils 20201201-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 11,868 kB
  • sloc: ansic: 104,667; sh: 5,947; cpp: 4,675; python: 878; makefile: 646; awk: 11
file content (368 lines) | stat: -rw-r--r-- 11,439 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/*
Copyright (C) 2020 David Anderson. All Rights Reserved.

    This program is free software; you can redistribute it
    and/or modify it under the terms of version 2 of the GNU
    General Public License as published by the Free Software
    Foundation.

    This program is distributed in the hope that it would
    be useful, but WITHOUT ANY WARRANTY; without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.

    Further, this software is distributed without any warranty
    that it is free of the rightful claim of any third person
    regarding infringement or the like.  Any license provided
    herein, whether implied or otherwise, applies only to
    this software file.  Patent licenses, if any, provided
    herein do not apply to combinations of this program with
    other software, or any other product whatsoever.

    You should have received a copy of the GNU General Public
    License along with this program; if not, write the Free
    Software Foundation, Inc., 51 Franklin Street - Fifth
    Floor, Boston MA 02110-1301, USA.
*/

/*  DWARF5 has the new .debug_loclists section.
    Here we print that data.
    The raw printing covers all the content of the
    section but without relating it to any
    compilation unit.

    Printing the actual address means printing
    with the actual DIEs on hand.
*/

#include "config.h"
#include "globals.h"
#include "esb.h"
#include "esb_using_functions.h"
#include "sanitized.h"

static void
print_sec_name(Dwarf_Debug dbg)
{
    struct esb_s truename;
    char buf[DWARF_SECNAME_BUFFER_SIZE];

    esb_constructor_fixed(&truename,buf,sizeof(buf));
    get_true_section_name(dbg,".debug_loclists",
        &truename,TRUE);
    printf("\n%s\n\n",sanitized(esb_get_string(&truename)));
    esb_destructor(&truename);
}

static int
print_offset_entry_table(Dwarf_Debug dbg,
    Dwarf_Unsigned contextnum,
    Dwarf_Unsigned offset_entry_count,
    Dwarf_Error *error)
{
    Dwarf_Unsigned e = 0;
    unsigned colmax = 4;
    unsigned col = 0;
    int res = 0;
    int hasnewline = TRUE;

    for ( ; e < offset_entry_count; ++e) {
        Dwarf_Unsigned value = 0;

        if (e == 0) {
            printf("   Location Offset Table :\n");
        }
        hasnewline = FALSE;
        res = dwarf_get_loclist_offset_index_value(dbg,
            contextnum,e,&value,0,error);
        if (res != DW_DLV_OK) {
            return res;
        }
        if (col == 0) {
            printf("   [%2" DW_PR_DUu "]",e);
        }
        printf(" 0x%" DW_PR_XZEROS DW_PR_DUx, value);
        col++;
        if (col == colmax) {
            printf("\n");
            hasnewline = TRUE;
            col = 0;
        }
    }
    if (!hasnewline) {
        printf("\n");
    }
    return DW_DLV_OK;
}

static void
print_opsbytes(Dwarf_Unsigned expr_ops_blocklen,
    Dwarf_Small* expr_ops)
{
    Dwarf_Unsigned i = 0;

    if (!expr_ops_blocklen) {
        return;
    }
    printf(" opsbytes:");
    for( ; i < expr_ops_blocklen; ++i ) {
        Dwarf_Small *b =  expr_ops+i;
        printf(" %02x", *b);
    }
    printf(" ");
}

/*  Print single raw lle */
static int
print_single_lle(UNUSEDARG Dwarf_Debug dbg,
    UNUSEDARG Dwarf_Unsigned contextnum,
    Dwarf_Unsigned lineoffset,
    Dwarf_Unsigned code,
    Dwarf_Unsigned v1,
    Dwarf_Unsigned v2,
    Dwarf_Unsigned expr_ops_blocklen,
    UNUSEDARG Dwarf_Unsigned expr_ops_offset,
    Dwarf_Small    *expr_ops,
    Dwarf_Unsigned entrylen)
{
    int res = DW_DLV_OK;

    const char *name = "";
    struct esb_s m;

    esb_constructor(&m);
    res = dwarf_get_LLE_name(code,&name);
    if (res != DW_DLV_OK) {
        /* ASSERT: res == DW_DLV_NO_ENTRY, see dwarf_names.c */
        esb_append_printf_u(&m, "<ERROR: lle code 0x%" DW_PR_DUx
            "unknown>",code);
    } else {
        esb_append(&m,name);
    }
    printf("    ");
    printf("<0x%" DW_PR_XZEROS DW_PR_DUx "> %-20s",
        lineoffset,esb_get_string(&m));
    switch(code) {
    case DW_LLE_end_of_list:
        printf("           ");
        printf("           ");
        break;
    case DW_LLE_base_addressx:
        printf(" 0x%" DW_PR_XZEROS DW_PR_DUx ,v1);
        printf("           ");
        break;
    case DW_LLE_startx_endx:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    case DW_LLE_startx_length:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    case DW_LLE_offset_pair:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    case DW_LLE_default_location:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    case DW_LLE_base_address:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1);
        printf("           ");
        break;
    case DW_LLE_start_end:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    case DW_LLE_start_length:
        printf(
            " 0x%" DW_PR_XZEROS DW_PR_DUx
            " 0x%" DW_PR_XZEROS DW_PR_DUx ,v1,v2);
        break;
    default:
        printf(" ERROR: Unknown LLE code in .debug_loclists. %s\n",
            esb_get_string(&m));
        simple_err_return_msg_either_action(res,
            esb_get_string(&m));
        break;
    }
    printf( " %" DW_PR_DUu,entrylen);
    esb_destructor(&m);
    if (glflags.verbose && expr_ops_blocklen > 0) {
        printf("\n");
        printf("    ");
        printf(" opslen %" DW_PR_DUu,expr_ops_blocklen);
        print_opsbytes(expr_ops_blocklen,expr_ops);
    }
    printf("\n");
    return res;
}

/*  Prints the raw content. Exactly as in .debug_loclists */
static int
print_entire_loclist(Dwarf_Debug dbg,
    Dwarf_Unsigned contextnumber,
    Dwarf_Unsigned offset_of_first_loc,
    Dwarf_Unsigned offset_past_last_locentry,
    Dwarf_Error *error)
{
    /*  These offsets are rnglists section global offsets,
        not rnglist context local offsets. */
    Dwarf_Unsigned curoffset = offset_of_first_loc;
    Dwarf_Unsigned endoffset = offset_past_last_locentry;
    int res = 0;
    Dwarf_Unsigned ct = 0;

    for ( ; curoffset < endoffset; ++ct ) {
        unsigned entrylen = 0;
        unsigned code = 0;
        Dwarf_Unsigned v1 = 0;
        Dwarf_Unsigned v2 = 0;
        Dwarf_Unsigned expr_ops_blocksize = 0;
        Dwarf_Unsigned expr_ops_offset = 0;
        Dwarf_Small   *expr_ops_data = 0;

        if (!ct) {
            printf("   Loc  (raw)\n");
            printf("     Offset      entryname            val1 "
                "      val2   entrylen\n");
        }
        /*  This returns ops data as in DWARF. No
            application of base addresses or anything. */
        res = dwarf_get_loclist_lle(dbg,contextnumber,
            curoffset,endoffset,
            &entrylen,
            &code,&v1,&v2,
            &expr_ops_blocksize,&expr_ops_offset,&expr_ops_data,
            error);
        if (res != DW_DLV_OK) {
            return res;
        }
        print_single_lle(dbg,contextnumber,curoffset,
            code,v1,v2,expr_ops_blocksize,expr_ops_offset,
            expr_ops_data,entrylen);
        curoffset += entrylen;
        if (curoffset > endoffset) {
            struct esb_s m;

            esb_constructor(&m);
            esb_append_printf_u(&m, "DW_DLE_USER_DECLARED_ERROR: "
                "final RLE in "
                ".debug_rnglists runs past end of its area "
                "so current offset 0x%" DW_PR_DUx,curoffset);

            esb_append_printf_u(&m," exceeds context 1-past-end"
                " offset of 0x%" DW_PR_DUx ".",endoffset);
            dwarf_error_creation(dbg,error,
                esb_get_string(&m));
            esb_destructor(&m);
            return DW_DLV_ERROR;
        }
    }
    return DW_DLV_OK;
}



int
print_raw_all_loclists(Dwarf_Debug dbg,
    Dwarf_Error *error)
{
    int res = 0;
    Dwarf_Unsigned count = 0;
    Dwarf_Unsigned i = 0;

    res = dwarf_load_loclists(dbg,&count,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    print_sec_name(dbg);

    printf(" Number of loclists contexts:  %" DW_PR_DUu "\n",
        count);
    for (i = 0; i < count ; ++i) {
        Dwarf_Unsigned header_offset = 0;
        Dwarf_Small   offset_size = 0;
        Dwarf_Small   extension_size = 0;
        unsigned      version = 0; /* 5 */
        Dwarf_Small   address_size = 0;
        Dwarf_Small   segment_selector_size = 0;
        Dwarf_Unsigned offset_entry_count = 0;
        Dwarf_Unsigned offset_of_offset_array = 0;
        Dwarf_Unsigned offset_of_first_locentry = 0;
        Dwarf_Unsigned offset_past_last_locentry = 0;

        res = dwarf_get_loclist_context_basics(dbg,i,
            &header_offset,
            &offset_size,
            &extension_size,
            &version,&address_size,&segment_selector_size,
            &offset_entry_count,&offset_of_offset_array,
            &offset_of_first_locentry,
            &offset_past_last_locentry,
            error);
        if (res != DW_DLV_OK) {
            struct esb_s m;

            esb_constructor(&m);
            esb_append_printf_u(&m,"ERROR: Getting debug_rnglists "
                "entry %u we unexpectedly stop early.",i);
            simple_err_return_msg_either_action(res,
                esb_get_string(&m));
            esb_destructor(&m);
            return res;
        }
        printf("  Context number         : %3" DW_PR_DUu "\n",i);
        printf("   Version               : %3u\n",version);
        printf("   address size          : %3u\n",address_size);
        printf("   offset size           : %3u\n",offset_size);
        if(glflags.verbose) {
            printf("   extension size        : %3u\n",extension_size);
        }
        printf("   segment selector size : %3u\n",
            segment_selector_size);
        printf("   offset entry count    : %3" DW_PR_DUu "\n",
            offset_entry_count);
        printf("   context size in bytes : %3" DW_PR_DUu "\n",
            offset_past_last_locentry - header_offset);
        if(glflags.verbose) {
            printf("   Offset in section     : 0x%"
                DW_PR_XZEROS DW_PR_DUx"\n",
                header_offset);
            printf("   Offset  of offsets    : 0x%"
                DW_PR_XZEROS DW_PR_DUx"\n",
                offset_of_offset_array);
            printf("   Offsetof first loc    : 0x%"
                DW_PR_XZEROS DW_PR_DUx"\n",
                offset_of_first_locentry);
            printf("   Offset past locations : 0x%"
                DW_PR_XZEROS DW_PR_DUx"\n",
                offset_past_last_locentry);
        }
        if (offset_entry_count) {
            res = print_offset_entry_table(dbg,i,offset_entry_count,
                error);
            if (res == DW_DLV_ERROR) {
                return res;
            }
        }
        if ((offset_of_first_locentry+1) <
            offset_past_last_locentry) {
            res = print_entire_loclist(dbg,i,
                offset_of_first_locentry,
                offset_past_last_locentry,
                error);
            if(res != DW_DLV_OK) {
                return res;
            }
        }
    }
    return DW_DLV_OK;
}