add link
This commit is contained in:
parent
87abdd99c6
commit
0f93a28a4b
18
Makefile
18
Makefile
@ -36,13 +36,16 @@ HEADERS = $(shell find . -name *.h)
|
|||||||
ASM_SOURCES = $(shell find asm/ -name *.c -not -name main.c)
|
ASM_SOURCES = $(shell find asm/ -name *.c -not -name main.c)
|
||||||
ASM_OBJECTS = $(patsubst %.c,build/%.o,$(ASM_SOURCES))
|
ASM_OBJECTS = $(patsubst %.c,build/%.o,$(ASM_SOURCES))
|
||||||
|
|
||||||
|
LINK_SOURCES = $(shell find link/ -name *.c)
|
||||||
|
LINK_OBJECTS = $(patsubst %.c,build/%.o,$(LINK_SOURCES))
|
||||||
|
|
||||||
VM_SOURCES = $(shell find vm/ -name *.c)
|
VM_SOURCES = $(shell find vm/ -name *.c)
|
||||||
VM_OBJECTS = $(patsubst %.c,build/%.o,$(VM_SOURCES))
|
VM_OBJECTS = $(patsubst %.c,build/%.o,$(VM_SOURCES))
|
||||||
|
|
||||||
KERN_SOURCES = $(shell find kern/ -name *.c)
|
KERN_SOURCES = $(shell find kern/ -name *.c)
|
||||||
KERN_OBJECTS = $(patsubst %.c,build/%.o,$(KERN_SOURCES))
|
KERN_OBJECTS = $(patsubst %.c,build/%.o,$(KERN_SOURCES))
|
||||||
|
|
||||||
all: bin/vm bin/build_disk_image bin/asm
|
all: bin/vm bin/build_disk_image bin/asm bin/link
|
||||||
|
|
||||||
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS) build/image
|
bin/vm: $(VM_OBJECTS) $(ASM_OBJECTS) build/image
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@ -56,6 +59,10 @@ bin/build_disk_image: $(KERN_OBJECTS) $(ASM_OBJECTS)
|
|||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
|
bin/link: $(LINK_OBJECTS)
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
|
|
||||||
bin/asm: $(ASM_OBJECTS) build/asm/main.o
|
bin/asm: $(ASM_OBJECTS) build/asm/main.o
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
$(CC) $^ -o $@ $(F_FLAGS) $(OPTIMIZATION) $(L_FLAGS)
|
||||||
@ -64,6 +71,15 @@ build/%.o: %.c $(HEADERS)
|
|||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $< -c -o $@ $(C_FLAGS) $(OPTIMIZATION) $(F_FLAGS)
|
$(CC) $< -c -o $@ $(C_FLAGS) $(OPTIMIZATION) $(F_FLAGS)
|
||||||
|
|
||||||
|
.PHONY: run_kern clean
|
||||||
|
|
||||||
|
run_kern_main_asm: bin/asm bin/vm
|
||||||
|
./bin/asm kern/main.asm
|
||||||
|
./bin/vm -i out.o
|
||||||
|
|
||||||
|
link_kern: bin/asm bin/link
|
||||||
|
./bin/asm kern/main.asm -o build/kern_main.o
|
||||||
|
./bin/link -p kern -o build/kern.out build/kern_main.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build/ bin/
|
rm -rf build/ bin/
|
||||||
|
@ -11,17 +11,17 @@ typedef struct {
|
|||||||
char* ident;
|
char* ident;
|
||||||
Loc loc;
|
Loc loc;
|
||||||
uint16_t ip;
|
uint16_t ip;
|
||||||
} GlobalSym;
|
} HeaderGlobalSym;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t id;
|
size_t id;
|
||||||
char* ident;
|
char* ident;
|
||||||
} ExternSym;
|
} HeaderExternSym;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t id;
|
size_t id;
|
||||||
uint16_t ip;
|
uint16_t ip;
|
||||||
} ExternRef;
|
} HeaderExternRef;
|
||||||
|
|
||||||
#define DEFINE_VEC_FIELDS(T, NAME) \
|
#define DEFINE_VEC_FIELDS(T, NAME) \
|
||||||
size_t NAME##_capacity; \
|
size_t NAME##_capacity; \
|
||||||
@ -29,9 +29,9 @@ typedef struct {
|
|||||||
size_t NAME##_size;
|
size_t NAME##_size;
|
||||||
|
|
||||||
struct HeaderBuilder {
|
struct HeaderBuilder {
|
||||||
DEFINE_VEC_FIELDS(GlobalSym, global_syms)
|
DEFINE_VEC_FIELDS(HeaderGlobalSym, global_syms)
|
||||||
DEFINE_VEC_FIELDS(ExternSym, extern_syms)
|
DEFINE_VEC_FIELDS(HeaderExternSym, extern_syms)
|
||||||
DEFINE_VEC_FIELDS(ExternRef, extern_refs)
|
DEFINE_VEC_FIELDS(HeaderExternRef, extern_refs)
|
||||||
size_t program_size;
|
size_t program_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,9 +48,9 @@ HeaderBuilder* header_builder_new(void)
|
|||||||
HeaderBuilder* builder = malloc(sizeof(HeaderBuilder));
|
HeaderBuilder* builder = malloc(sizeof(HeaderBuilder));
|
||||||
|
|
||||||
*builder = (HeaderBuilder) {
|
*builder = (HeaderBuilder) {
|
||||||
VEC_CTOR_INIT(GlobalSym, global_syms, 8),
|
VEC_CTOR_INIT(HeaderGlobalSym, global_syms, 8),
|
||||||
VEC_CTOR_INIT(ExternSym, extern_syms, 8),
|
VEC_CTOR_INIT(HeaderExternSym, extern_syms, 8),
|
||||||
VEC_CTOR_INIT(ExternRef, extern_refs, 8),
|
VEC_CTOR_INIT(HeaderExternRef, extern_refs, 8),
|
||||||
.program_size = 0,
|
.program_size = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,19 +84,19 @@ void header_builder_free(HeaderBuilder* builder)
|
|||||||
void header_builder_add_global_sym(
|
void header_builder_add_global_sym(
|
||||||
HeaderBuilder* builder, char* ident, Loc loc, uint16_t ip)
|
HeaderBuilder* builder, char* ident, Loc loc, uint16_t ip)
|
||||||
{
|
{
|
||||||
VEC_PUSH(builder, GlobalSym, global_syms, ident, loc, ip);
|
VEC_PUSH(builder, HeaderGlobalSym, global_syms, ident, loc, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void header_builder_add_extern_sym(
|
void header_builder_add_extern_sym(
|
||||||
HeaderBuilder* builder, size_t id, char* ident)
|
HeaderBuilder* builder, size_t id, char* ident)
|
||||||
{
|
{
|
||||||
VEC_PUSH(builder, ExternSym, extern_syms, id, ident);
|
VEC_PUSH(builder, HeaderExternSym, extern_syms, id, ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
void header_builder_add_extern_ref(
|
void header_builder_add_extern_ref(
|
||||||
HeaderBuilder* builder, size_t id, uint16_t ip)
|
HeaderBuilder* builder, size_t id, uint16_t ip)
|
||||||
{
|
{
|
||||||
VEC_PUSH(builder, ExternRef, extern_refs, id, ip);
|
VEC_PUSH(builder, HeaderExternRef, extern_refs, id, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
int header_builder_resolve_global_syms(
|
int header_builder_resolve_global_syms(
|
||||||
@ -161,9 +161,9 @@ int header_builder_write(const HeaderBuilder* builder,
|
|||||||
|
|
||||||
size_t header_size = 5 + 1 + 1 + 1 + 1 + 1;
|
size_t header_size = 5 + 1 + 1 + 1 + 1 + 1;
|
||||||
for (size_t i = 0; i < builder->global_syms_size; ++i)
|
for (size_t i = 0; i < builder->global_syms_size; ++i)
|
||||||
header_size += 1 + 1 + strlen(builder->global_syms[i].ident);
|
header_size += 1 + 1 + (strlen(builder->global_syms[i].ident) + 1) / 2;
|
||||||
for (size_t i = 0; i < builder->extern_syms_size; ++i)
|
for (size_t i = 0; i < builder->extern_syms_size; ++i)
|
||||||
header_size += 1 + 1 + strlen(builder->extern_syms[i].ident);
|
header_size += 1 + 1 + (strlen(builder->extern_syms[i].ident) + 1) / 2;
|
||||||
for (size_t i = 0; i < builder->extern_refs_size; ++i)
|
for (size_t i = 0; i < builder->extern_refs_size; ++i)
|
||||||
header_size += 1 + 1;
|
header_size += 1 + 1;
|
||||||
header_size *= 2;
|
header_size *= 2;
|
||||||
@ -192,7 +192,7 @@ int header_builder_write(const HeaderBuilder* builder,
|
|||||||
TRY_WRITE_WORD((W)header_size);
|
TRY_WRITE_WORD((W)header_size);
|
||||||
TRY_WRITE_WORD((W)builder->global_syms_size);
|
TRY_WRITE_WORD((W)builder->global_syms_size);
|
||||||
for (size_t i = 0; i < builder->global_syms_size; ++i) {
|
for (size_t i = 0; i < builder->global_syms_size; ++i) {
|
||||||
const GlobalSym* sym = &builder->global_syms[i];
|
const HeaderGlobalSym* sym = &builder->global_syms[i];
|
||||||
TRY_WRITE_WORD(sym->ip);
|
TRY_WRITE_WORD(sym->ip);
|
||||||
size_t ident_len = strlen(sym->ident);
|
size_t ident_len = strlen(sym->ident);
|
||||||
TRY_WRITE_WORD((W)ident_len);
|
TRY_WRITE_WORD((W)ident_len);
|
||||||
@ -201,7 +201,7 @@ int header_builder_write(const HeaderBuilder* builder,
|
|||||||
}
|
}
|
||||||
TRY_WRITE_WORD((W)builder->extern_syms_size);
|
TRY_WRITE_WORD((W)builder->extern_syms_size);
|
||||||
for (size_t i = 0; i < builder->extern_syms_size; ++i) {
|
for (size_t i = 0; i < builder->extern_syms_size; ++i) {
|
||||||
const ExternSym* sym = &builder->extern_syms[i];
|
const HeaderExternSym* sym = &builder->extern_syms[i];
|
||||||
TRY_WRITE_WORD((W)sym->id);
|
TRY_WRITE_WORD((W)sym->id);
|
||||||
size_t ident_len = strlen(sym->ident);
|
size_t ident_len = strlen(sym->ident);
|
||||||
TRY_WRITE_WORD((W)ident_len);
|
TRY_WRITE_WORD((W)ident_len);
|
||||||
@ -210,7 +210,7 @@ int header_builder_write(const HeaderBuilder* builder,
|
|||||||
}
|
}
|
||||||
TRY_WRITE_WORD((W)builder->extern_refs_size);
|
TRY_WRITE_WORD((W)builder->extern_refs_size);
|
||||||
for (size_t i = 0; i < builder->extern_refs_size; ++i) {
|
for (size_t i = 0; i < builder->extern_refs_size; ++i) {
|
||||||
const ExternRef* ref = &builder->extern_refs[i];
|
const HeaderExternRef* ref = &builder->extern_refs[i];
|
||||||
TRY_WRITE_WORD((W)ref->id);
|
TRY_WRITE_WORD((W)ref->id);
|
||||||
TRY_WRITE_WORD(ref->ip);
|
TRY_WRITE_WORD(ref->ip);
|
||||||
}
|
}
|
||||||
@ -228,21 +228,21 @@ void header_builder_print(const HeaderBuilder* builder)
|
|||||||
printf("address symbol\n");
|
printf("address symbol\n");
|
||||||
printf("-----------------------\n");
|
printf("-----------------------\n");
|
||||||
for (size_t i = 0; i < builder->global_syms_size; ++i) {
|
for (size_t i = 0; i < builder->global_syms_size; ++i) {
|
||||||
GlobalSym* sym = &builder->global_syms[i];
|
HeaderGlobalSym* sym = &builder->global_syms[i];
|
||||||
printf("%04x, %s\n", sym->ip, sym->ident);
|
printf("%04x, %s\n", sym->ip, sym->ident);
|
||||||
}
|
}
|
||||||
printf("\nexterns:\n");
|
printf("\nexterns:\n");
|
||||||
printf("id symbol\n");
|
printf("id symbol\n");
|
||||||
printf("--------------------\n");
|
printf("--------------------\n");
|
||||||
for (size_t i = 0; i < builder->extern_syms_size; ++i) {
|
for (size_t i = 0; i < builder->extern_syms_size; ++i) {
|
||||||
ExternSym* sym = &builder->extern_syms[i];
|
HeaderExternSym* sym = &builder->extern_syms[i];
|
||||||
printf("%-3ld %s\n", sym->id, sym->ident);
|
printf("%-3ld %s\n", sym->id, sym->ident);
|
||||||
}
|
}
|
||||||
printf("\nextern uses:\n");
|
printf("\nextern uses:\n");
|
||||||
printf("id address\n");
|
printf("id address\n");
|
||||||
printf("-----------\n");
|
printf("-----------\n");
|
||||||
for (size_t i = 0; i < builder->extern_refs_size; ++i) {
|
for (size_t i = 0; i < builder->extern_refs_size; ++i) {
|
||||||
ExternRef* ref = &builder->extern_refs[i];
|
HeaderExternRef* ref = &builder->extern_refs[i];
|
||||||
printf("%3ld %04x\n", ref->id, ref->ip);
|
printf("%3ld %04x\n", ref->id, ref->ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
|
||||||
include "arch.asm"
|
include "arch.asm"
|
||||||
|
|
||||||
|
global start
|
||||||
|
extern stuff
|
||||||
|
global keyboard_interrupt
|
||||||
|
extern stuff_2
|
||||||
|
|
||||||
start:
|
start:
|
||||||
; rsp points *at* the top element
|
; rsp points *at* the top element
|
||||||
mov rbp, 2048
|
mov rbp, 2048
|
||||||
@ -23,6 +28,8 @@ interrupt_table:
|
|||||||
; size
|
; size
|
||||||
d16 1
|
d16 1
|
||||||
d16 keyboard_interrupt
|
d16 keyboard_interrupt
|
||||||
|
call stuff
|
||||||
|
call stuff_2
|
||||||
nop
|
nop
|
||||||
|
|
||||||
keyboard_interrupt:
|
keyboard_interrupt:
|
||||||
@ -34,6 +41,7 @@ keyboard_interrupt:
|
|||||||
push r2
|
push r2
|
||||||
push r3
|
push r3
|
||||||
|
|
||||||
|
call stuff
|
||||||
in r0, Device_Keyboard
|
in r0, Device_Keyboard
|
||||||
|
|
||||||
cmp r0, 44
|
cmp r0, 44
|
||||||
|
151
link/common.c
Normal file
151
link/common.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include "link.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
const char* file_iter_next(FileIter* iter)
|
||||||
|
{
|
||||||
|
while (iter->files) {
|
||||||
|
const char* arg = iter->argv[iter->argc];
|
||||||
|
iter->argc += 1;
|
||||||
|
if (strcmp(arg, "-o") == 0) {
|
||||||
|
iter->argc += 1;
|
||||||
|
continue;
|
||||||
|
} else if (strcmp(arg, "-p") == 0) {
|
||||||
|
iter->argc += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
iter->files -= 1;
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 += (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 += (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);
|
||||||
|
}
|
||||||
|
}
|
55
link/kern.c
Normal file
55
link/kern.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "link.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int link_kern(const Args* args, FileIter input_files)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
FILE* output_fp = fopen(args->output_file, "wb");
|
||||||
|
if (!output_fp) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"could not open output file '%s' for writing: %s\n",
|
||||||
|
args->output_file,
|
||||||
|
strerror(errno));
|
||||||
|
goto leave_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* input_fp = NULL;
|
||||||
|
Header header = (Header) { 0 };
|
||||||
|
|
||||||
|
const char* input_filename = file_iter_next(&input_files);
|
||||||
|
while (input_filename != NULL) {
|
||||||
|
input_fp = fopen(input_filename, "rb");
|
||||||
|
if (!input_fp) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"could not open input file '%s' for reading: %s\n",
|
||||||
|
input_filename,
|
||||||
|
strerror(errno));
|
||||||
|
goto leave_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_res = header_read_from(&header, input_fp, input_filename);
|
||||||
|
if (read_res != 0) {
|
||||||
|
res = -1;
|
||||||
|
goto leave_1;
|
||||||
|
}
|
||||||
|
header_print(&header);
|
||||||
|
|
||||||
|
fclose(input_fp);
|
||||||
|
input_fp = NULL;
|
||||||
|
|
||||||
|
input_filename = file_iter_next(&input_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
leave_1:
|
||||||
|
if (input_fp)
|
||||||
|
fclose(input_fp);
|
||||||
|
if (header.header_size != 0)
|
||||||
|
header_destroy(&header);
|
||||||
|
fclose(output_fp);
|
||||||
|
leave_0:
|
||||||
|
return res;
|
||||||
|
}
|
57
link/link.h
Normal file
57
link/link.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
typedef enum {
|
||||||
|
Profile_Linked,
|
||||||
|
Profile_Shared,
|
||||||
|
Profile_Kern,
|
||||||
|
} Profile;
|
||||||
|
|
||||||
|
static const char* profile_strs[] = { "linked", "shared", "kern" };
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* output_file;
|
||||||
|
int input_files;
|
||||||
|
Profile profile;
|
||||||
|
} Args;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int argc;
|
||||||
|
char** argv;
|
||||||
|
int files;
|
||||||
|
} FileIter;
|
||||||
|
|
||||||
|
const char* file_iter_next(FileIter* iter);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t offset;
|
||||||
|
char* ident;
|
||||||
|
} HeaderGlobalSym;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t id;
|
||||||
|
char* ident;
|
||||||
|
} HeaderExternSym;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t id;
|
||||||
|
uint16_t offset;
|
||||||
|
} HeaderExternRef;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t header_size;
|
||||||
|
uint16_t global_syms_size;
|
||||||
|
HeaderGlobalSym* global_syms;
|
||||||
|
uint16_t extern_syms_size;
|
||||||
|
HeaderExternSym* extern_syms;
|
||||||
|
uint16_t extern_refs_size;
|
||||||
|
HeaderExternRef* extern_refs;
|
||||||
|
uint16_t program_size;
|
||||||
|
} Header;
|
||||||
|
|
||||||
|
void header_destroy(Header* header);
|
||||||
|
int header_read_from(Header* header, FILE* fp, const char* filename);
|
||||||
|
void header_print(const Header* header);
|
||||||
|
|
||||||
|
int link_kern(const Args* args, FileIter input_files);
|
76
link/main.c
Normal file
76
link/main.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include "link.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static inline Args parse_args(int argc, char** argv);
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
Args args = parse_args(argc, argv);
|
||||||
|
FileIter input_files = { 1, argv, args.input_files };
|
||||||
|
|
||||||
|
switch (args.profile) {
|
||||||
|
case Profile_Linked:
|
||||||
|
case Profile_Shared:
|
||||||
|
fprintf(stderr,
|
||||||
|
"profile '%s' not implemented\n",
|
||||||
|
profile_strs[args.profile]);
|
||||||
|
break;
|
||||||
|
case Profile_Kern:
|
||||||
|
return link_kern(&args, input_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Args parse_args(int argc, char** argv)
|
||||||
|
{
|
||||||
|
const char* output_file = NULL;
|
||||||
|
int input_files = 0;
|
||||||
|
Profile profile = Profile_Linked;
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
if (strcmp(argv[i], "-o") == 0) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= argc) {
|
||||||
|
fprintf(stderr, "no filename given to -o\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
output_file = argv[i];
|
||||||
|
} else if (strcmp(argv[i], "-p") == 0) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= argc) {
|
||||||
|
fprintf(stderr, "no profile given to -p\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strs_size = sizeof(profile_strs) / sizeof(profile_strs[0]);
|
||||||
|
bool found = false;
|
||||||
|
for (size_t si = 0; si < strs_size; ++si) {
|
||||||
|
if (strcmp(profile_strs[si], argv[i]) == 0) {
|
||||||
|
profile = (Profile)si;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
fprintf(stderr, "invalid profile '%s'\n", argv[i]);
|
||||||
|
fprintf(stderr, "valid profiles: linked, shared, kern\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
input_files += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input_files == 0) {
|
||||||
|
fprintf(stderr, "no input files specified\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (output_file == NULL) {
|
||||||
|
output_file = "a.out";
|
||||||
|
}
|
||||||
|
return (Args) {
|
||||||
|
output_file,
|
||||||
|
input_files,
|
||||||
|
profile,
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user