factor/native/relocate.c

197 lines
4.2 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;
case PORT_TYPE:
fixup_port((F_PORT*)relocating);
2004-08-24 23:46:55 -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;
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
INLINE CELL init_object(CELL relocating, CELL* handle, CELL type)
2004-08-29 01:04:42 -04:00
{
if(untag_header(get(relocating)) != type)
fatal_error("init_object() failed",get(relocating));
*handle = tag_object((CELL*)relocating);
2004-12-25 02:55:03 -05:00
return relocate_data_next(relocating);
2004-08-29 01:04:42 -04:00
}
2004-12-25 02:55:03 -05:00
void relocate_data()
2004-07-16 02:26:21 -04:00
{
2004-12-25 02:55:03 -05:00
CELL relocating = active.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]);
2004-07-16 02:26:21 -04:00
2004-09-08 02:31:03 -04:00
/* The first object in the image must always T */
2004-12-25 02:55:03 -05:00
relocating = init_object(relocating,&T,T_TYPE);
2004-07-16 02:26:21 -04:00
2004-08-29 01:04:42 -04:00
/* The next three must be bignum 0, 1, -1 */
2004-12-25 02:55:03 -05:00
relocating = init_object(relocating,&bignum_zero,BIGNUM_TYPE);
relocating = init_object(relocating,&bignum_pos_one,BIGNUM_TYPE);
relocating = init_object(relocating,&bignum_neg_one,BIGNUM_TYPE);
2004-07-16 02:26:21 -04:00
for(;;)
{
if(relocating >= active.here)
2004-07-16 02:26:21 -04:00
break;
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 relocate_primitive(F_REL* rel, bool relative)
{
/* this is intended for x86, so the address is relative to after
the insn, ie offset + CELLS. */
put(rel->offset,primitive_to_xt(rel->argument)
- (relative ? rel->offset + CELLS : 0));
}
void relocate_dlsym(F_REL* rel, bool relative)
{
2004-12-25 18:08:20 -05:00
F_CONS* cons = untag_cons(get(rel->argument));
F_STRING* symbol = untag_string(cons->car);
DLL* dll = (cons->cdr == F ? NULL : untag_dll(cons->cdr));
put(rel->offset,(CELL)ffi_dlsym(dll,symbol)
2004-12-25 02:55:03 -05:00
- (relative ? rel->offset + CELLS : 0));
}
2005-03-22 21:20:58 -05:00
void relocate_primitive_16_16(F_REL* rel)
{
reloc_set_16_16((CELL*)rel->offset,primitive_to_xt(rel->argument));
}
INLINE void code_fixup_16_16(CELL* cell)
{
CELL difference = (compiling.base - code_relocation_base);
reloc_set_16_16(cell,reloc_get_16_16(cell) + difference);
}
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)
fatal_error("Wrong compiled header",relocating);
while(rel < rel_end)
{
/* to_c_string can fill up the heap */
maybe_garbage_collection();
code_fixup(&rel->offset);
switch(rel->type)
{
case F_RELATIVE_PRIMITIVE:
relocate_primitive(rel,true);
break;
case F_ABSOLUTE_PRIMITIVE:
relocate_primitive(rel,false);
break;
2004-12-25 18:08:20 -05:00
case F_RELATIVE_DLSYM:
2004-12-25 02:55:03 -05:00
code_fixup(&rel->argument);
relocate_dlsym(rel,true);
break;
2004-12-25 18:08:20 -05:00
case F_ABSOLUTE_DLSYM:
2004-12-25 02:55:03 -05:00
code_fixup(&rel->argument);
relocate_dlsym(rel,false);
break;
case F_ABSOLUTE:
code_fixup((CELL*)rel->offset);
break;
2005-03-22 21:20:58 -05:00
case F_ABSOLUTE_PRIMITIVE_16_16:
relocate_primitive_16_16(rel);
break;
case F_ABSOLUTE_16_16:
code_fixup_16_16((CELL*)rel->offset);
break;
2004-12-25 02:55:03 -05:00
default:
fatal_error("Unsupported rel",rel->type);
break;
}
rel++;
}
return (CELL)rel_end;
}
void relocate_code()
{
/* start relocating from the end of the space reserved for literals */
CELL relocating = literal_max;
for(;;)
{
/* fprintf(stderr,"relocation %d %d\n",relocating,compiling.here); */
if(relocating >= compiling.here)
break;
relocating = relocate_code_next(relocating);
2004-07-16 02:26:21 -04:00
}
}