frontend: disassemble: add a range of switches to control what information is provided

This commit is contained in:
2025-05-13 13:24:43 +01:00
parent 197ba14a4d
commit 6399022cb3

View File

@@ -12,6 +12,7 @@
#include <ivy/asm/parse.h>
#include <ivy/asm/reader.h>
#include <ivy/file.h>
#include <ivy/selector.h>
#include <stdio.h>
#include <stdlib.h>
@@ -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("<unknown>");
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, &sect);
enum ivy_status status = ivy_asm_reader_open_section(
reader, IVY_ASM_SECTION_ANY_TYPE, index, &sect);
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 = &sections[i];
const struct ivy_asm_section_info *sect = &section_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();