asm: reader: implement constpool reader interface
This commit is contained in:
292
asm/reader.c
292
asm/reader.c
@@ -3,6 +3,8 @@
|
||||
#include <ctype.h>
|
||||
#include <ivy/asm/bin.h>
|
||||
#include <ivy/asm/reader.h>
|
||||
#include <ivy/ident.h>
|
||||
#include <ivy/selector.h>
|
||||
#include <ivy/status.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -115,10 +117,38 @@ const struct ivy_asm_section_info *ivy_asm_reader_get_sections(
|
||||
return reader->r_sections;
|
||||
}
|
||||
|
||||
static size_t find_section(struct ivy_asm_reader *reader, uint32_t type, size_t index)
|
||||
{
|
||||
if (type == IVY_ASM_SECTION_ANY_TYPE) {
|
||||
return index;
|
||||
}
|
||||
|
||||
size_t nr_sections = reader->r_info.obj_nr_sections;
|
||||
for (size_t i = 0; i < nr_sections; i++) {
|
||||
if (reader->r_sections[i].s_type != type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_asm_reader_open_section(
|
||||
struct ivy_asm_reader *reader, size_t index,
|
||||
struct ivy_asm_reader *reader, uint32_t type, size_t index,
|
||||
struct ivy_asm_section_reader **out)
|
||||
{
|
||||
index = find_section(reader, type, index);
|
||||
if (index == (size_t)-1) {
|
||||
return IVY_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
if (index >= reader->r_info.obj_nr_sections) {
|
||||
return IVY_ERR_NO_ENTRY;
|
||||
}
|
||||
@@ -137,6 +167,43 @@ enum ivy_status ivy_asm_reader_open_section(
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_asm_reader_open_constpool(
|
||||
struct ivy_asm_reader *reader, size_t constpool_index,
|
||||
size_t xdat_index, struct ivy_asm_constpool_reader **out)
|
||||
{
|
||||
struct ivy_asm_section_reader *pool = NULL, *xdat = NULL;
|
||||
enum ivy_status status = ivy_asm_reader_open_section(
|
||||
reader, IVY_TABLE_POOL, constpool_index, &pool);
|
||||
if (status == IVY_ERR_NO_ENTRY) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ivy_asm_reader_open_section(
|
||||
reader, IVY_TABLE_XDAT, xdat_index, &xdat);
|
||||
if (status == IVY_ERR_NO_ENTRY) {
|
||||
ivy_asm_section_reader_close(pool);
|
||||
return status;
|
||||
}
|
||||
|
||||
struct ivy_asm_constpool_reader *pool_reader = malloc(sizeof *pool_reader);
|
||||
if (!pool_reader) {
|
||||
ivy_asm_section_reader_close(pool);
|
||||
ivy_asm_section_reader_close(xdat);
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(pool_reader, 0x0, sizeof *pool_reader);
|
||||
|
||||
pool_reader->r_pool = pool;
|
||||
pool_reader->r_xdat = xdat;
|
||||
pool_reader->r_nr_entries
|
||||
= (pool->r_info->s_length - sizeof(struct ivy_bin_constpool))
|
||||
/ sizeof(struct ivy_bin_constpool_table_entry);
|
||||
|
||||
*out = pool_reader;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
const struct ivy_asm_section_info *ivy_asm_section_reader_get_info(
|
||||
struct ivy_asm_section_reader *reader)
|
||||
{
|
||||
@@ -163,6 +230,229 @@ enum ivy_status ivy_asm_section_reader_read(
|
||||
return ferror(fp) ? IVY_ERR_IO_FAILURE : IVY_OK;
|
||||
}
|
||||
|
||||
size_t ivy_asm_constpool_reader_get_nr_entries(
|
||||
struct ivy_asm_constpool_reader *reader)
|
||||
{
|
||||
return reader->r_nr_entries;
|
||||
}
|
||||
|
||||
static enum ivy_status read_string_xdata(
|
||||
struct ivy_asm_constpool_reader *pool, size_t key, char **out)
|
||||
{
|
||||
if (!key) {
|
||||
*out = NULL;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
size_t r;
|
||||
struct ivy_bin_string str;
|
||||
|
||||
enum ivy_status status = ivy_asm_section_reader_read(
|
||||
pool->r_xdat, key, sizeof str, &str, &r);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (r != sizeof str) {
|
||||
return IVY_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
size_t str_len = b_i32_btoh(str.s_len);
|
||||
if (str_len == 0) {
|
||||
*out = NULL;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
char *s = malloc(str_len + 1);
|
||||
if (!s) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = ivy_asm_section_reader_read(
|
||||
pool->r_xdat, key + sizeof str, str_len, s, &r);
|
||||
if (status != IVY_OK) {
|
||||
free(s);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (r != str_len) {
|
||||
free(s);
|
||||
return IVY_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
s[str_len] = 0;
|
||||
*out = s;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_asm_constpool_reader_read_value(
|
||||
struct ivy_asm_constpool_reader *reader, size_t index,
|
||||
struct ivy_asm_constpool_value **out)
|
||||
{
|
||||
struct ivy_bin_constpool_table_entry entry;
|
||||
enum ivy_status status = IVY_OK;
|
||||
size_t r, offset
|
||||
= sizeof(struct ivy_bin_constpool) + (index * sizeof entry);
|
||||
|
||||
status = ivy_asm_section_reader_read(
|
||||
reader->r_pool, offset, sizeof entry, &entry, &r);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (r != sizeof entry) {
|
||||
return IVY_ERR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
unsigned long type = b_i32_btoh(entry.e_type);
|
||||
|
||||
struct ivy_asm_constpool_value *value = malloc(sizeof *value);
|
||||
if (!value) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(value, 0x0, sizeof *value);
|
||||
size_t handle;
|
||||
|
||||
switch (type) {
|
||||
case IVY_CONSTPOOL_TABLE_STRING: {
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_STRING;
|
||||
handle = b_i32_btoh(entry.e_ex_handle);
|
||||
status = read_string_xdata(reader, handle, &value->v_str);
|
||||
break;
|
||||
}
|
||||
case IVY_CONSTPOOL_TABLE_INT:
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_INT;
|
||||
value->v_int = b_i32_btoh(entry.e_int);
|
||||
break;
|
||||
case IVY_CONSTPOOL_TABLE_UINT:
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_UINT;
|
||||
value->v_uint = b_i32_btoh(entry.e_int);
|
||||
break;
|
||||
case IVY_CONSTPOOL_TABLE_ATOM:
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_ATOM;
|
||||
break;
|
||||
case IVY_CONSTPOOL_TABLE_SELECTOR: {
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_SELECTOR;
|
||||
handle = b_i32_btoh(entry.e_ex_handle);
|
||||
|
||||
struct ivy_bin_selector sel_entry;
|
||||
status = ivy_asm_section_reader_read(
|
||||
reader->r_xdat, handle, sizeof sel_entry, &sel_entry, &r);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (r != sizeof sel_entry) {
|
||||
status = IVY_ERR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
struct ivy_selector *sel;
|
||||
status = ivy_selector_create(&sel);
|
||||
if (status != IVY_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sel_entry.sel_flags & IVY_BIN_SELECTOR_OBJECT) {
|
||||
ivy_selector_set_recipient(sel, IVY_SEL_OBJECT);
|
||||
} else if (sel_entry.sel_flags & IVY_BIN_SELECTOR_CLASS) {
|
||||
ivy_selector_set_recipient(sel, IVY_SEL_CLASS);
|
||||
}
|
||||
|
||||
size_t name_key = b_i32_btoh(sel_entry.sel_name);
|
||||
status = read_string_xdata(reader, name_key, &sel->sel_name);
|
||||
if (status != IVY_OK) {
|
||||
ivy_selector_destroy(sel);
|
||||
break;
|
||||
}
|
||||
|
||||
handle += sizeof sel_entry;
|
||||
size_t nr_args = sel_entry.sel_nr_args;
|
||||
for (size_t i = 0; i < nr_args; i++) {
|
||||
b_i32 arg;
|
||||
status = ivy_asm_section_reader_read(
|
||||
reader->r_xdat, handle, sizeof arg, &arg, &r);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (r != sizeof arg) {
|
||||
status = IVY_ERR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t arg_key = b_i32_btoh(arg);
|
||||
char *arg_name = NULL;
|
||||
status = read_string_xdata(reader, arg_key, &arg_name);
|
||||
if (status != IVY_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
ivy_selector_add_arg(sel, arg_name, NULL);
|
||||
free(arg_name);
|
||||
}
|
||||
|
||||
if (status != IVY_OK) {
|
||||
ivy_selector_destroy(sel);
|
||||
break;
|
||||
}
|
||||
|
||||
value->v_sel = sel;
|
||||
break;
|
||||
}
|
||||
case IVY_CONSTPOOL_TABLE_IDENT:
|
||||
value->v_type = IVY_ASM_CONSTPOOL_TYPE_IDENT;
|
||||
break;
|
||||
default:
|
||||
status = IVY_ERR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != IVY_OK) {
|
||||
free(value);
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
*out = value;
|
||||
return status;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_asm_constpool_reader_close(
|
||||
struct ivy_asm_constpool_reader *reader)
|
||||
{
|
||||
ivy_asm_section_reader_close(reader->r_pool);
|
||||
ivy_asm_section_reader_close(reader->r_xdat);
|
||||
free(reader);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_asm_constpool_value_destroy(struct ivy_asm_constpool_value *v)
|
||||
{
|
||||
switch (v->v_type) {
|
||||
case IVY_ASM_CONSTPOOL_TYPE_IDENT:
|
||||
ivy_ident_destroy(v->v_ident);
|
||||
break;
|
||||
case IVY_ASM_CONSTPOOL_TYPE_SELECTOR:
|
||||
ivy_selector_destroy(v->v_sel);
|
||||
break;
|
||||
case IVY_ASM_CONSTPOOL_TYPE_STRING:
|
||||
free(v->v_str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(v);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
bool ivy_asm_section_type_to_string(uint32_t in, char out[5])
|
||||
{
|
||||
b_i32 v = b_i32_htob(in);
|
||||
|
||||
Reference in New Issue
Block a user