mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 22:31:05 +00:00
Relocate the data in the type encodings space.
Because of the way it is used, the data in the type encodings space needs to always be correct (ie, relocated), even for partially linked object files.
This commit is contained in:
parent
453ac11bc3
commit
39c1034afb
1 changed files with 53 additions and 21 deletions
|
@ -434,23 +434,26 @@ static int
|
|||
add_relocs (qfo_t *qfo, int start, int count, int target)
|
||||
{
|
||||
int size;
|
||||
qfo_reloc_t *reloc;
|
||||
qfo_reloc_t *ireloc;
|
||||
qfo_reloc_t *oreloc;
|
||||
|
||||
size = work->num_relocs + count;
|
||||
work->relocs = realloc (work->relocs, size * sizeof (qfo_reloc_t));
|
||||
memcpy (work->relocs + work->num_relocs, qfo->relocs + start,
|
||||
count * sizeof (qfo_reloc_t));
|
||||
while (work->num_relocs < size) {
|
||||
reloc = work->relocs + work->num_relocs++;
|
||||
if (reloc->space < 0 || reloc->space >= qfo->num_spaces) {
|
||||
linker_error ("bad reloc space: %d (%d)", reloc->space,
|
||||
ireloc = qfo->relocs + start;
|
||||
oreloc = work->relocs + work->num_relocs;
|
||||
for ( ; work->num_relocs < size; ireloc++, oreloc++) {
|
||||
*oreloc = *ireloc;
|
||||
ireloc->type = -1;
|
||||
ireloc->offset = work->num_relocs++;
|
||||
if (oreloc->space < 0 || oreloc->space >= qfo->num_spaces) {
|
||||
linker_error ("bad reloc space: %d (%d)", oreloc->space,
|
||||
qfo->num_spaces);
|
||||
reloc->type = rel_none;
|
||||
oreloc->type = rel_none;
|
||||
continue;
|
||||
}
|
||||
reloc->space = qfo->spaces[reloc->space].id;
|
||||
adjust_reloc_offset (reloc);
|
||||
reloc->target = target;
|
||||
oreloc->space = qfo->spaces[oreloc->space].id;
|
||||
adjust_reloc_offset (oreloc);
|
||||
oreloc->target = target;
|
||||
}
|
||||
return work->num_relocs - count;
|
||||
}
|
||||
|
@ -477,6 +480,8 @@ add_defs (qfo_t *qfo, qfo_mspace_t *space, qfo_mspace_t *dest_space,
|
|||
*odef = *idef; // copy the def data
|
||||
odef->name = linker_add_string (QFOSTR (qfo, idef->name));
|
||||
odef->file = linker_add_string (QFOSTR (qfo, idef->file));
|
||||
idef->file = -1; // mark def as copied
|
||||
idef->line = num_work_defrefs; // so def can be found
|
||||
type = QFOTYPE(idef->type);
|
||||
odef->type = type->t.class; // pointer to type in work
|
||||
if (odef->flags & QFOD_EXTERNAL && !odef->num_relocs)
|
||||
|
@ -776,6 +781,23 @@ type_def_compare (const void *a, const void *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
update_type_space_reloc (qfo_mspace_t *space, qfo_reloc_t *reloc)
|
||||
{
|
||||
qfo_def_t dummy;
|
||||
qfo_def_t *def;
|
||||
|
||||
if (reloc->type == -1)
|
||||
reloc = work->relocs + reloc->offset;
|
||||
dummy.offset = reloc->offset;
|
||||
def = (qfo_def_t *) bsearch (&dummy, space->defs, space->num_defs,
|
||||
sizeof (qfo_def_t), type_def_compare);
|
||||
if (!def)
|
||||
linker_internal_error ("relocation record with invalid address. "
|
||||
"corrupt object file?");
|
||||
reloc->offset += def->type - def->offset;
|
||||
}
|
||||
|
||||
static int
|
||||
process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||
{
|
||||
|
@ -797,21 +819,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
|||
qsort (space->defs, space->num_defs, sizeof (qfo_def_t), type_def_compare);
|
||||
|
||||
// update the offsets of all relocation records that point into the type
|
||||
// encoding space
|
||||
// encoding space.
|
||||
for (i = 0; i < qfo->num_relocs; i++) {
|
||||
qfo_reloc_t *reloc = qfo->relocs + i;
|
||||
qfo_def_t dummy;
|
||||
qfo_def_t *def;
|
||||
|
||||
if (reloc->space != space->id)
|
||||
continue;
|
||||
dummy.offset = reloc->offset;
|
||||
def = (qfo_def_t *) bsearch (&dummy, space->defs, space->num_defs,
|
||||
sizeof (qfo_def_t), type_def_compare);
|
||||
if (!def)
|
||||
linker_internal_error ("relocation record with invalid address. "
|
||||
"corrupt object file?");
|
||||
reloc->offset += def->type - def->offset;
|
||||
update_type_space_reloc (space, reloc);
|
||||
// while we're at it, update the strings so the type space strings
|
||||
// are always correct.
|
||||
if (reloc->type == rel_def_string) {
|
||||
string_t str;
|
||||
str = linker_add_string (QFOSTR (qfo, reloc->target));
|
||||
QFO_STRING (work, reloc->space, reloc->offset) = str;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_builtins; i++) {
|
||||
builtin_sym_t *bi = builtin_symbols + i;
|
||||
|
@ -1255,6 +1276,17 @@ build_qfo (void)
|
|||
reloc++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < qfo->num_relocs; i++) {
|
||||
qfo_def_t *def;
|
||||
|
||||
reloc = qfo->relocs + i;
|
||||
if (reloc->space != qfo_type_space)
|
||||
continue;
|
||||
if (reloc->type != rel_def_def)
|
||||
continue;
|
||||
def = qfo->defs + reloc->target;
|
||||
QFO_INT (qfo, reloc->space, reloc->offset) = def->offset;
|
||||
}
|
||||
return qfo;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue