diff --git a/frontend/cmd/disassemble.c b/frontend/cmd/disassemble.c index ccc4b53..58ad0f1 100644 --- a/frontend/cmd/disassemble.c +++ b/frontend/cmd/disassemble.c @@ -196,6 +196,202 @@ static void dump_instruction(b_i32 x) } } +static enum ivy_status dump_class( + struct ivy_asm_reader *object, struct ivy_asm_constpool_reader *pool, + size_t index) +{ + struct ivy_asm_section_reader *xcls = NULL; + struct ivy_asm_constpool_value *class_ident = NULL; + enum ivy_status status = ivy_asm_reader_open_section( + object, IVY_TABLE_CLASS, index, &xcls); + + if (status != IVY_OK) { + goto cleanup; + } + + const struct ivy_asm_section_info *class_info + = ivy_asm_section_reader_get_info(xcls); + + size_t r; + struct ivy_bin_class class_header; + status = ivy_asm_section_reader_read( + xcls, 0, sizeof class_header, &class_header, &r); + if (status != IVY_OK) { + goto cleanup; + } + + if (r != sizeof class_header) { + status = IVY_ERR_BAD_FORMAT; + goto cleanup; + } + + status = ivy_asm_constpool_reader_read_value( + pool, b_i32_btoh(class_header.c_ident), &class_ident); + if (status != IVY_OK) { + goto cleanup; + } + + if (class_ident->v_type != IVY_ASM_CONSTPOOL_TYPE_IDENT) { + status = IVY_ERR_BAD_FORMAT; + goto cleanup; + } + + char class_ident_str[128]; + ivy_ident_to_string( + class_ident->v_ident, class_ident_str, sizeof class_ident_str); + + printf(" * %s\n", class_ident_str); + + struct ivy_bin_class_table_entry entry; + size_t nr_entries + = (class_info->s_length - sizeof class_header) / sizeof entry; + size_t offset = sizeof class_header; + + for (size_t i = 0; i < nr_entries; i++) { + status = ivy_asm_section_reader_read( + xcls, offset, sizeof entry, &entry, &r); + if (status != IVY_OK) { + break; + } + + if (r != sizeof entry) { + status = IVY_ERR_BAD_FORMAT; + break; + } + + printf(" [%03zu] ", i); + + char s[256]; + uint32_t type = b_i32_btoh(entry.e_type); + switch (type) { + case IVY_CLASS_TABLE_PROP: { + printf("type:property\n"); + struct ivy_asm_constpool_value *prop_ident = NULL; + status = ivy_asm_constpool_reader_read_value( + pool, b_i32_btoh(entry.e_property.p_ident), + &prop_ident); + if (status != IVY_OK) { + break; + } + + if (prop_ident->v_type != IVY_ASM_CONSTPOOL_TYPE_IDENT) { + status = IVY_ERR_BAD_FORMAT; + break; + } + + uint32_t get = b_i32_btoh(entry.e_property.p_get); + uint32_t set = b_i32_btoh(entry.e_property.p_set); + + ivy_ident_to_string(prop_ident->v_ident, s, sizeof s); + ivy_asm_constpool_value_destroy(prop_ident); + printf(" ident:%s, get:", s); + if (get) { + printf("0x%" PRIx32 "[%" PRIu32 "]", get, get); + } else { + printf(""); + } + + printf(", set:"); + + if (set) { + printf("0x%" PRIx32 "[%" PRIu32 "]", set, set); + } else { + printf(""); + } + + break; + } + case IVY_CLASS_TABLE_MVAR: { + printf("type:variable\n"); + struct ivy_asm_constpool_value *var_ident = NULL; + status = ivy_asm_constpool_reader_read_value( + pool, b_i32_btoh(entry.e_mvar.m_ident), &var_ident); + if (status != IVY_OK) { + break; + } + + if (var_ident->v_type != IVY_ASM_CONSTPOOL_TYPE_IDENT) { + status = IVY_ERR_BAD_FORMAT; + break; + } + + uint32_t index = b_i32_btoh(entry.e_mvar.m_index); + ivy_ident_to_string(var_ident->v_ident, s, sizeof s); + ivy_asm_constpool_value_destroy(var_ident); + printf(" ident:%s, index:0x%" PRIx32 + "[%" PRIu32 "]", + s, index, index); + + break; + } + case IVY_CLASS_TABLE_MSGH: { + printf("type:method\n"); + struct ivy_asm_constpool_value *sel = NULL; + status = ivy_asm_constpool_reader_read_value( + pool, b_i32_btoh(entry.e_msgh.msg_selector), &sel); + if (status != IVY_OK) { + break; + } + + if (sel->v_type != IVY_ASM_CONSTPOOL_TYPE_SELECTOR) { + status = IVY_ERR_BAD_FORMAT; + break; + } + + uint32_t block = b_i32_btoh(entry.e_msgh.msg_block); + ivy_selector_to_string(sel->v_sel, s, sizeof s); + ivy_asm_constpool_value_destroy(sel); + + printf(" selector:[%s], block:0x%" PRIx32 + "[%" PRIu32 "]", + s, block, block); + + break; + } + default: + break; + } + + printf("\n"); + offset += sizeof entry; + } + +cleanup: + if (class_ident) { + ivy_asm_constpool_value_destroy(class_ident); + } + + if (xcls) { + ivy_asm_section_reader_close(xcls); + } + + return status; +} + +static enum ivy_status dump_classes(struct ivy_asm_reader *object) +{ + struct ivy_asm_constpool_reader *pool; + enum ivy_status status + = ivy_asm_reader_open_constpool(object, 0, 0, &pool); + if (status != IVY_OK) { + return status; + } + + printf("classes:\n"); + for (size_t i = 0;; i++) { + status = dump_class(object, pool, i); + if (status == IVY_ERR_NO_ENTRY) { + break; + } + + if (status != IVY_OK) { + return status; + } + } + + return IVY_OK; +} + static enum ivy_status dump_constpool(struct ivy_asm_reader *object) { printf("constpool:\n"); @@ -507,7 +703,7 @@ static int disassemble( } if (classes) { - printf("\nclasses:\n"); + status = dump_classes(reader); } ivy_asm_reader_close(reader); @@ -558,7 +754,8 @@ B_COMMAND(CMD_DISASSEMBLE, CMD_ROOT) B_OPTION_SHORT_NAME('c'); B_OPTION_LONG_NAME("classes"); B_OPTION_DESC( - "print the classes contained in the object file."); + "print the classes contained in the object " + "file."); } B_COMMAND_OPTION(OPT_CONSTPOOL)