[t][TT#1509] Prevent core dumps by preventing negative length array creation. Tests...
[parrot.git] / src / pbc_dump.c
blob217b2d06a9deeb9b8eca072cecfce949a63c07b1
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 pbc_dump - Dump or convert Parrot bytecode (PBC) files
9 =head1 SYNOPSIS
11 pbc_dump [-tdh] [--terse|--disassemble|--header-only] file.pbc
13 pbc_dump -o converted.pbc file.pbc
15 =head1 DESCRIPTION
17 A program to dump pack files to human readable form.
19 =head2 Command-Line Options
21 =over 4
23 =item C<-d>
25 Disassemble bytecode segments.
27 =item C<-h>
29 Dump the bytecode header only.
31 =item C<-t>
33 Terse output.
35 =item C<-D> C--debug> 1-7
37 Display detailed packfile reader debugging information if
38 F<include/parrot/packfile.h> enables TRACE_PACKFILE.
40 1 print general debug info
41 2 print alignment info
42 4 print values
44 =item C<-o converted.pbc>
46 Repacks a PBC file into the platform's native binary format for better
47 efficiency on reading non-native PBCs.
49 =back
51 =head2 Functions
53 =over 4
55 =cut
59 #include "parrot/parrot.h"
60 #include "parrot/embed.h"
61 #include "parrot/oplib/ops.h"
65 =item C<static void const_dump(PARROT_INTERP, const PackFile_Segment *segp)>
67 Dump the constant table.
69 =cut
73 static void
74 const_dump(PARROT_INTERP, const PackFile_Segment *segp)
76 Parrot_io_printf(interp, "%Ss => [\n", segp->name);
77 PackFile_ConstTable_dump(interp, (const PackFile_ConstTable *)segp);
78 Parrot_io_printf(interp, "],\n");
83 =item C<static void fixup_dump(PARROT_INTERP, const PackFile_Segment *segp)>
85 Dump the fixup table.
87 =cut
91 static void
92 fixup_dump(PARROT_INTERP, const PackFile_Segment *segp)
94 Parrot_io_printf(interp, "%Ss => [\n", segp->name);
95 PackFile_Fixup_dump(interp, (const PackFile_FixupTable *)segp);
96 Parrot_io_printf(interp, "],\n");
101 =item C<static void disas_dump(PARROT_INTERP, const PackFile_Segment *self)>
103 Disassemble and dump.
105 =cut
109 static void
110 disas_dump(PARROT_INTERP, const PackFile_Segment *self)
112 opcode_t *pc;
113 size_t i, n;
114 Parrot_io_printf(interp, "%Ss => [ # %d ops at offs 0x%x\n",
115 self->name, (int)self->size, (int)self->file_offset + 4);
116 pc = self->data;
117 while (pc < self->data + self->size) {
118 /* trace_op_dump(interp, self->pf->src, pc); */
119 Parrot_io_printf(interp, " %04x: ", (int) (pc - self->data));
120 n = (size_t)interp->op_info_table[*pc].op_count;
121 for (i = 0; i < 6; i++)
122 if (i < n)
123 Parrot_io_printf(interp, "%08lx ", (unsigned long) pc[i]);
124 else
125 Parrot_io_printf(interp, " ");
126 Parrot_io_printf(interp, "%s\n",
127 interp->op_info_table[*pc].full_name);
128 ADD_OP_VAR_PART(interp, interp->code, pc, n);
129 pc += n;
131 Parrot_io_printf(interp, "]\n");
136 =item C<static void PackFile_header_dump(PARROT_INTERP, PackFile *pf)>
138 Dump the header.
140 =cut
144 static void
145 PackFile_header_dump(PARROT_INTERP, PackFile *pf)
147 Parrot_io_printf(interp, "HEADER => [\n");
148 Parrot_io_printf(interp, "\twordsize = %d", pf->header->wordsize);
149 Parrot_io_printf(interp, "\t(interpreter's wordsize/INTVAL = %d/%d)\n",
150 sizeof (opcode_t), sizeof (INTVAL));
151 Parrot_io_printf(interp, "\tbyteorder = %d", pf->header->byteorder);
152 Parrot_io_printf(interp, "\t(interpreter's byteorder = %d)\n",
153 PARROT_BIGENDIAN);
154 Parrot_io_printf(interp, "\tfloattype = %d", pf->header->floattype);
155 Parrot_io_printf(interp, "\t(interpreter's NUMVAL_SIZE = %d)\n", NUMVAL_SIZE);
156 Parrot_io_printf(interp, "\tparrot-version %d.%d.%d, bytecode-version %d.%d\n",
157 pf->header->major, pf->header->minor, pf->header->patch,
158 pf->header->bc_major, pf->header->bc_minor);
159 Parrot_io_printf(interp, "\tUUID: type = %d, size = %d",
160 pf->header->uuid_type, pf->header->uuid_size);
161 if (pf->header->uuid_size)
162 Parrot_io_printf(interp, ", '%s'\n", pf->header->uuid_data);
163 else
164 Parrot_io_printf(interp, "\n");
165 Parrot_io_printf(interp, "\t%s endianize, %s opcode, %s numval transform\n",
166 pf->need_endianize ? "**need**" : "no",
167 pf->need_wordsize ? "**need**" : "no",
168 pf->fetch_nv ? "**need**" : "no");
169 Parrot_io_printf(interp, "\tdirformat = %d\n", pf->header->dir_format);
170 Parrot_io_printf(interp, "]\n");
175 =item C<static void help(void)>
177 Print out the user help info.
179 =cut
183 static void help(void)
185 printf("pbc_dump - dump or convert parrot bytecode (PBC) files\n");
186 printf("usage:\n");
187 printf("pbc_dump [-tdh] [--terse|--disassemble|--header-only] file.pbc\n");
188 printf("pbc_dump -o converted.pbc file.pbc\n\n");
189 printf("\t-d ... disassemble bytecode segments\n");
190 printf("\t-h ... dump header only\n");
191 printf("\t-t ... terse output\n");
192 #if TRACE_PACKFILE
193 printf("\t-D<1-7> --debug debug output\n");
194 printf("\t 1 general info\n");
195 printf("\t 2 alignment\n");
196 printf("\t 4 values\n");
197 #endif
198 printf("\t-o converted.pbc ... repacks a PBC file into "
199 "the platform's native\n");
200 printf("\t binary format for better efficiency on reading "
201 "non native PBCs\n");
202 exit(EXIT_SUCCESS);
205 static struct longopt_opt_decl opt_options[] = {
206 { 'h', 'h', OPTION_optional_FLAG, { "--header-only" } },
207 { '?', '?', OPTION_optional_FLAG, { "--help" } },
208 { 't', 't', OPTION_optional_FLAG, { "--terse" } },
209 { 'd', 'd', OPTION_optional_FLAG, { "--disassemble" } },
210 #if TRACE_PACKFILE
211 { 'D', 'D', OPTION_required_FLAG, { "--debug" } },
212 #endif
213 { 'o', 'o', OPTION_required_FLAG, { "--output" } }
218 =item C<int main(int argc, const char **argv)>
220 The run loop. Process the command-line arguments and dump accordingly.
222 =cut
227 main(int argc, const char **argv)
229 PackFile *pf;
230 Interp *interp;
231 int terse = 0;
232 int disas = 0;
233 int convert = 0;
234 int options = PFOPT_UTILS;
235 const char *file = NULL;
236 struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT;
237 int status;
239 if (argc < 2) {
240 help();
242 interp = Parrot_new(NULL);
243 /* init and set top of stack */
244 Parrot_init_stacktop(interp, &status);
245 while ((status = longopt_get(interp,
246 argc, argv, opt_options, &opt)) > 0) {
247 switch (opt.opt_id) {
248 case 'h':
249 options += PFOPT_HEADERONLY;
250 break;
251 case 't':
252 terse = 1;
253 break;
254 case 'd':
255 disas = 1;
256 break;
257 #if TRACE_PACKFILE
258 case 'D':
259 options += atoi(opt.opt_arg) << 2;
260 break;
261 #endif
262 case 'o':
263 file = opt.opt_arg;
264 convert = 1;
265 break;
266 case '?':
267 default:
268 help();
269 break;
272 if (status == -1) {
273 help();
275 argc -= opt.opt_index;
276 argv += opt.opt_index;
279 pf = Parrot_pbc_read(interp, *argv, options);
281 if (!pf) {
282 printf("Can't read PBC\n");
283 return 1;
285 Parrot_pbc_load(interp, pf);
286 if (convert) {
287 size_t size;
288 opcode_t *pack;
289 FILE *fp;
291 size = PackFile_pack_size(interp,
292 interp->code->base.pf) * sizeof (opcode_t);
293 pack = (opcode_t*) Parrot_gc_allocate_memory_chunk(interp, size);
294 if (!pack) {
295 printf("out of mem\n");
296 exit(EXIT_FAILURE);
298 PackFile_pack(interp, interp->code->base.pf, pack);
299 if (STREQ(file, "-"))
300 fp = stdout;
301 else if ((fp = fopen(file, "wb")) == 0) {
302 printf("Couldn't open %s\n", file);
303 exit(EXIT_FAILURE);
306 if ((1 != fwrite(pack, size, 1, fp))) {
307 printf("Couldn't write %s\n", file);
308 exit(EXIT_FAILURE);
310 fclose(fp);
311 Parrot_gc_free_memory_chunk(interp, pack);
312 Parrot_exit(interp, 0);
315 PackFile_header_dump(interp, pf);
316 if (options & PFOPT_HEADERONLY) {
317 Parrot_exit(interp, 0);
319 /* install a dumper function */
320 if (!terse) {
321 pf->PackFuncs[PF_CONST_SEG].dump = const_dump;
322 pf->PackFuncs[PF_FIXUP_SEG].dump = fixup_dump;
324 if (disas)
325 pf->PackFuncs[PF_BYTEC_SEG].dump = disas_dump;
326 /* do a directory dump, which dumps segs then */
327 PackFile_Segment_dump(interp, &pf->directory.base);
329 Parrot_exit(interp, 0);
334 =back
336 =head1 SEE ALSO
338 F<src/packdump.c>.
340 =cut
345 * Local variables:
346 * c-file-style: "parrot"
347 * End:
348 * vim: expandtab shiftwidth=4: