Coverage Report

Created: 2025-06-10 07:19

/src/ghostpdl/psi/idebug.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Debugging support for Ghostscript interpreter */
18
/* This file must always be compiled with DEBUG set. */
19
#undef DEBUG
20
#define DEBUG
21
#include "string_.h"
22
#include "ghost.h"
23
#include "gxalloc.h"    /* for procs for getting struct type */
24
#include "idebug.h"   /* defines interface */
25
#include "idict.h"
26
#include "iname.h"
27
#include "ipacked.h"
28
#include "istack.h"
29
#include "iutil.h"
30
#include "ivmspace.h"
31
#include "opdef.h"
32
33
/* Table of type name strings */
34
static const char *const type_strings[] = {
35
    REF_TYPE_DEBUG_PRINT_STRINGS
36
};
37
38
/* First unassigned type index */
39
extern const int tx_next_index; /* in interp.c */
40
41
/* Print a name. */
42
void
43
debug_print_name(const gs_memory_t *mem, const ref * pnref)
44
0
{
45
0
    ref sref;
46
47
0
    name_string_ref(mem, pnref, &sref);
48
0
    debug_print_string(mem, sref.value.const_bytes, r_size(&sref));
49
0
}
50
void
51
debug_print_name_index(const gs_memory_t *mem, name_index_t nidx)
52
0
{
53
0
    ref nref;
54
55
0
    name_index_ref(mem, nidx, &nref);
56
0
    debug_print_name(mem, &nref);
57
0
}
58
59
/* Print a ref. */
60
static void
61
debug_print_full_ref(const gs_memory_t *mem, const ref * pref)
62
0
{
63
0
    uint size = r_size(pref);
64
0
    ref nref;
65
66
0
    dmprintf1(mem, "(%x)", r_type_attrs(pref));
67
0
    switch (r_type(pref)) {
68
0
        case t_array:
69
0
            dmprintf2(mem, "array(%u)"PRI_INTPTR, size, (intptr_t)pref->value.refs);
70
0
            break;
71
0
        case t_astruct:
72
0
            goto strct;
73
0
        case t_boolean:
74
0
            dmprintf1(mem, "boolean %x", pref->value.boolval);
75
0
            break;
76
0
        case t_device:
77
0
            dmprintf1(mem, "device "PRI_INTPTR, (intptr_t) pref->value.pdevice->device);
78
0
            break;
79
0
        case t_dictionary:
80
0
            dmprintf3(mem, "dict(%u/%u)"PRI_INTPTR,
81
0
                     dict_length(pref), dict_maxlength(pref),
82
0
                     (intptr_t)pref->value.pdict);
83
0
            break;
84
0
        case t_file:
85
0
            dmprintf1(mem, "file "PRI_INTPTR, (intptr_t)pref->value.pfile);
86
0
            break;
87
0
        case t_fontID:
88
0
            goto strct;
89
0
        case t_integer:
90
0
            dmprintf1(mem, "int %"PRIpsint, pref->value.intval);
91
0
            break;
92
0
        case t_mark:
93
0
            dmprintf(mem, "mark");
94
0
            break;
95
0
        case t_mixedarray:
96
0
            dmprintf2(mem, "mixed packedarray(%u)"PRI_INTPTR"", size,
97
0
                     (intptr_t)pref->value.packed);
98
0
            break;
99
0
        case t_name:
100
0
            dmprintf2(mem, "name("PRI_INTPTR"#%u)", (intptr_t)pref->value.pname,
101
0
                     name_index(mem, pref));
102
0
            debug_print_name(mem, pref);
103
0
            break;
104
0
        case t_null:
105
0
            dmprintf(mem, "null");
106
0
            break;
107
0
        case t_oparray:
108
0
            dmprintf2(mem, "op_array(%u)"PRI_INTPTR":", size, (intptr_t) pref->value.const_refs);
109
0
            {
110
0
                const op_array_table *opt = get_op_array(mem, size);
111
112
0
                name_index_ref(mem, opt->nx_table[size - opt->base_index], &nref);
113
0
            }
114
0
            debug_print_name(mem, &nref);
115
0
            break;
116
0
        case t_operator:
117
0
            dmprintf1(mem, "op(%u", size);
118
0
            if (size > 0 && size < op_def_count) /* just in case */
119
0
                dmprintf1(mem, ":%s", (const char *)(op_index_def(size)->oname + 1));
120
0
            dmprintf1(mem, ")"PRI_INTPTR"", (intptr_t)pref->value.opproc);
121
0
            break;
122
0
        case t_real:
123
0
            dmprintf1(mem, "real %f", pref->value.realval);
124
0
            break;
125
0
        case t_save:
126
0
            dmprintf1(mem, "save %lu", pref->value.saveid);
127
0
            break;
128
0
        case t_shortarray:
129
0
            dmprintf2(mem, "short packedarray(%u)"PRI_INTPTR"", size,
130
0
                     (intptr_t)pref->value.packed);
131
0
            break;
132
0
        case t_string:
133
0
            dmprintf2(mem, "string(%u)"PRI_INTPTR"", size, (intptr_t)pref->value.bytes);
134
0
            break;
135
0
        case t_pdfctx:
136
0
        case t_struct:
137
0
          strct:{
138
0
                obj_header_t *obj = (obj_header_t *) pref->value.pstruct;
139
                /* HACK: We know this object was allocated with gsalloc.c. */
140
0
                gs_memory_type_ptr_t otype =
141
0
                    gs_ref_memory_procs.object_type(NULL, obj);
142
143
0
                dmprintf2(mem, "struct %s "PRI_INTPTR"",
144
0
                         (r_is_foreign(pref) ? "-foreign-" :
145
0
                          gs_struct_type_name_string(otype)),
146
0
                         (intptr_t)obj);
147
0
            }
148
0
            break;
149
0
        default:
150
0
            dmprintf1(mem, "type 0x%x", r_type(pref));
151
0
    }
152
0
}
153
static void
154
debug_print_packed_ref(const gs_memory_t *mem, const ref_packed *pref)
155
0
{
156
0
    ushort elt = *pref & packed_value_mask;
157
0
    ref nref;
158
159
0
    switch (*pref >> r_packed_type_shift) {
160
0
        case pt_executable_operator:
161
0
            dmprintf(mem, "<op_name>");
162
0
            op_index_ref(mem, elt, &nref);
163
0
            debug_print_ref(mem, &nref);
164
0
            break;
165
0
        case pt_integer:
166
0
            dmprintf1(mem, "<int> %d", (int)elt + packed_min_intval);
167
0
            break;
168
0
        case pt_literal_name:
169
0
            dmprintf(mem, "<lit_name>");
170
0
            goto ptn;
171
0
        case pt_executable_name:
172
0
            dmprintf(mem, "<exec_name>");
173
0
    ptn:    name_index_ref(mem, elt, &nref);
174
0
            dmprintf2(mem, "("PRI_INTPTR"#%u)", (intptr_t) nref.value.pname, elt);
175
0
            debug_print_name(mem, &nref);
176
0
            break;
177
0
        default:
178
0
            dmprintf2(mem, "<packed_%d?>0x%x", *pref >> r_packed_type_shift, elt);
179
0
    }
180
0
}
181
void
182
debug_print_ref_packed(const gs_memory_t *mem, const ref_packed *rpp)
183
0
{
184
0
    if (r_is_packed(rpp))
185
0
        debug_print_packed_ref(mem, rpp);
186
0
    else
187
0
        debug_print_full_ref(mem, (const ref *)rpp);
188
0
    dmflush(mem);
189
0
}
190
void
191
debug_print_ref(const gs_memory_t *mem, const ref * pref)
192
0
{
193
0
    debug_print_ref_packed(mem, (const ref_packed *)pref);
194
0
}
195
196
/* Dump one ref. */
197
static void print_ref_data(const gs_memory_t *mem, const ref *);
198
void
199
debug_dump_one_ref(const gs_memory_t *mem, const ref * p)
200
0
{
201
0
    uint attrs = r_type_attrs(p);
202
0
    uint type = r_type(p);
203
0
    static const ref_attr_print_mask_t apm[] = {
204
0
        REF_ATTR_PRINT_MASKS,
205
0
        {0, 0, 0}
206
0
    };
207
0
    const ref_attr_print_mask_t *ap = apm;
208
209
0
    if (type >= tx_next_index)
210
0
        dmprintf1(mem, "0x%02x?? ", type);
211
0
    else if (type >= t_next_index)
212
0
        dmprintf(mem, "opr* ");
213
0
    else
214
0
        dmprintf1(mem, "%s ", type_strings[type]);
215
0
    for (; ap->mask; ++ap)
216
0
        if ((attrs & ap->mask) == ap->value)
217
0
            dmputc(mem, ap->print);
218
0
    dmprintf2(mem, " 0x%04x 0x%08lx", r_size(p), *(const ulong *)&p->value);
219
0
    print_ref_data(mem, p);
220
0
    dmflush(mem);
221
0
}
222
static void
223
print_ref_data(const gs_memory_t *mem, const ref *p)
224
0
{
225
0
#define BUF_SIZE 30
226
0
    byte buf[BUF_SIZE + 1];
227
0
    const byte *pchars;
228
0
    uint plen;
229
230
0
    if (obj_cvs(mem, p, buf, countof(buf) - 1, &plen, &pchars) >= 0 &&
231
0
        pchars == buf &&
232
0
        ((buf[plen] = 0), strcmp((char *)buf, "--nostringval--"))
233
0
        )
234
0
        dmprintf1(mem, " = %s", (char *)buf);
235
0
#undef BUF_SIZE
236
0
}
237
238
/* Dump a region of memory containing refs. */
239
void
240
debug_dump_refs(const gs_memory_t *mem, const ref * from,
241
                uint size, const char *msg)
242
0
{
243
0
    const ref *p = from;
244
0
    uint count = size;
245
246
0
    if (size && msg)
247
0
        dmprintf2(mem, "%s at "PRI_INTPTR":\n", msg, (intptr_t)from);
248
0
    while (count--) {
249
0
        dmprintf2(mem, PRI_INTPTR": 0x%04x ", (intptr_t)p, r_type_attrs(p));
250
0
        debug_dump_one_ref(mem, p);
251
0
        dmputc(mem, '\n');
252
0
        p++;
253
0
    }
254
0
}
255
256
/* Dump a stack. */
257
void
258
debug_dump_stack(const gs_memory_t *mem,
259
                 const ref_stack_t * pstack, const char *msg)
260
0
{
261
0
    int i;
262
0
    const char *m = msg;
263
264
0
    for (i = ref_stack_count(pstack); i > 0;) {
265
0
        const ref *p = ref_stack_index(pstack, --i);
266
267
0
        if (m) {
268
0
            dmprintf2(mem, "%s at "PRI_INTPTR":\n", m, (intptr_t)pstack);
269
0
            m = NULL;
270
0
        }
271
0
        dmprintf2(mem, PRI_INTPTR": 0x%02x ", (intptr_t)p, r_type(p));
272
0
        debug_dump_one_ref(mem, p);
273
0
        dmputc(mem, '\n');
274
0
    }
275
0
}
276
277
/* Dump an array. */
278
void
279
debug_dump_array(const gs_memory_t *mem, const ref * array)
280
0
{
281
0
    const ref_packed *pp;
282
0
    uint type = r_type(array);
283
0
    uint len;
284
285
0
    switch (type) {
286
0
        default:
287
0
            dmprintf2(mem, "%s at "PRI_INTPTR" isn't an array.\n",
288
0
                      (type < countof(type_strings) ?
289
0
                       type_strings[type] : "????"),
290
0
                      (intptr_t)array);
291
0
            return;
292
0
        case t_oparray:
293
            /* This isn't really an array, but we'd like to see */
294
            /* its contents anyway. */
295
0
            debug_dump_array(mem, array->value.const_refs);
296
0
            return;
297
0
        case t_array:
298
0
        case t_mixedarray:
299
0
        case t_shortarray:
300
0
            ;
301
0
    }
302
303
    /* This "packed" loop works for all array-types. */
304
0
    for (len = r_size(array), pp = array->value.packed;
305
0
         len > 0;
306
0
         len--, pp = packed_next(pp)) {
307
0
        ref temp;
308
309
0
        packed_get(mem, pp, &temp);
310
0
        if (r_is_packed(pp)) {
311
0
            dmprintf2(mem, PRI_INTPTR"* 0x%04x ", (intptr_t)pp, (uint)*pp);
312
0
            print_ref_data(mem, &temp);
313
0
        } else {
314
0
            dmprintf2(mem, PRI_INTPTR": 0x%02x ", (intptr_t)pp, r_type(&temp));
315
0
            debug_dump_one_ref(mem, &temp);
316
0
        }
317
0
        dmputc(mem, '\n');
318
0
    }
319
0
}