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