From 6399022cb3aaa930a0658c4716bebe709d68528d Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 13 May 2025 13:24:43 +0100 Subject: [PATCH] frontend: disassemble: add a range of switches to control what information is provided --- frontend/cmd/disassemble.c | 210 ++++++++++++++++++++++++++++--------- 1 file changed, 162 insertions(+), 48 deletions(-) diff --git a/frontend/cmd/disassemble.c b/frontend/cmd/disassemble.c index 643be4f..dc430d4 100644 --- a/frontend/cmd/disassemble.c +++ b/frontend/cmd/disassemble.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -21,7 +22,11 @@ enum dump_flags { enum { ARG_BIN_FILE, + OPT_HEADER, + OPT_SECTIONS, OPT_DUMP, + OPT_CLASSES, + OPT_CONSTPOOL, }; static void dump_instruction(b_i32 x) @@ -122,14 +127,12 @@ static void dump_instruction(b_i32 x) break; case IVY_OP_PUSH_REG: + case IVY_OP_POP: printf(" x%ld", instr.i_arg[0]); break; case IVY_OP_PUSH_CONST: printf(" #%ld", instr.i_arg[0]); break; - case IVY_OP_POP: - printf(" x%ld", instr.i_arg[0]); - break; case IVY_OP_MSG_REG: printf(" x%ld, x%ld, x%lx", instr.i_arg[0], instr.i_arg[1], @@ -192,6 +195,51 @@ static void dump_instruction(b_i32 x) } } +static enum ivy_status dump_constpool(struct ivy_asm_reader *object) +{ + printf("constpool:\n"); + struct ivy_asm_constpool_reader *pool = NULL; + enum ivy_status status + = ivy_asm_reader_open_constpool(object, 0, 0, &pool); + if (status == IVY_ERR_NO_ENTRY) { + b_err("object file has no constpool.\n"); + return status; + } + + size_t nr_entries = ivy_asm_constpool_reader_get_nr_entries(pool); + + for (size_t i = 0; i < nr_entries; i++) { + struct ivy_asm_constpool_value *v; + status = ivy_asm_constpool_reader_read_value(pool, i, &v); + if (status != IVY_OK) { + b_err("cannot read constpool value"); + b_i("reason: %s", ivy_status_to_string(status)); + break; + } + + printf(" [%03zu] ", i); + + switch (v->v_type) { + case IVY_ASM_CONSTPOOL_TYPE_STRING: + printf("string \"%s\"", v->v_str); + break; + case IVY_ASM_CONSTPOOL_TYPE_SELECTOR: { + char s[256]; + ivy_selector_to_string(v->v_sel, s, sizeof s); + printf("selector %s", s); + break; + } + default: + printf(""); + break; + } + + fputc('\n', stdout); + } + + return status; +} + static void dump_instructions(b_i32 *x, size_t buffer_size) { size_t nr_instr = buffer_size / sizeof *x; @@ -275,7 +323,8 @@ static enum ivy_status dump_section( enum dump_flags flags) { struct ivy_asm_section_reader *sect = NULL; - enum ivy_status status = ivy_asm_reader_open_section(reader, index, §); + enum ivy_status status = ivy_asm_reader_open_section( + reader, IVY_ASM_SECTION_ANY_TYPE, index, §); if (status != IVY_OK) { return status; } @@ -285,6 +334,7 @@ static enum ivy_status dump_section( size_t len = info->s_length; size_t buffer_size = chunks_per_line * sizeof(uint32_t); uint32_t *x = malloc(buffer_size); + size_t bytes_per_line = chunks_per_line * sizeof *x; size_t offset = 0; status = dump_header(sect, &offset); @@ -306,8 +356,13 @@ static enum ivy_status dump_section( printf(" %08zx | ", i); - for (size_t ii = 0; ii < chunks_per_line; ii++) { - printf("%08" PRIx32 " ", x[ii]); + unsigned char *z = (unsigned char *)x; + for (size_t ii = 0; ii < bytes_per_line; ii++) { + if (ii > 0 && (ii % sizeof *x) == 0) { + fputc(' ', stdout); + } + + printf("%02x", z[ii]); } printf(" | "); @@ -326,53 +381,16 @@ static enum ivy_status dump_section( return status; } -static int disassemble( - const b_command *cmd, const b_arglist *args, const b_array *_) +static enum ivy_status dump_section_table(struct ivy_asm_reader *reader, bool dump) { - bool dump = b_arglist_get_count(args, OPT_DUMP, B_COMMAND_INVALID_ID) > 0; - - const char *in_path = NULL; - - b_arglist_get_string(args, B_COMMAND_INVALID_ID, ARG_BIN_FILE, 0, &in_path); - if (!in_path) { - b_err("no input file specified."); - return -1; - } - - FILE *in = fopen(in_path, "rb"); - if (!in) { - b_err("cannot open object file"); - b_i("reason: %s", strerror(errno)); - - return -1; - } - - struct ivy_asm_reader *reader = NULL; - enum ivy_status status = ivy_asm_reader_open(in, &reader); - - if (status != IVY_OK) { - b_err("cannot open object file"); - b_i("reason: %s", ivy_status_to_string(status)); - - fclose(in); - return -1; - } - + const struct ivy_asm_section_info *section_table + = ivy_asm_reader_get_sections(reader); const struct ivy_asm_object_info *object_info = ivy_asm_reader_get_info(reader); - const struct ivy_asm_section_info *sections - = ivy_asm_reader_get_sections(reader); - - printf("header:\n"); - printf("\tmagic: 0x%08" PRIx32 "\n", object_info->obj_magic); - printf("\ttable offset: 0x%zx\n", object_info->obj_table_offset); - printf("\tnr sections: %zu\n", object_info->obj_nr_sections); - - printf("\n"); printf("sections:\n"); for (size_t i = 0; i < object_info->obj_nr_sections; i++) { - const struct ivy_asm_section_info *sect = §ions[i]; + const struct ivy_asm_section_info *sect = §ion_table[i]; char type[5]; printf(" * #%03zu: ", i); @@ -411,6 +429,72 @@ static int disassemble( fputc('\n', stdout); } } + return IVY_OK; +} + +static int disassemble( + const b_command *cmd, const b_arglist *args, const b_array *_) +{ + bool header = b_arglist_get_count(args, OPT_HEADER, B_COMMAND_INVALID_ID) + > 0; + bool sections + = b_arglist_get_count(args, OPT_SECTIONS, B_COMMAND_INVALID_ID) > 0; + bool dump = b_arglist_get_count(args, OPT_DUMP, B_COMMAND_INVALID_ID) > 0; + bool constpool + = b_arglist_get_count(args, OPT_CONSTPOOL, B_COMMAND_INVALID_ID) + > 0; + bool classes + = b_arglist_get_count(args, OPT_CLASSES, B_COMMAND_INVALID_ID) > 0; + + const char *in_path = NULL; + + b_arglist_get_string(args, B_COMMAND_INVALID_ID, ARG_BIN_FILE, 0, &in_path); + if (!in_path) { + b_err("no input file specified."); + return -1; + } + + FILE *in = fopen(in_path, "rb"); + if (!in) { + b_err("cannot open object file"); + b_i("reason: %s", strerror(errno)); + + return -1; + } + + struct ivy_asm_reader *reader = NULL; + enum ivy_status status = ivy_asm_reader_open(in, &reader); + + if (status != IVY_OK) { + b_err("cannot open object file"); + b_i("reason: %s", ivy_status_to_string(status)); + + fclose(in); + return -1; + } + + const struct ivy_asm_object_info *object_info + = ivy_asm_reader_get_info(reader); + + if (header) { + printf("header:\n"); + printf("\tmagic: 0x%08" PRIx32 "\n", object_info->obj_magic); + printf("\ttable offset: 0x%zx\n", object_info->obj_table_offset); + printf("\tnr sections: %zu\n", object_info->obj_nr_sections); + printf("\n"); + } + + if (sections) { + status = dump_section_table(reader, dump); + } + + if (constpool) { + status = dump_constpool(reader); + } + + if (classes) { + printf("\nclasses:\n"); + } ivy_asm_reader_close(reader); @@ -432,13 +516,43 @@ B_COMMAND(CMD_DISASSEMBLE, CMD_ROOT) B_ARG_NR_VALUES(1); } + B_COMMAND_OPTION(OPT_HEADER) + { + B_OPTION_SHORT_NAME('h'); + B_OPTION_LONG_NAME("header"); + B_OPTION_DESC("print the object file header."); + } + + B_COMMAND_OPTION(OPT_SECTIONS) + { + B_OPTION_SHORT_NAME('s'); + B_OPTION_LONG_NAME("section-table"); + B_OPTION_DESC("print the object file section table."); + } + B_COMMAND_OPTION(OPT_DUMP) { B_OPTION_SHORT_NAME('d'); B_OPTION_LONG_NAME("dump"); B_OPTION_DESC( "decode and print the contents of each object " - "section."); + "section."); + } + + B_COMMAND_OPTION(OPT_CLASSES) + { + B_OPTION_SHORT_NAME('c'); + B_OPTION_LONG_NAME("classes"); + B_OPTION_DESC( + "print the classes contained in the object file."); + } + + B_COMMAND_OPTION(OPT_CONSTPOOL) + { + B_OPTION_SHORT_NAME('p'); + B_OPTION_LONG_NAME("pool-data"); + B_OPTION_DESC( + "print the constant pool data in the object file."); } B_COMMAND_HELP_OPTION();