2 Copyright (C) 2001-2010, Parrot Foundation.
7 pbc_dump - Dump or convert Parrot bytecode (PBC) files
11 pbc_dump [-tdh] [--terse|--disassemble|--header-only] file.pbc
13 pbc_dump -o converted.pbc file.pbc
17 A program to dump pack files to human readable form.
19 =head2 Command-Line Options
25 Disassemble bytecode segments.
29 Dump the bytecode header only.
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
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.
59 #include "parrot/parrot.h"
60 #include "parrot/embed.h"
61 #include "parrot/oplib/ops.h"
62 #include "parrot/oplib/core_ops.h"
66 =item C<static void const_dump(PARROT_INTERP, const PackFile_Segment *segp)>
68 Dump the constant table.
75 const_dump(PARROT_INTERP
, const PackFile_Segment
*segp
)
77 Parrot_io_printf(interp
, "%Ss => [\n", segp
->name
);
78 PackFile_ConstTable_dump(interp
, (const PackFile_ConstTable
*)segp
);
79 Parrot_io_printf(interp
, "],\n");
85 =item C<static void fixup_dump(PARROT_INTERP, const PackFile_Segment *segp)>
94 fixup_dump(PARROT_INTERP
, const PackFile_Segment
*segp
)
96 Parrot_io_printf(interp
, "%Ss => [\n", segp
->name
);
97 PackFile_Fixup_dump(interp
, (const PackFile_FixupTable
*)segp
);
98 Parrot_io_printf(interp
, "],\n");
104 =item C<static void disas_dump(PARROT_INTERP, const PackFile_Segment *self)>
106 Disassemble and dump.
113 disas_dump(PARROT_INTERP
, const PackFile_Segment
*self
)
115 const opcode_t
*pc
= self
->data
;
117 Parrot_io_printf(interp
, "%Ss => [ # %d ops at offs 0x%x\n",
118 self
->name
, (int)self
->size
, (int)self
->file_offset
+ 4);
120 while (pc
< self
->data
+ self
->size
) {
121 /* n can't be const; the ADD_OP_VAR_PART macro increments it */
122 size_t n
= (size_t)interp
->code
->op_info_table
[*pc
]->op_count
;
125 /* trace_op_dump(interp, self->pf->src, pc); */
126 Parrot_io_printf(interp
, " %04x: ", (int)(pc
- self
->data
));
128 for (i
= 0; i
< 6; ++i
)
130 Parrot_io_printf(interp
, "%08lx ", (unsigned long)pc
[i
]);
132 Parrot_io_printf(interp
, " ");
134 Parrot_io_printf(interp
, "%s\n",
135 interp
->code
->op_info_table
[*pc
]->full_name
);
137 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
141 Parrot_io_printf(interp
, "]\n");
147 =item C<static void nums_dump(PARROT_INTERP, const PackFile_Segment *self)>
149 Disassembles and dumps op names and line numbers only.
156 nums_dump(PARROT_INTERP
, const PackFile_Segment
*self
)
158 const STRING
*debug_name
= Parrot_str_concat(interp
, self
->name
,
159 Parrot_str_new_constant(interp
, "_DB"));
160 const PackFile_Segment
*debug
= PackFile_find_segment(interp
,
161 self
->dir
, debug_name
, 1);
163 opcode_t
* pc
= self
->data
;
164 opcode_t
* debug_ops
= debug
->data
;
165 op_info_t
** const op_info
= interp
->code
->op_info_table
;
167 while (pc
< self
->data
+ self
->size
) {
168 /* n can't be const; the ADD_OP_VAR_PART macro increments it */
169 size_t n
= (size_t)op_info
[*pc
]->op_count
;
171 Parrot_io_printf(interp
, " %04x: %s\n",
172 *(debug_ops
++), op_info
[*pc
]->full_name
);
174 ADD_OP_VAR_PART(interp
, interp
->code
, pc
, n
);
182 =item C<static void null_dump(PARROT_INTERP, const PackFile_Segment *self)>
184 Produces no output for the given segment type.
191 null_dump(SHIM_INTERP
, const PackFile_Segment
*self
)
199 =item C<static void null_dir_dump(PARROT_INTERP, const PackFile_Segment *self)>
201 Dumps all of the segments of the given PackFile_Directory, but produces no
202 output for the directory itself.
209 null_dir_dump(PARROT_INTERP
, const PackFile_Segment
*self
)
211 const PackFile_Directory
* const dir
= (const PackFile_Directory
*)self
;
214 for (i
= 0; i
< dir
->num_segments
; ++i
)
215 self
->pf
->PackFuncs
[dir
->segments
[i
]->type
].dump(interp
, dir
->segments
[i
]);
221 =item C<static void PackFile_header_dump(PARROT_INTERP, PackFile *pf)>
230 PackFile_header_dump(PARROT_INTERP
, PackFile
*pf
)
232 Parrot_io_printf(interp
, "HEADER => [\n");
233 Parrot_io_printf(interp
, "\twordsize = %d", pf
->header
->wordsize
);
234 Parrot_io_printf(interp
, "\t(interpreter's wordsize/INTVAL = %d/%d)\n",
235 sizeof (opcode_t
), sizeof (INTVAL
));
236 Parrot_io_printf(interp
, "\tbyteorder = %d", pf
->header
->byteorder
);
237 Parrot_io_printf(interp
, "\t(interpreter's byteorder = %d)\n",
239 Parrot_io_printf(interp
, "\tfloattype = %d", pf
->header
->floattype
);
240 Parrot_io_printf(interp
, "\t(interpreter's NUMVAL_SIZE = %d)\n",
242 Parrot_io_printf(interp
, "\tparrot-version %d.%d.%d, "
243 "bytecode-version %d.%d\n",
244 pf
->header
->major
, pf
->header
->minor
, pf
->header
->patch
,
245 pf
->header
->bc_major
, pf
->header
->bc_minor
);
246 Parrot_io_printf(interp
, "\tUUID: type = %d, size = %d",
247 pf
->header
->uuid_type
, pf
->header
->uuid_size
);
249 if (pf
->header
->uuid_size
)
250 Parrot_io_printf(interp
, ", '%s'\n", pf
->header
->uuid_data
);
252 Parrot_io_printf(interp
, "\n");
254 Parrot_io_printf(interp
, "\t%s endianize, %s opcode, %s numval transform\n",
255 pf
->need_endianize
? "**need**" : "no",
256 pf
->need_wordsize
? "**need**" : "no",
257 pf
->fetch_nv
? "**need**" : "no");
259 Parrot_io_printf(interp
, "\tdirformat = %d\n", pf
->header
->dir_format
);
260 Parrot_io_printf(interp
, "]\n");
266 =item C<static void help(void)>
268 Print out the user help info.
274 static void help(void)
276 printf("pbc_dump - dump or convert parrot bytecode (PBC) files\n");
278 printf("pbc_dump [-tdh] [--terse|--disassemble|--header-only|--line-nums]"
280 printf("pbc_dump -o converted.pbc file.pbc\n\n");
281 printf("\t-d ... disassemble bytecode segments\n");
282 printf("\t-h ... dump header only\n");
283 printf("\t-t ... terse output\n");
284 printf("\t-n ... show ops and line numbers only\n");
287 printf("\t-D<1-7> --debug debug output\n");
288 printf("\t 1 general info\n");
289 printf("\t 2 alignment\n");
290 printf("\t 4 values\n");
293 printf("\t-o converted.pbc ... repacks a PBC file into "
294 "the platform's native\n");
295 printf("\t binary format for better efficiency on reading "
296 "non native PBCs\n");
301 static struct longopt_opt_decl opt_options
[] = {
302 { 'h', 'h', OPTION_optional_FLAG
, { "--header-only" } },
303 { '?', '?', OPTION_optional_FLAG
, { "--help" } },
304 { 't', 't', OPTION_optional_FLAG
, { "--terse" } },
305 { 'n', 'n', OPTION_optional_FLAG
, { "--line-nums" } },
306 { 'd', 'd', OPTION_optional_FLAG
, { "--disassemble" } },
307 { 'o', 'o', OPTION_required_FLAG
, { "--output" } }
310 { 'D', 'D', OPTION_required_FLAG
, { "--debug" } },
317 =item C<int main(int argc, const char **argv)>
319 The run loop. Process the command-line arguments and dump accordingly.
326 main(int argc
, const char **argv
)
331 const char *file
= NULL
;
336 int options
= PFOPT_UTILS
;
338 struct longopt_opt_info opt
= LONGOPT_OPT_INFO_INIT
;
345 interp
= Parrot_new(NULL
);
347 /* init and set top of stack */
348 Parrot_init_stacktop(interp
, &status
);
350 while ((status
= longopt_get(interp
, argc
, argv
, opt_options
, &opt
)) > 0) {
351 switch (opt
.opt_id
) {
354 options
+= atoi(opt
.opt_arg
) << 2;
358 options
+= PFOPT_HEADERONLY
;
383 argc
-= opt
.opt_index
;
384 argv
+= opt
.opt_index
;
386 pf
= Parrot_pbc_read(interp
, *argv
, options
);
389 printf("Can't read PBC\n");
393 Parrot_pbc_load(interp
, pf
);
396 size_t size
= PackFile_pack_size(interp
,
397 interp
->code
->base
.pf
) * sizeof (opcode_t
);
398 opcode_t
*pack
= (opcode_t
*)Parrot_gc_allocate_memory_chunk(interp
,
403 printf("out of mem\n");
407 PackFile_pack(interp
, interp
->code
->base
.pf
, pack
);
409 if (STREQ(file
, "-"))
411 else if ((fp
= fopen(file
, "wb")) == 0) {
412 printf("Couldn't open %s\n", file
);
416 if ((1 != fwrite(pack
, size
, 1, fp
))) {
417 printf("Couldn't write %s\n", file
);
422 Parrot_gc_free_memory_chunk(interp
, pack
);
423 Parrot_exit(interp
, 0);
427 PackFile_header_dump(interp
, pf
);
429 if (options
& PFOPT_HEADERONLY
)
430 Parrot_exit(interp
, 0);
432 /* install a dumper function */
434 pf
->PackFuncs
[PF_CONST_SEG
].dump
= const_dump
;
435 pf
->PackFuncs
[PF_FIXUP_SEG
].dump
= fixup_dump
;
439 pf
->PackFuncs
[PF_BYTEC_SEG
].dump
= disas_dump
;
444 for (i
= PF_DIR_SEG
+ 1; i
< PF_MAX_SEG
; ++i
)
445 pf
->PackFuncs
[i
].dump
= null_dump
;
447 pf
->PackFuncs
[PF_DIR_SEG
].dump
= null_dir_dump
;
448 pf
->PackFuncs
[PF_BYTEC_SEG
].dump
= nums_dump
;
451 /* do a directory dump, which dumps segs then */
452 PackFile_Segment_dump(interp
, &pf
->directory
.base
);
454 Parrot_exit(interp
, 0);
472 * c-file-style: "parrot"
474 * vim: expandtab shiftwidth=4: