vc3/link/header.c
2025-04-17 13:27:20 +02:00

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