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)))
|
|
|
|
|
{
|
2006-05-15 18:00:37 -04:00
|
|
|
case RATIO_TYPE:
|
|
|
|
|
fixup_ratio((F_RATIO*)relocating);
|
|
|
|
|
break;
|
|
|
|
|
case COMPLEX_TYPE:
|
|
|
|
|
fixup_complex((F_COMPLEX*)relocating);
|
|
|
|
|
break;
|
2004-07-27 23:29:37 -04:00
|
|
|
case WORD_TYPE:
|
2004-12-10 21:46:42 -05:00
|
|
|
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:
|
2005-01-29 16:39:30 -05:00
|
|
|
case TUPLE_TYPE:
|
2006-05-15 18:15:35 -04:00
|
|
|
case QUOTATION_TYPE:
|
2004-12-10 21:46:42 -05:00
|
|
|
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:
|
2004-12-10 21:46:42 -05:00
|
|
|
fixup_vector((F_VECTOR*)relocating);
|
2004-07-16 02:26:21 -04:00
|
|
|
break;
|
2004-08-29 23:30:54 -04:00
|
|
|
case STRING_TYPE:
|
2004-12-10 21:46:42 -05:00
|
|
|
rehash_string((F_STRING*)relocating);
|
2004-08-29 23:30:54 -04:00
|
|
|
break;
|
2004-07-16 02:26:21 -04:00
|
|
|
case SBUF_TYPE:
|
2004-12-10 21:46:42 -05:00
|
|
|
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-08-03 23:56:28 -04:00
|
|
|
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
|
|
|
void relocate_data()
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2006-05-18 01:08:09 -04:00
|
|
|
CELL relocating;
|
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
|
|
|
|
2006-05-18 01:08:09 -04:00
|
|
|
for(relocating = tenured.base;
|
|
|
|
|
relocating < tenured.here;
|
|
|
|
|
relocating += untagged_object_size(relocating))
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2005-05-13 18:27:18 -04:00
|
|
|
allot_barrier(relocating);
|
2006-05-18 01:08:09 -04:00
|
|
|
relocate_object(relocating);
|
2004-12-25 02:55:03 -05:00
|
|
|
}
|
|
|
|
|
|
2006-05-18 01:08:09 -04:00
|
|
|
for(relocating = compiling.base;
|
|
|
|
|
relocating < literal_top;
|
|
|
|
|
relocating += CELLS)
|
2004-12-25 02:55:03 -05:00
|
|
|
{
|
2006-05-18 01:08:09 -04:00
|
|
|
data_fixup((CELL*)relocating);
|
2004-12-25 02:55:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-15 15:34:00 -04:00
|
|
|
void undefined_symbol(void)
|
|
|
|
|
{
|
2006-05-15 00:03:55 -04:00
|
|
|
general_error(ERROR_UNDEFINED_SYMBOL,F,F,true);
|
2005-08-15 15:34:00 -04:00
|
|
|
}
|
|
|
|
|
|
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);
|
2006-05-18 01:08:09 -04:00
|
|
|
F_ARRAY *pair = untag_array(get(compiling.base + arg * CELLS));
|
2006-05-15 00:03:55 -04:00
|
|
|
F_STRING *symbol = untag_string(AREF(pair,0));
|
|
|
|
|
DLL* dll = (AREF(pair,1) == F ? NULL : untag_dll(AREF(pair,1)));
|
2005-08-15 15:34:00 -04:00
|
|
|
CELL sym;
|
|
|
|
|
|
2005-08-15 15:45:46 -04:00
|
|
|
if(dll != NULL && !dll->dll)
|
2005-08-15 15:34:00 -04:00
|
|
|
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
|
|
|
{
|
2005-05-13 18:27:18 -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:
|
2005-05-14 00:23:00 -04:00
|
|
|
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;
|
|
|
|
|
|
2005-05-14 00:23:00 -04:00
|
|
|
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;
|
2006-05-18 01:08:09 -04:00
|
|
|
while(relocating < compiling.here)
|
2004-12-25 02:55:03 -05:00
|
|
|
relocating = relocate_code_next(relocating);
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|