asm: reader: implement constpool reader interface

This commit is contained in:
2025-05-13 13:23:59 +01:00
parent 179d0dddaa
commit 197ba14a4d
3 changed files with 338 additions and 2 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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