182 lines
3.7 KiB
C
182 lines
3.7 KiB
C
#include "reader.h"
|
|
|
|
#include <ctype.h>
|
|
#include <ivy/asm/bin.h>
|
|
#include <ivy/asm/reader.h>
|
|
#include <ivy/status.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|