diff --git a/asm/include/ivy/asm/reader.h b/asm/include/ivy/asm/reader.h new file mode 100644 index 0000000..fe0849f --- /dev/null +++ b/asm/include/ivy/asm/reader.h @@ -0,0 +1,46 @@ +#ifndef IVY_ASM_READER_H_ +#define IVY_ASM_READER_H_ + +#include +#include +#include +#include + +struct ivy_asm_object_info { + uint32_t obj_magic; + size_t obj_table_offset; + size_t obj_nr_sections; +}; + +struct ivy_asm_section_info { + uint32_t s_type; + size_t s_offset; + size_t s_length; +}; + +struct ivy_asm_reader; +struct ivy_asm_section_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_close(struct ivy_asm_reader *reader); + +IVY_API const struct ivy_asm_object_info *ivy_asm_reader_get_info( + struct ivy_asm_reader *reader); +IVY_API const struct ivy_asm_section_info *ivy_asm_reader_get_sections( + struct ivy_asm_reader *reader); + +IVY_API enum ivy_status ivy_asm_reader_open_section( + struct ivy_asm_reader *reader, size_t index, + struct ivy_asm_section_reader **out); + +IVY_API const struct ivy_asm_section_info *ivy_asm_section_reader_get_info( + struct ivy_asm_section_reader *reader); +IVY_API enum ivy_status ivy_asm_section_reader_close( + struct ivy_asm_section_reader *reader); +IVY_API enum ivy_status ivy_asm_section_reader_read( + struct ivy_asm_section_reader *reader, size_t offset, size_t count, + void *p, size_t *nr_read); + +IVY_API bool ivy_asm_section_type_to_string(uint32_t in, char out[5]); + +#endif diff --git a/asm/reader.c b/asm/reader.c new file mode 100644 index 0000000..3b19596 --- /dev/null +++ b/asm/reader.c @@ -0,0 +1,181 @@ +#include "reader.h" + +#include +#include +#include +#include +#include +#include + +static enum ivy_status decode_header( + const struct ivy_bin_header *hdr, struct ivy_asm_object_info *out) +{ + out->obj_magic = b_i32_btoh(hdr->h_magic); + out->obj_nr_sections = b_i16_btoh(hdr->h_table_len); + out->obj_table_offset = b_i64_btoh(hdr->h_table_offset); + + return IVY_OK; +} + +static enum ivy_status decode_table_entry( + const struct ivy_bin_table_entry *entry, struct ivy_asm_section_info *out) +{ + out->s_type = b_i32_btoh(entry->e_type); + out->s_offset = b_i64_btoh(entry->e_offset); + out->s_length = b_i32_btoh(entry->e_size); + + return IVY_OK; +} + +enum ivy_status ivy_asm_reader_open(FILE *in, struct ivy_asm_reader **out) +{ + struct ivy_asm_reader *reader = malloc(sizeof *reader); + if (!reader) { + return IVY_ERR_NO_MEMORY; + } + + memset(reader, 0x0, sizeof *reader); + + reader->r_fp = in; + + fseek(in, 0, SEEK_SET); + + struct ivy_bin_header hdr; + size_t r = fread(&hdr, sizeof hdr, 1, in); + + if (r != 1) { + free(reader); + return IVY_ERR_IO_FAILURE; + } + + enum ivy_status status = decode_header(&hdr, &reader->r_info); + if (status != IVY_OK) { + free(reader); + return status; + } + + if (reader->r_info.obj_magic != IVY_BIN_MAGIC) { + free(reader); + return IVY_ERR_BAD_FORMAT; + } + + fseek(in, reader->r_info.obj_table_offset, SEEK_SET); + + size_t nr_sections = reader->r_info.obj_nr_sections; + struct ivy_bin_table_entry *table = calloc(nr_sections, sizeof *table); + if (!table) { + free(reader); + return IVY_ERR_NO_MEMORY; + } + + r = fread(table, sizeof *table, nr_sections, in); + if (r != nr_sections) { + free(table); + free(reader); + return IVY_ERR_IO_FAILURE; + } + + struct ivy_asm_section_info *sections + = calloc(nr_sections, sizeof *sections); + for (size_t i = 0; i < nr_sections; i++) { + status = decode_table_entry(&table[i], §ions[i]); + + if (status != IVY_OK) { + free(table); + free(sections); + free(reader); + + return status; + } + } + + free(table); + + reader->r_sections = sections; + + *out = reader; + return IVY_OK; +} + +enum ivy_status ivy_asm_reader_close(struct ivy_asm_reader *reader) +{ + free(reader); + return IVY_OK; +} + +const struct ivy_asm_object_info *ivy_asm_reader_get_info( + struct ivy_asm_reader *reader) +{ + return &reader->r_info; +} + +const struct ivy_asm_section_info *ivy_asm_reader_get_sections( + struct ivy_asm_reader *reader) +{ + return reader->r_sections; +} + +enum ivy_status ivy_asm_reader_open_section( + struct ivy_asm_reader *reader, size_t index, + struct ivy_asm_section_reader **out) +{ + if (index >= reader->r_info.obj_nr_sections) { + return IVY_ERR_NO_ENTRY; + } + + struct ivy_asm_section_reader *sect = malloc(sizeof *sect); + if (!sect) { + return IVY_ERR_NO_MEMORY; + } + + memset(sect, 0x0, sizeof *sect); + + sect->r_parent = reader; + sect->r_info = &reader->r_sections[index]; + + *out = sect; + return IVY_OK; +} + +const struct ivy_asm_section_info *ivy_asm_section_reader_get_info( + struct ivy_asm_section_reader *reader) +{ + return reader->r_info; +} + +enum ivy_status ivy_asm_section_reader_close(struct ivy_asm_section_reader *reader) +{ + free(reader); + return IVY_OK; +} + +enum ivy_status ivy_asm_section_reader_read( + struct ivy_asm_section_reader *reader, size_t offset, size_t count, + void *p, size_t *nr_read) +{ + size_t object_offset = reader->r_info->s_offset + offset; + FILE *fp = reader->r_parent->r_fp; + fseek(fp, object_offset, SEEK_SET); + size_t r = fread(p, 1, count, fp); + + *nr_read = r; + + return ferror(fp) ? IVY_ERR_IO_FAILURE : IVY_OK; +} + +bool ivy_asm_section_type_to_string(uint32_t in, char out[5]) +{ + b_i32 v = b_i32_htob(in); + + for (size_t i = 0; i < sizeof in; i++) { + char c = v.i_bytes[i]; + if (!isgraph(c)) { + return false; + } + + out[i] = c; + } + + out[4] = 0; + return true; +} diff --git a/asm/reader.h b/asm/reader.h new file mode 100644 index 0000000..c7a0480 --- /dev/null +++ b/asm/reader.h @@ -0,0 +1,18 @@ +#ifndef _ASM_READER_H_ +#define _ASM_READER_H_ + +#include +#include + +struct ivy_asm_reader { + FILE *r_fp; + struct ivy_asm_object_info r_info; + struct ivy_asm_section_info *r_sections; +}; + +struct ivy_asm_section_reader { + struct ivy_asm_reader *r_parent; + const struct ivy_asm_section_info *r_info; +}; + +#endif