frontend: disassemble: implement dumping the contents of classes
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user