Partial linking for a single qfo file now seems to work.

This commit is contained in:
Bill Currie 2011-03-02 14:03:41 +09:00
parent bfeece3255
commit 065d3e0dd7
1 changed files with 133 additions and 47 deletions

View File

@ -957,13 +957,10 @@ undefined_def (qfo_def_t *def)
}
}
qfo_t *
linker_finish (void)
static void
check_defs (void)
{
defref_t **undef_defs, **defref;
qfo_t *qfo;
if (!options.partial_link) {
int did_self = 0, did_this = 0;
undef_defs = (defref_t **) Hash_GetList (extern_defs);
@ -1005,15 +1002,104 @@ linker_finish (void)
undefined_def (def);
}
free (undef_defs);
}
static qfo_t *
build_qfo (void)
{
qfo_t *qfo;
int size;
int i;
qfo_mspace_t *space;
qfo_reloc_t *reloc;
qfo_def_t **defs;
qfo = qfo_new ();
qfo->spaces = calloc (work->num_spaces, sizeof (qfo_mspace_t));
qfo->num_spaces = work->num_spaces;
for (i = 0; i < work->num_spaces; i++) {
space = &work->spaces[i];
qfo->spaces[i].type = work->spaces[i].type;
qfo->spaces[i].id = work->spaces[i].id;
qfo->spaces[i].d = work->spaces[i].d;
qfo->spaces[i].data_size = work->spaces[i].data_size;
}
// allocate space for all relocs and copy in the loose relocs. bound
// relocs will be handled with defs and funcs.
size = work->num_relocs + work_num_loose_relocs;
qfo->relocs = malloc (size * sizeof (qfo_reloc_t));
reloc = qfo->relocs;
memcpy (qfo->relocs + work->num_relocs, work_loose_relocs,
work_num_loose_relocs * sizeof (qfo_reloc_t));
qfo->num_relocs = size;
qfo->num_loose_relocs = work_num_loose_relocs;
qfo->funcs = work->funcs;
qfo->num_funcs = work->num_funcs;
qfo->lines = work->lines;
qfo->num_lines = work->num_lines;
// count final defs
for (i = 0; i < num_work_defrefs; i++) {
if (work_defrefs[i]->merge)
continue;
qfo->num_defs++;
qfo->spaces[work_defrefs[i]->space].num_defs++;
}
qfo->defs = malloc (qfo->num_defs * sizeof (qfo_def_t));
defs = alloca (qfo->num_spaces * sizeof (qfo_def_t *));
defs[0] = qfo->defs;
for (i = 1; i < qfo->num_spaces; i++) {
defs[i] = defs[i - 1] + qfo->spaces[i - 1].num_defs;
if (qfo->spaces[i].num_defs)
qfo->spaces[i].defs = defs[i];
}
for (i = 0; i < num_work_defrefs; i++) {
defref_t *r = work_defrefs[i];
qfo_def_t d;
int space;
if (r->merge)
continue;
space = r->space;
d = *REF (r);
d.relocs = reloc - qfo->relocs;
memcpy (reloc, work->relocs + REF (r)->relocs,
REF (r)->num_relocs * sizeof (qfo_reloc_t));
reloc += REF (r)->num_relocs;
r->def_list = &qfo->spaces[space].defs;
r->def = defs[space] - qfo->defs;
// copy relocs from merged defs
for (r = r->merge_list; r; r = r->next) {
memcpy (reloc, work->relocs + REF (r)->relocs,
REF (r)->num_relocs * sizeof (qfo_reloc_t));
reloc += REF (r)->num_relocs;
d.num_relocs += REF (r)->num_relocs;
r->def_list = &qfo->spaces[space].defs;
r->space = space;
r->def = defs[space] - qfo->defs;
}
*defs[space]++ = d;
}
for (i = 0; i < qfo->num_funcs; i++) {
qfo_func_t *f = &qfo->funcs[i];
f->def = work_defrefs[f->def]->def;
memcpy (reloc, work->relocs + f->relocs,
f->num_relocs * sizeof (qfo_reloc_t));
reloc += f->num_relocs;
}
return qfo;
}
qfo_t *
linker_finish (void)
{
if (!options.partial_link) {
check_defs ();
if (pr.error_count)
return 0;
}
//fixup_relocs ();
qfo = qfo_new ();
return work;
return build_qfo ();
}
void