frontend: disassemble: add a range of switches to control what information is provided
This commit is contained in:
@@ -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, §);
|
||||
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,6 +516,20 @@ 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');
|
||||
@@ -441,5 +539,21 @@ B_COMMAND(CMD_DISASSEMBLE, CMD_ROOT)
|
||||
"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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user