asm: implement object file reader
This commit is contained in:
46
asm/include/ivy/asm/reader.h
Normal file
46
asm/include/ivy/asm/reader.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef IVY_ASM_READER_H_
|
||||
#define IVY_ASM_READER_H_
|
||||
|
||||
#include <ivy/misc.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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
|
||||
181
asm/reader.c
Normal file
181
asm/reader.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#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;
|
||||
}
|
||||
18
asm/reader.h
Normal file
18
asm/reader.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _ASM_READER_H_
|
||||
#define _ASM_READER_H_
|
||||
|
||||
#include <ivy/asm/reader.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user