extract object header
This commit is contained in:
parent
0f93a28a4b
commit
3771ed4ee7
163
link/common.c
163
link/common.c
@ -1,9 +1,44 @@
|
||||
#include "link.h"
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char* link_strdup(const char* str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char* val = calloc(len + 1, sizeof(char));
|
||||
strncpy(val, str, len);
|
||||
return val;
|
||||
}
|
||||
|
||||
FILE* open_output_file(const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
if (!fp) {
|
||||
fprintf(stderr,
|
||||
"error: could not open output file '%s' for writing: %s\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
FILE* open_input_file(const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr,
|
||||
"error: could not open input file '%s' for reading: %s\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
const char* file_iter_next(FileIter* iter)
|
||||
{
|
||||
while (iter->files) {
|
||||
@ -21,131 +56,3 @@ const char* file_iter_next(FileIter* iter)
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
133
link/header.c
Normal file
133
link/header.c
Normal file
@ -0,0 +1,133 @@
|
||||
#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);
|
||||
}
|
||||
}
|
34
link/header.h
Normal file
34
link/header.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
35
link/kern.c
35
link/kern.c
@ -1,5 +1,6 @@
|
||||
#include "header.h"
|
||||
#include "link.h"
|
||||
#include <errno.h>
|
||||
#include "sym.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -7,12 +8,15 @@ int link_kern(const Args* args, FileIter input_files)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
FILE* output_fp = fopen(args->output_file, "wb");
|
||||
SymTable sym_table;
|
||||
sym_table_construct(&sym_table);
|
||||
SymTable* syms = &sym_table;
|
||||
|
||||
uint16_t offset = 0;
|
||||
|
||||
FILE* output_fp = open_output_file(args->output_file);
|
||||
if (!output_fp) {
|
||||
fprintf(stderr,
|
||||
"could not open output file '%s' for writing: %s\n",
|
||||
args->output_file,
|
||||
strerror(errno));
|
||||
res = -1;
|
||||
goto leave_0;
|
||||
}
|
||||
|
||||
@ -21,22 +25,20 @@ int link_kern(const Args* args, FileIter input_files)
|
||||
|
||||
const char* input_filename = file_iter_next(&input_files);
|
||||
while (input_filename != NULL) {
|
||||
input_fp = fopen(input_filename, "rb");
|
||||
input_fp = open_input_file(input_filename);
|
||||
if (!input_fp) {
|
||||
fprintf(stderr,
|
||||
"could not open input file '%s' for reading: %s\n",
|
||||
input_filename,
|
||||
strerror(errno));
|
||||
goto leave_1;
|
||||
res = -1;
|
||||
goto leave_0;
|
||||
}
|
||||
|
||||
int read_res = header_read_from(&header, input_fp, input_filename);
|
||||
if (read_res != 0) {
|
||||
res = -1;
|
||||
res = header_read_from(&header, input_fp, input_filename);
|
||||
if (res != 0)
|
||||
goto leave_1;
|
||||
}
|
||||
|
||||
header_print(&header);
|
||||
|
||||
sym_table_walk_header(syms, &header, offset, input_filename);
|
||||
|
||||
fclose(input_fp);
|
||||
input_fp = NULL;
|
||||
|
||||
@ -50,6 +52,7 @@ leave_1:
|
||||
if (header.header_size != 0)
|
||||
header_destroy(&header);
|
||||
fclose(output_fp);
|
||||
sym_table_destroy(&sym_table);
|
||||
leave_0:
|
||||
return res;
|
||||
}
|
||||
|
37
link/link.h
37
link/link.h
@ -1,7 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char* link_strdup(const char* str);
|
||||
|
||||
FILE* open_output_file(const char* filename);
|
||||
FILE* open_input_file(const char* filename);
|
||||
|
||||
typedef enum {
|
||||
Profile_Linked,
|
||||
Profile_Shared,
|
||||
@ -24,34 +31,4 @@ typedef struct {
|
||||
|
||||
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);
|
||||
|
10
link/main.c
10
link/main.c
@ -32,14 +32,14 @@ static inline Args parse_args(int argc, char** argv)
|
||||
if (strcmp(argv[i], "-o") == 0) {
|
||||
i += 1;
|
||||
if (i >= argc) {
|
||||
fprintf(stderr, "no filename given to -o\n");
|
||||
fprintf(stderr, "error: 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");
|
||||
fprintf(stderr, "error: no profile given to -p\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ static inline Args parse_args(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr, "invalid profile '%s'\n", argv[i]);
|
||||
fprintf(stderr, "valid profiles: linked, shared, kern\n");
|
||||
fprintf(stderr, "error: invalid profile '%s'\n", argv[i]);
|
||||
fprintf(stderr, "info: valid profiles: linked, shared, kern\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
@ -62,7 +62,7 @@ static inline Args parse_args(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
if (input_files == 0) {
|
||||
fprintf(stderr, "no input files specified\n");
|
||||
fprintf(stderr, "error: no input files specified\n");
|
||||
exit(1);
|
||||
}
|
||||
if (output_file == NULL) {
|
||||
|
43
link/ref.c
Normal file
43
link/ref.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "ref.h"
|
||||
#include "sym.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void ref_queue_construct(RefQueue* queue)
|
||||
{
|
||||
const size_t start_capacity = 128;
|
||||
*queue = (RefQueue) {
|
||||
.data = malloc(sizeof(Ref) * start_capacity),
|
||||
.capacity = start_capacity,
|
||||
.back = 0,
|
||||
.front = 0,
|
||||
};
|
||||
}
|
||||
|
||||
void ref_queue_destroy(RefQueue* queue)
|
||||
{
|
||||
free(queue->data);
|
||||
}
|
||||
|
||||
void ref_queue_push(RefQueue* queue, const Sym* sym, uint16_t offset)
|
||||
{
|
||||
if (queue->front + 1 > queue->capacity) {
|
||||
queue->capacity *= 2;
|
||||
queue->data = realloc(queue->data, sizeof(Ref) * queue->capacity);
|
||||
}
|
||||
queue->data[queue->front++] = (Ref) { sym, offset };
|
||||
}
|
||||
|
||||
Ref ref_queue_pop(RefQueue* queue)
|
||||
{
|
||||
if (queue->back == queue->front) {
|
||||
fprintf(stderr, "panic: queue underflow\n");
|
||||
exit(1);
|
||||
}
|
||||
return queue->data[queue->back++];
|
||||
}
|
||||
|
||||
size_t ref_queue_size(const RefQueue* queue)
|
||||
{
|
||||
return queue->front - queue->back;
|
||||
}
|
24
link/ref.h
Normal file
24
link/ref.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "sym.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
const Sym* sym;
|
||||
uint16_t offset;
|
||||
} Ref;
|
||||
|
||||
typedef struct RefQueueChunk RefQueueChunk;
|
||||
|
||||
typedef struct {
|
||||
Ref* data;
|
||||
size_t capacity;
|
||||
size_t back;
|
||||
size_t front;
|
||||
} RefQueue;
|
||||
|
||||
void ref_queue_construct(RefQueue* queue);
|
||||
void ref_queue_destroy(RefQueue* queue);
|
||||
void ref_queue_push(RefQueue* queue, const Sym* sym, uint16_t offset);
|
||||
Ref ref_queue_pop(RefQueue* queue);
|
||||
size_t ref_queue_size(const RefQueue* queue);
|
110
link/sym.c
Normal file
110
link/sym.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "sym.h"
|
||||
#include "header.h"
|
||||
#include "link.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void sym_destroy(Sym* sym)
|
||||
{
|
||||
free(sym->ident);
|
||||
}
|
||||
|
||||
void sym_table_construct(SymTable* table)
|
||||
{
|
||||
const size_t syms_capacity = 16;
|
||||
*table = (SymTable) {
|
||||
.syms = malloc(sizeof(SymTable) * syms_capacity),
|
||||
.syms_capacity = syms_capacity,
|
||||
.syms_size = 0,
|
||||
};
|
||||
}
|
||||
|
||||
void sym_table_destroy(SymTable* table)
|
||||
{
|
||||
for (size_t i = 0; i < table->syms_size; ++i) {
|
||||
sym_destroy(&table->syms[i]);
|
||||
}
|
||||
free(table->syms);
|
||||
}
|
||||
|
||||
Sym* sym_table_find(SymTable* table, const char* ident)
|
||||
{
|
||||
for (size_t i = 0; i < table->syms_size; ++i) {
|
||||
Sym* sym = &table->syms[i];
|
||||
if (strcmp(sym->ident, ident) == 0) {
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void sym_table_add(SymTable* table,
|
||||
char* ident,
|
||||
const char* filename,
|
||||
uint16_t offset,
|
||||
bool resolved)
|
||||
{
|
||||
if (table->syms_size + 1 > table->syms_capacity) {
|
||||
table->syms_capacity *= 2;
|
||||
table->syms
|
||||
= realloc(table->syms, sizeof(SymTable) * table->syms_capacity);
|
||||
}
|
||||
table->syms[table->syms_size++]
|
||||
= (Sym) { ident, filename, offset, resolved };
|
||||
}
|
||||
|
||||
void sym_table_add_unresolved(
|
||||
SymTable* table, char* ident, const char* filename)
|
||||
{
|
||||
sym_table_add(table, ident, filename, 0, false);
|
||||
}
|
||||
|
||||
void sym_table_add_resolved(
|
||||
SymTable* table, char* ident, const char* filename, uint16_t offset)
|
||||
{
|
||||
sym_table_add(table, ident, filename, offset, true);
|
||||
}
|
||||
|
||||
int sym_table_walk_header(
|
||||
SymTable* syms, Header* header, uint16_t offset, const char* input_filename)
|
||||
{
|
||||
for (size_t i = 0; i < header->global_syms_size; ++i) {
|
||||
const HeaderGlobalSym* global_sym = &header->global_syms[i];
|
||||
Sym* sym = sym_table_find(syms, global_sym->ident);
|
||||
|
||||
if (!sym) {
|
||||
sym_table_add_resolved(syms,
|
||||
link_strdup(global_sym->ident),
|
||||
input_filename,
|
||||
offset + global_sym->offset);
|
||||
} else if (!sym->resolved) {
|
||||
sym->offset = offset + global_sym->offset;
|
||||
sym->resolved = true;
|
||||
} else {
|
||||
|
||||
fprintf(stderr,
|
||||
"error: duplicate symbol '%s' defined in %s\n",
|
||||
global_sym->ident,
|
||||
input_filename);
|
||||
fprintf(stderr,
|
||||
"info: symbol '%s' originally defined in %s\n",
|
||||
sym->ident,
|
||||
sym->filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < header->extern_syms_size; ++i) {
|
||||
const HeaderExternSym* extern_sym = &header->extern_syms[i];
|
||||
Sym* sym = sym_table_find(syms, extern_sym->ident);
|
||||
|
||||
if (!sym) {
|
||||
sym_table_add_unresolved(
|
||||
syms, link_strdup(extern_sym->ident), input_filename);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
33
link/sym.h
Normal file
33
link/sym.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "header.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char* ident;
|
||||
const char* filename;
|
||||
uint16_t offset;
|
||||
bool resolved;
|
||||
} Sym;
|
||||
|
||||
void sym_destroy(Sym* sym);
|
||||
|
||||
typedef struct {
|
||||
Sym* syms;
|
||||
size_t syms_capacity;
|
||||
size_t syms_size;
|
||||
} SymTable;
|
||||
|
||||
void sym_table_construct(SymTable* table);
|
||||
void sym_table_destroy(SymTable* table);
|
||||
Sym* sym_table_find(SymTable* table, const char* ident);
|
||||
void sym_table_add_unresolved(
|
||||
SymTable* table, char* ident, const char* filename);
|
||||
void sym_table_add_resolved(
|
||||
SymTable* table, char* ident, const char* filename, uint16_t offset);
|
||||
int sym_table_walk_header(SymTable* syms,
|
||||
Header* header,
|
||||
uint16_t offset,
|
||||
const char* input_filename);
|
Loading…
x
Reference in New Issue
Block a user