factor/native/relocate.c

216 lines
4.1 KiB
C
Raw Normal View History

2004-07-16 02:26:21 -04:00
#include "factor.h"
2004-12-25 02:55:03 -05:00
void relocate_object(CELL relocating)
2004-07-16 02:26:21 -04:00
{
switch(untag_header(get(relocating)))
{
2004-07-27 23:29:37 -04:00
case WORD_TYPE:
fixup_word((F_WORD*)relocating);
2004-07-27 23:29:37 -04:00
break;
2004-07-16 02:26:21 -04:00
case ARRAY_TYPE:
case TUPLE_TYPE:
fixup_array((F_ARRAY*)relocating);
2004-07-16 02:26:21 -04:00
break;
2005-01-27 20:06:10 -05:00
case HASHTABLE_TYPE:
fixup_hashtable((F_HASHTABLE*)relocating);
break;
2004-07-16 02:26:21 -04:00
case VECTOR_TYPE:
fixup_vector((F_VECTOR*)relocating);
2004-07-16 02:26:21 -04:00
break;
case STRING_TYPE:
rehash_string((F_STRING*)relocating);
break;
2004-07-16 02:26:21 -04:00
case SBUF_TYPE:
fixup_sbuf((F_SBUF*)relocating);
2004-07-16 02:26:21 -04:00
break;
2004-09-21 22:58:54 -04:00
case DLL_TYPE:
fixup_dll((DLL*)relocating);
break;
case ALIEN_TYPE:
fixup_alien((ALIEN*)relocating);
break;
2005-04-09 18:30:46 -04:00
case DISPLACED_ALIEN_TYPE:
fixup_displaced_alien((DISPLACED_ALIEN*)relocating);
break;
case WRAPPER_TYPE:
fixup_wrapper((F_WRAPPER*)relocating);
break;
2004-07-16 02:26:21 -04:00
}
}
2004-12-25 02:55:03 -05:00
INLINE CELL relocate_data_next(CELL relocating)
2004-07-16 02:26:21 -04:00
{
2004-09-08 02:31:03 -04:00
CELL size = CELLS;
CELL cell = get(relocating);
2004-09-08 02:31:03 -04:00
if(headerp(cell))
2004-07-16 02:26:21 -04:00
{
2004-09-08 02:31:03 -04:00
size = untagged_object_size(relocating);
2004-12-25 02:55:03 -05:00
relocate_object(relocating);
2004-07-16 02:26:21 -04:00
}
else if(cell != F)
data_fixup((CELL*)relocating);
2004-12-25 02:55:03 -05:00
return relocating + size;
2004-07-16 02:26:21 -04:00
}
2004-12-25 02:55:03 -05:00
void relocate_data()
2004-07-16 02:26:21 -04:00
{
2005-05-11 00:43:52 -04:00
CELL relocating = tenured.base;
2004-07-16 02:26:21 -04:00
2004-12-25 02:55:03 -05:00
data_fixup(&userenv[BOOT_ENV]);
data_fixup(&userenv[GLOBAL_ENV]);
2005-05-10 22:30:58 -04:00
data_fixup(&T);
data_fixup(&bignum_zero);
data_fixup(&bignum_pos_one);
data_fixup(&bignum_neg_one);
2004-12-25 02:55:03 -05:00
2004-07-16 02:26:21 -04:00
for(;;)
{
2005-05-11 00:43:52 -04:00
if(relocating >= tenured.here)
2004-07-16 02:26:21 -04:00
break;
allot_barrier(relocating);
2004-12-25 02:55:03 -05:00
relocating = relocate_data_next(relocating);
}
relocating = compiling.base;
for(;;)
{
if(relocating >= literal_top)
break;
relocating = relocate_data_next(relocating);
}
}
void undefined_symbol(void)
{
general_error(ERROR_UNDEFINED_SYMBOL,F);
}
2005-04-29 02:36:32 -04:00
CELL get_rel_symbol(F_REL* rel)
2004-12-25 02:55:03 -05:00
{
2005-12-11 15:14:41 -05:00
CELL arg = REL_ARGUMENT(rel);
2005-12-11 18:27:39 -05:00
F_CONS* cons = untag_cons(get(compiling.base + arg * sizeof(CELL)));
2004-12-25 18:08:20 -05:00
F_STRING* symbol = untag_string(cons->car);
DLL* dll = (cons->cdr == F ? NULL : untag_dll(cons->cdr));
CELL sym;
if(dll != NULL && !dll->dll)
return (CELL)undefined_symbol;
sym = (CELL)ffi_dlsym(dll,symbol,false);
if(!sym)
return (CELL)undefined_symbol;
return sym;
2005-04-29 02:36:32 -04:00
}
2005-05-12 03:52:56 -04:00
INLINE CELL compute_code_rel(F_REL *rel, CELL original)
2005-04-29 02:36:32 -04:00
{
switch(REL_TYPE(rel))
2005-05-12 03:52:56 -04:00
{
case F_PRIMITIVE:
2005-12-11 15:14:41 -05:00
return primitive_to_xt(REL_ARGUMENT(rel));
2005-05-12 03:52:56 -04:00
case F_DLSYM:
return get_rel_symbol(rel);
case F_ABSOLUTE:
return original + (compiling.base - code_relocation_base);
case F_USERENV:
2005-12-11 15:14:41 -05:00
return (CELL)&userenv[REL_ARGUMENT(rel)];
2005-05-12 03:52:56 -04:00
case F_CARDS:
return cards_offset;
2005-05-12 03:52:56 -04:00
default:
2005-12-11 15:14:41 -05:00
critical_error("Unsupported rel type",rel->type);
2005-05-13 00:09:49 -04:00
return -1;
2005-05-12 03:52:56 -04:00
}
2005-03-22 21:20:58 -05:00
}
2004-12-25 02:55:03 -05:00
INLINE CELL relocate_code_next(CELL relocating)
{
F_COMPILED* compiled = (F_COMPILED*)relocating;
F_REL* rel = (F_REL*)(
relocating + sizeof(F_COMPILED)
+ compiled->code_length);
F_REL* rel_end = (F_REL*)(
relocating + sizeof(F_COMPILED)
+ compiled->code_length
+ compiled->reloc_length);
if(compiled->header != COMPILED_HEADER)
2005-05-12 01:02:39 -04:00
critical_error("Wrong compiled header",relocating);
2004-12-25 02:55:03 -05:00
while(rel < rel_end)
{
2005-05-12 03:52:56 -04:00
CELL original;
CELL new_value;
code_fixup(&rel->offset);
2005-12-11 15:14:41 -05:00
switch(REL_CLASS(rel))
{
case REL_ABSOLUTE_CELL:
2005-05-12 03:52:56 -04:00
original = get(rel->offset);
2005-12-11 15:14:41 -05:00
break;
case REL_ABSOLUTE:
original = *(u32*)rel->offset;
break;
case REL_RELATIVE:
original = *(u32*)rel->offset - (rel->offset + sizeof(u32));
break;
case REL_2_2:
original = reloc_get_2_2(rel->offset);
break;
default:
critical_error("Unsupported rel class",REL_CLASS(rel));
return -1;
}
2005-05-12 03:52:56 -04:00
2004-12-25 02:55:03 -05:00
/* to_c_string can fill up the heap */
2005-06-16 18:50:49 -04:00
maybe_gc(0);
2005-05-12 03:52:56 -04:00
new_value = compute_code_rel(rel,original);
2004-12-25 02:55:03 -05:00
2005-12-11 15:14:41 -05:00
switch(REL_CLASS(rel))
{
case REL_ABSOLUTE_CELL:
2005-05-12 03:52:56 -04:00
put(rel->offset,new_value);
2005-12-11 15:14:41 -05:00
break;
case REL_ABSOLUTE:
*(u32*)rel->offset = new_value;
break;
case REL_RELATIVE:
*(u32*)rel->offset = new_value - (rel->offset + CELLS);
break;
case REL_2_2:
reloc_set_2_2(rel->offset,new_value);
break;
default:
critical_error("Unsupported rel class",REL_CLASS(rel));
return -1;
}
2004-12-25 02:55:03 -05:00
rel++;
}
return (CELL)rel_end;
}
void relocate_code()
{
/* start relocating from the end of the space reserved for literals */
CELL relocating = literal_max;
for(;;)
{
if(relocating >= compiling.here)
break;
relocating = relocate_code_next(relocating);
2004-07-16 02:26:21 -04:00
}
}