asm: reader: implement constpool reader interface
This commit is contained in:
@@ -6,6 +6,20 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define IVY_ASM_SECTION_ANY_TYPE ((uint32_t) - 1)
|
||||||
|
|
||||||
|
struct ivy_ident;
|
||||||
|
|
||||||
|
enum ivy_asm_constpool_value_type {
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_NONE = 0,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_INT,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_UINT,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_STRING,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_ATOM,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_IDENT,
|
||||||
|
IVY_ASM_CONSTPOOL_TYPE_SELECTOR,
|
||||||
|
};
|
||||||
|
|
||||||
struct ivy_asm_object_info {
|
struct ivy_asm_object_info {
|
||||||
uint32_t obj_magic;
|
uint32_t obj_magic;
|
||||||
size_t obj_table_offset;
|
size_t obj_table_offset;
|
||||||
@@ -18,8 +32,21 @@ struct ivy_asm_section_info {
|
|||||||
size_t s_length;
|
size_t s_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ivy_asm_constpool_value {
|
||||||
|
enum ivy_asm_constpool_value_type v_type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
long long v_int;
|
||||||
|
unsigned long long v_uint;
|
||||||
|
struct ivy_ident *v_ident;
|
||||||
|
struct ivy_selector *v_sel;
|
||||||
|
char *v_str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct ivy_asm_reader;
|
struct ivy_asm_reader;
|
||||||
struct ivy_asm_section_reader;
|
struct ivy_asm_section_reader;
|
||||||
|
struct ivy_asm_constpool_reader;
|
||||||
|
|
||||||
IVY_API enum ivy_status ivy_asm_reader_open(FILE *in, struct ivy_asm_reader **out);
|
IVY_API enum ivy_status ivy_asm_reader_open(FILE *in, struct ivy_asm_reader **out);
|
||||||
IVY_API enum ivy_status ivy_asm_reader_close(struct ivy_asm_reader *reader);
|
IVY_API enum ivy_status ivy_asm_reader_close(struct ivy_asm_reader *reader);
|
||||||
@@ -30,8 +57,11 @@ IVY_API const struct ivy_asm_section_info *ivy_asm_reader_get_sections(
|
|||||||
struct ivy_asm_reader *reader);
|
struct ivy_asm_reader *reader);
|
||||||
|
|
||||||
IVY_API enum ivy_status ivy_asm_reader_open_section(
|
IVY_API 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);
|
struct ivy_asm_section_reader **out);
|
||||||
|
IVY_API 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);
|
||||||
|
|
||||||
IVY_API const struct ivy_asm_section_info *ivy_asm_section_reader_get_info(
|
IVY_API const struct ivy_asm_section_info *ivy_asm_section_reader_get_info(
|
||||||
struct ivy_asm_section_reader *reader);
|
struct ivy_asm_section_reader *reader);
|
||||||
@@ -41,6 +71,17 @@ IVY_API enum ivy_status ivy_asm_section_reader_read(
|
|||||||
struct ivy_asm_section_reader *reader, size_t offset, size_t count,
|
struct ivy_asm_section_reader *reader, size_t offset, size_t count,
|
||||||
void *p, size_t *nr_read);
|
void *p, size_t *nr_read);
|
||||||
|
|
||||||
|
IVY_API size_t ivy_asm_constpool_reader_get_nr_entries(
|
||||||
|
struct ivy_asm_constpool_reader *reader);
|
||||||
|
IVY_API enum ivy_status ivy_asm_constpool_reader_read_value(
|
||||||
|
struct ivy_asm_constpool_reader *reader, size_t index,
|
||||||
|
struct ivy_asm_constpool_value **out);
|
||||||
|
IVY_API enum ivy_status ivy_asm_constpool_reader_close(
|
||||||
|
struct ivy_asm_constpool_reader *reader);
|
||||||
|
|
||||||
|
IVY_API enum ivy_status ivy_asm_constpool_value_destroy(
|
||||||
|
struct ivy_asm_constpool_value *v);
|
||||||
|
|
||||||
IVY_API bool ivy_asm_section_type_to_string(uint32_t in, char out[5]);
|
IVY_API bool ivy_asm_section_type_to_string(uint32_t in, char out[5]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
292
asm/reader.c
292
asm/reader.c
@@ -3,6 +3,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <ivy/asm/bin.h>
|
#include <ivy/asm/bin.h>
|
||||||
#include <ivy/asm/reader.h>
|
#include <ivy/asm/reader.h>
|
||||||
|
#include <ivy/ident.h>
|
||||||
|
#include <ivy/selector.h>
|
||||||
#include <ivy/status.h>
|
#include <ivy/status.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -115,10 +117,38 @@ const struct ivy_asm_section_info *ivy_asm_reader_get_sections(
|
|||||||
return reader->r_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(
|
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)
|
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) {
|
if (index >= reader->r_info.obj_nr_sections) {
|
||||||
return IVY_ERR_NO_ENTRY;
|
return IVY_ERR_NO_ENTRY;
|
||||||
}
|
}
|
||||||
@@ -137,6 +167,43 @@ enum ivy_status ivy_asm_reader_open_section(
|
|||||||
return IVY_OK;
|
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(
|
const struct ivy_asm_section_info *ivy_asm_section_reader_get_info(
|
||||||
struct ivy_asm_section_reader *reader)
|
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;
|
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])
|
bool ivy_asm_section_type_to_string(uint32_t in, char out[5])
|
||||||
{
|
{
|
||||||
b_i32 v = b_i32_htob(in);
|
b_i32 v = b_i32_htob(in);
|
||||||
|
|||||||
@@ -15,4 +15,9 @@ struct ivy_asm_section_reader {
|
|||||||
const struct ivy_asm_section_info *r_info;
|
const struct ivy_asm_section_info *r_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ivy_asm_constpool_reader {
|
||||||
|
size_t r_nr_entries;
|
||||||
|
struct ivy_asm_section_reader *r_pool, *r_xdat;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user