xref: /plan9/sys/src/cmd/gs/src/idebug.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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