134 lines
3.8 KiB
C
134 lines
3.8 KiB
C
#include "header.h"
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
void header_destroy(Header* header)
|
|
{
|
|
for (size_t i = 0; i < header->global_syms_size; ++i) {
|
|
free(header->global_syms[i].ident);
|
|
}
|
|
free(header->global_syms);
|
|
for (size_t i = 0; i < header->extern_syms_size; ++i) {
|
|
free(header->extern_syms[i].ident);
|
|
}
|
|
free(header->extern_syms);
|
|
free(header->extern_refs);
|
|
}
|
|
|
|
int header_read_from(Header* header, FILE* fp, const char* filename)
|
|
{
|
|
int res = 0;
|
|
|
|
uint16_t ident[6] = { 0 };
|
|
if (fread(ident, sizeof(uint16_t), 5, fp) != 5) {
|
|
res = 1;
|
|
goto leave_1;
|
|
}
|
|
if (strcmp((char*)ident, "vc3-object") != 0) {
|
|
res = 2;
|
|
goto leave_1;
|
|
}
|
|
uint16_t header_size;
|
|
if (fread(&header_size, sizeof(uint16_t), 1, fp) != 1) {
|
|
res = 3;
|
|
goto leave_1;
|
|
}
|
|
// We want header size in words, not bytes.
|
|
header_size /= 2;
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
uint16_t* data = malloc(sizeof(uint16_t) * header_size);
|
|
if (fread(data, sizeof(uint16_t), header_size, fp) != header_size) {
|
|
res = 4;
|
|
goto leave_2;
|
|
}
|
|
|
|
size_t dc = 6;
|
|
|
|
uint16_t global_syms_size = data[dc++];
|
|
HeaderGlobalSym* global_syms
|
|
= malloc(sizeof(HeaderGlobalSym) * global_syms_size);
|
|
for (size_t i = 0; i < global_syms_size; ++i) {
|
|
uint16_t offset = data[dc++];
|
|
uint16_t ident_len = data[dc++];
|
|
char* ident = calloc(ident_len + 1, sizeof(char));
|
|
strncpy(ident, (char*)&data[dc], ident_len);
|
|
dc += (size_t)(ident_len + 1) / 2;
|
|
global_syms[i] = (HeaderGlobalSym) { offset, ident };
|
|
}
|
|
|
|
uint16_t extern_syms_size = data[dc++];
|
|
HeaderExternSym* extern_syms
|
|
= malloc(sizeof(HeaderExternSym) * extern_syms_size);
|
|
for (size_t i = 0; i < extern_syms_size; ++i) {
|
|
uint16_t id = data[dc++];
|
|
uint16_t ident_len = data[dc++];
|
|
char* ident = calloc(ident_len + 1, sizeof(char));
|
|
strncpy(ident, (char*)&data[dc], ident_len);
|
|
dc += (size_t)(ident_len + 1) / 2;
|
|
extern_syms[i] = (HeaderExternSym) { id, ident };
|
|
}
|
|
|
|
uint16_t extern_refs_size = data[dc++];
|
|
HeaderExternRef* extern_refs
|
|
= malloc(sizeof(HeaderExternRef) * extern_refs_size);
|
|
for (size_t i = 0; i < extern_refs_size; ++i) {
|
|
uint16_t id = data[dc++];
|
|
uint16_t offset = data[dc++];
|
|
extern_refs[i] = (HeaderExternRef) { id, offset };
|
|
}
|
|
|
|
uint16_t program_size = data[dc++];
|
|
// We want program size in words too.
|
|
program_size /= 2;
|
|
|
|
*header = (Header) {
|
|
header_size,
|
|
global_syms_size,
|
|
global_syms,
|
|
extern_syms_size,
|
|
extern_syms,
|
|
extern_refs_size,
|
|
extern_refs,
|
|
program_size,
|
|
};
|
|
|
|
res = 0;
|
|
leave_2:
|
|
free(data);
|
|
leave_1:
|
|
if (res != 0) {
|
|
fprintf(stderr, "error: malformed object file '%s'\n", filename);
|
|
printf("res = %d\n", res);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void header_print(const Header* header)
|
|
{
|
|
printf("globals:\n");
|
|
printf("address symbol\n");
|
|
printf("-----------------------\n");
|
|
for (size_t i = 0; i < header->global_syms_size; ++i) {
|
|
HeaderGlobalSym* sym = &header->global_syms[i];
|
|
printf("%04x, %s\n", sym->offset, sym->ident);
|
|
}
|
|
printf("\nexterns:\n");
|
|
printf("id symbol\n");
|
|
printf("--------------------\n");
|
|
for (size_t i = 0; i < header->extern_syms_size; ++i) {
|
|
HeaderExternSym* sym = &header->extern_syms[i];
|
|
printf("%-3d %s\n", sym->id, sym->ident);
|
|
}
|
|
printf("\nextern uses:\n");
|
|
printf("id address\n");
|
|
printf("-----------\n");
|
|
for (size_t i = 0; i < header->extern_refs_size; ++i) {
|
|
HeaderExternRef* ref = &header->extern_refs[i];
|
|
printf("%3d %04x\n", ref->id, ref->offset);
|
|
}
|
|
}
|