frontend: disassemble: implement dumping the contents of classes

This commit is contained in:
2025-05-15 12:11:11 +01:00
parent 49d21de894
commit 2b28371cb6

View File

@@ -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("<none>");
}
printf(", set:");
if (set) {
printf("0x%" PRIx32 "[%" PRIu32 "]", set, set);
} else {
printf("<none>");
}
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) static enum ivy_status dump_constpool(struct ivy_asm_reader *object)
{ {
printf("constpool:\n"); printf("constpool:\n");
@@ -507,7 +703,7 @@ static int disassemble(
} }
if (classes) { if (classes) {
printf("\nclasses:\n"); status = dump_classes(reader);
} }
ivy_asm_reader_close(reader); ivy_asm_reader_close(reader);
@@ -558,7 +754,8 @@ B_COMMAND(CMD_DISASSEMBLE, CMD_ROOT)
B_OPTION_SHORT_NAME('c'); B_OPTION_SHORT_NAME('c');
B_OPTION_LONG_NAME("classes"); B_OPTION_LONG_NAME("classes");
B_OPTION_DESC( B_OPTION_DESC(
"print the classes contained in the object file."); "print the classes contained in the object "
"file.");
} }
B_COMMAND_OPTION(OPT_CONSTPOOL) B_COMMAND_OPTION(OPT_CONSTPOOL)