From bc5beea311318a46438031d4eeb93fa647e5a9a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Jul 2002 17:06:15 +0000 Subject: [PATCH] getting closer to being able to link --- tools/qfcc/include/obj_file.h | 11 ++ tools/qfcc/include/qfcc.h | 2 + tools/qfcc/include/reloc.h | 1 + tools/qfcc/source/linker.c | 189 ++++++++++++++++++++++++++++++---- tools/qfcc/source/obj_file.c | 86 ++++++++++++++++ tools/qfcc/source/reloc.c | 2 + 6 files changed, 273 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 3b93c7892..76381f10d 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -72,6 +72,7 @@ typedef struct qfo_def_s { #define QFOD_ABSOLUTE (1u<<2) #define QFOD_GLOBAL (1u<<3) #define QFOD_EXTERNAL (1u<<4) +#define QFOD_LOCAL (1u<<5) typedef struct qfo_function_s { string_t name; @@ -133,5 +134,15 @@ typedef struct qfo_s { int write_obj_file (const char *filename); qfo_t *read_obj_file (const char *filename); +qfo_t *qfo_new (void); +void qfo_add_code (qfo_t *qfo, dstatement_t *code, int code_size); +void qfo_add_data (qfo_t *qfo, pr_type_t *data, int data_size); +void qfo_add_far_data (qfo_t *qfo, pr_type_t *far_data, int far_data_size); +void qfo_add_strings (qfo_t *qfo, const char *strings, int strings_size); +void qfo_add_relocs (qfo_t *qfo, qfo_reloc_t *relocs, int num_relocs); +void qfo_add_defs (qfo_t *qfo, qfo_def_t *defs, int num_defs); +void qfo_add_functions (qfo_t *qfo, qfo_function_t *functions, int num_functions); +void qfo_add_types (qfo_t *qfo, const char *types, int types_size); +void qfo_delete (qfo_t *qfo); #endif//__obj_file_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 229f789c4..14e929f32 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -108,4 +108,6 @@ int yyparse (void); memset (v, 0, sizeof (*v)); \ } while (0) +#define RUP(x,a) (((x) + ((a) - 1)) % (a)) + #endif//__qfcc_h diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index 4c871a3e6..86ba3f30d 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -43,6 +43,7 @@ typedef enum { rel_def_op, rel_def_def, rel_def_func, + rel_def_string, } reloc_type; typedef struct reloc_s { diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index dfffa9d37..d7adf0377 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -49,6 +49,7 @@ static const char rcsid[] = #include "immediate.h" #include "obj_file.h" #include "qfcc.h" +#include "reloc.h" #include "strpool.h" static hashtab_t *extern_defs; @@ -59,9 +60,27 @@ static defspace_t *data; static defspace_t *far_data; static strpool_t *strings; static strpool_t *type_strings; +static struct { + qfo_reloc_t *relocs; + int num_relocs; + int max_relocs; +} relocs; +static struct { + qfo_def_t *defs; + int num_defs; + int max_defs; +} defs; +static struct { + qfo_function_t *funcs; + int num_funcs; + int max_funcs; +} funcs; static int code_base; static int data_base; static int far_data_base; +static int reloc_base; +static int def_base; +static int func_base; static const char * defs_get_key (void *_def, void *unused) @@ -71,20 +90,80 @@ defs_get_key (void *_def, void *unused) return G_GETSTR (def->name); } -void +static void +add_strings (qfo_t *qfo) +{ + int i; + + for (i = 0; i < qfo->strings_size; i += strlen (qfo->strings + i)) + strpool_addstr (strings, qfo->strings + i); +} + +static void +add_relocs (qfo_t *qfo) +{ + int i; + + if (relocs.num_relocs + qfo->num_relocs > relocs.max_relocs) { + relocs.max_relocs = RUP (relocs.num_relocs + qfo->num_relocs, 16384); + relocs.relocs = realloc (relocs.relocs, + relocs.max_relocs * sizeof (qfo_reloc_t)); + } + relocs.num_relocs += qfo->num_relocs; + memcpy (relocs.relocs + reloc_base, qfo->relocs, + qfo->num_relocs * sizeof (qfo_reloc_t)); + for (i = reloc_base; i < relocs.num_relocs; i++) { + qfo_reloc_t *reloc = relocs.relocs + i; + switch ((reloc_type)reloc->type) { + case rel_none: + break; + case rel_op_a_def: + case rel_op_b_def: + case rel_op_c_def: + case rel_op_a_op: + case rel_op_b_op: + case rel_op_c_op: + reloc->ofs += code_base; + break; + case rel_def_op: + case rel_def_def: + case rel_def_func: + case rel_def_string: + reloc->ofs += data_base; + break; + } + } +} + +static void add_defs (qfo_t *qfo) { - qfo_def_t *def; - qfo_def_t *d; + int i; + + if (defs.num_defs + qfo->num_defs > defs.max_defs) { + defs.max_defs = RUP (defs.num_defs + qfo->num_defs, 16384); + defs.defs = realloc (defs.defs, defs.max_defs * sizeof (qfo_def_t)); + } + defs.num_defs += qfo->num_defs; + memcpy (defs.defs + def_base, qfo->defs, + qfo->num_defs * sizeof (qfo_def_t)); + for (i = def_base; i < defs.num_defs; i++) { + qfo_def_t *def = defs.defs + i; - for (def = qfo->defs; def - qfo->defs < qfo->num_defs; def++) { def->full_type = strpool_addstr (type_strings, - qfo->strings + def->full_type); - def->name = strpool_addstr (strings, qfo->strings + def->name); - def->file = strpool_addstr (strings, qfo->strings + def->file); + qfo->types + def->full_type); + def->name = strpool_addstr (strings, qfo->strings + def->name); + if (!(def->flags & (QFOD_LOCAL | QFOD_ABSOLUTE))) { + def->ofs += data_base; + } + def->relocs += reloc_base; + def->file = strpool_addstr (strings, qfo->strings + def->file); + if (def->flags & QFOD_EXTERNAL) { Hash_Add (extern_defs, def); } else { + qfo_def_t *d; + if (def->flags & QFOD_GLOBAL) { if ((d = Hash_Find (defined_defs, G_GETSTR (def->name)))) { pr.source_file = def->file; @@ -117,17 +196,73 @@ add_defs (qfo_t *qfo) } } -void -add_functions (qfo_t *qfo) +static void +add_funcs (qfo_t *qfo) { - qfo_function_t *func; + int i; - for (func = qfo->functions; func - qfo->functions < qfo->num_functions; - func++) { + if (funcs.num_funcs + qfo->num_functions > funcs.max_funcs) { + funcs.max_funcs = RUP (funcs.num_funcs + qfo->num_functions, 16384); + funcs.funcs = realloc (funcs.funcs, + funcs.max_funcs * sizeof (qfo_function_t)); + } + funcs.num_funcs += qfo->num_functions; + memcpy (funcs.funcs + func_base, qfo->functions, + qfo->num_functions * sizeof (qfo_function_t)); + for (i = func_base; i < funcs.num_funcs; i++) { + qfo_function_t *func = funcs.funcs + i; func->name = strpool_addstr (strings, qfo->strings + func->name); func->file = strpool_addstr (strings, qfo->strings + func->file); if (func->code) - func->code += pr.code->size; + func->code += code_base; + if (func->def) + func->def += def_base; + if (func->local_defs) + func->local_defs += def_base; + func->relocs += reloc_base; + } +} + +static void +fixup_relocs (qfo_t *qfo) +{ + qfo_reloc_t *reloc; + + for (reloc = relocs.relocs + reloc_base; + reloc - relocs.relocs < relocs.num_relocs; + reloc++) { + switch ((reloc_type)reloc->type) { + case rel_none: + break; + case rel_op_a_def: + code->code[reloc->ofs].a += data_base; + break; + case rel_op_b_def: + code->code[reloc->ofs].b += data_base; + break; + case rel_op_c_def: + code->code[reloc->ofs].c += data_base; + break; + case rel_op_a_op: + case rel_op_b_op: + case rel_op_c_op: + break; + case rel_def_op: + data->data[reloc->ofs].integer_var += code_base; + break; + case rel_def_def: + data->data[reloc->ofs].integer_var += data_base; + break; + case rel_def_func: + data->data[reloc->ofs].integer_var += func_base; + break; + case rel_def_string: + data->data[reloc->ofs].string_var = + strpool_addstr (strings, + qfo->strings + data->data[reloc->ofs].string_var); + reloc->ofs += data_base; + break; + } } } @@ -157,13 +292,31 @@ linker_add_object_file (const char *filename) code_base = code->size; data_base = data->size; far_data_base = far_data->size; + reloc_base = relocs.num_relocs; + def_base = defs.num_defs; + func_base = funcs.num_funcs; - add_defs (qfo); - add_functions (qfo); codespace_addcode (code, qfo->code, qfo->code_size); - //add_data (qfo); - //add_far_data (qfo); - //add_strings (qfo); + defspace_adddata (data, qfo->data, qfo->data_size); + defspace_adddata (far_data, qfo->far_data, qfo->far_data_size); + add_strings (qfo); + add_relocs (qfo); + add_defs (qfo); + add_funcs (qfo); + + fixup_relocs (qfo); + + qfo_delete (qfo); + + qfo = qfo_new (); + qfo_add_code (qfo, code->code, code->size); + qfo_add_data (qfo, data->data, data->size); + qfo_add_far_data (qfo, far_data->data, far_data->size); + qfo_add_strings (qfo, strings->strings, strings->size); + qfo_add_relocs (qfo, relocs.relocs, relocs.num_relocs); + qfo_add_defs (qfo, defs.defs, defs.num_defs); + qfo_add_functions (qfo, funcs.funcs, funcs.num_funcs); + qfo_add_types (qfo, type_strings->strings, type_strings->size); } void diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index a01839676..4d7d523f7 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -499,3 +499,89 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr) } return 0; } + +qfo_t * +qfo_new (void) +{ + return calloc (1, sizeof (qfo_t)); +} + +void +qfo_add_code (qfo_t *qfo, dstatement_t *code, int code_size) +{ + qfo->code = malloc (code_size * sizeof (dstatement_t)); + memcpy (qfo->code, code, code_size * sizeof (dstatement_t)); +} + +void +qfo_add_data (qfo_t *qfo, pr_type_t *data, int data_size) +{ + qfo->data = malloc (data_size * sizeof (pr_type_t)); + memcpy (qfo->data, data, data_size * sizeof (pr_type_t)); +} + +void +qfo_add_far_data (qfo_t *qfo, pr_type_t *far_data, int far_data_size) +{ + qfo->far_data = malloc (far_data_size * sizeof (pr_type_t)); + memcpy (qfo->far_data, far_data, far_data_size * sizeof (pr_type_t)); +} + +void +qfo_add_strings (qfo_t *qfo, const char *strings, int strings_size) +{ + qfo->strings = malloc (strings_size); + memcpy (qfo->strings, strings, strings_size); +} + +void +qfo_add_relocs (qfo_t *qfo, qfo_reloc_t *relocs, int num_relocs) +{ + qfo->relocs = malloc (num_relocs * sizeof (qfo_reloc_t)); + memcpy (qfo->relocs, relocs, num_relocs * sizeof (qfo_reloc_t)); +} + +void +qfo_add_defs (qfo_t *qfo, qfo_def_t *defs, int num_defs) +{ + qfo->defs = malloc (num_defs * sizeof (qfo_def_t)); + memcpy (qfo->defs, defs, num_defs * sizeof (qfo_def_t)); +} + +void +qfo_add_functions (qfo_t *qfo, qfo_function_t *functions, int num_functions) +{ + qfo->functions = malloc (num_functions * sizeof (qfo_function_t)); + memcpy (qfo->functions, functions, num_functions * sizeof (qfo_function_t)); +} + +void +qfo_add_types (qfo_t *qfo, const char *types, int types_size) +{ + qfo->types = malloc (types_size); + memcpy (qfo->types, types, types_size); +} + +void +qfo_delete (qfo_t *qfo) +{ + if (!qfo) + return; + if (qfo->code) + free (qfo->code); + if (qfo->data) + free (qfo->data); + if (qfo->far_data) + free (qfo->far_data); + if (qfo->strings) + free (qfo->strings); + if (qfo->relocs) + free (qfo->relocs); + if (qfo->defs) + free (qfo->defs); + if (qfo->functions) + free (qfo->functions); + if (qfo->types) + free (qfo->types); + free (qfo); +} diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 9e72fa9ba..6c924325e 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -107,6 +107,8 @@ relocate_refs (reloc_t *refs, int ofs) case rel_def_func: G_INT (refs->ofs) = ofs; break; + case rel_def_string: + break; } refs = refs->next; }