/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@hom.net MUD++ development mailing list mudpp@van.ml.org ------------------------------------------------------------------------------ asmloader.cpp */ #include "config.h" #include "array.h" #include "memoryblock.h" #include "asmloader.h" #include "vmachine.h" #include "vmopcodes.h" Array <vmstack> vmconstant_table(200,100); Array <vmfun> vmfun_table(50,20); Array <vmstack> vmstatvar_table( 50, 20 ); Array <String> vmstatvar_nametable( 50, 20 ); bool vmachine_enabled = false; bool allow_redefinition_of_funs = false; int lookup_vmfun_number( const char * name ) { u16 i, size; size = vmfun_table.length(); for ( i=1; i < size; i++ ) { if ( vmfun_table[i].name == name ) return i; } return -1; } int deflookup_vmfun_number( const char * name ) { u16 i, size; size = vmfun_table.length(); for ( i=1; i < size; i++ ) { if ( vmfun_table[i].name == name ) return i; } vmfun vmf; vmf.low_border = NULL; vmf.high_border = NULL; vmf.name = name; vmfun_table.add(vmf); return i; } void add_vmfun( const char * name, memorycell * low_border, memorycell * high_border ) { u16 i, size; size = vmfun_table.length(); for ( i=1; i < size; i++ ) { if ( vmfun_table[i].name == name ) { if ( vmfun_table[i].low_border != NULL ) { if ( !allow_redefinition_of_funs ) { Cout << "AsmLinker - redefinition of function " << name <<endl; mudpp_exit(1); } delete [] vmfun_table[i].low_border; } // Cout << "Resolved function " << name << " at " << (int) vmfun_table[i].low_border <<endl; vmfun_table[i].low_border = low_border; vmfun_table[i].high_border = high_border; return; } } vmfun vmf; vmf.low_border = low_border; vmf.high_border = high_border; vmf.name = name; vmfun_table.add(vmf); // Cout << "Added function " << name << " at " << (int) vmfun_table[i].low_border <<endl; return; } u16 lookup_static_number( const char * name ) { u16 i,size; vmstack vmsv; size = vmstatvar_nametable.length(); for ( i=0; i < size; i++ ) { if ( vmstatvar_nametable[i] == name ) return i; } vmsv.type = VMT_NULL; vmsv.val.i = 0; vmstatvar_table.add(vmsv); vmstatvar_nametable.add(String (name)); return i; } bool link_vmachine() { AsmObjFile * image; InputFile * inf; int i; char name[128]; vmfun vmf; vmf.name = "FAKE_FUN"; vmf.low_border = 0; vmf.high_border = 0; vmf.error = vmf.name; vmfun_table.add(vmf); for ( i=0; ; i++ ) { sprintf( name, "../mudC/image/image.%d.mo", i); inf = new InputFile(name); if ( !(*inf) ) { delete inf; break; } image = new AsmObjFile(); image->readFrom( *inf ); delete inf; if ( !add_asmobject( *image ) ) { delete image; return false; } delete image; } return true; } enum funFound { NOT_NEEDED = 0, MUDASM, INTERFACE }; bool add_asmobject( AsmObjFile & aof ) { int i,size; int j, mapsize; int itmp,cnumber; char * buf; asmobjconst oconst; vmstack vmconst; vmfilefun vmff; memorycell * memptr; vmfunmap vfm; Array< vmfunmap > funmap( 10, 10); // it has size of const_count not reloc_count, as we map in-file // constants to in memory ones + funs + interfaces size = aof.constants_def.length(); int * reloc_table = new int[size]; funFound * reloc_funfound_table = new funFound[size]; for ( i=0; i < size; i++) reloc_funfound_table[i] = NOT_NEEDED; /* for (i =0; i < size; i++) { Cout << "Constant offset " << aof.constants_def[i].offset<< " starting with " << (int) aof.constants[constants_def[i].offset]; << endl; } */ for ( i=0; i < size; i++ ) { oconst = aof.constants_def[i]; switch ( oconst.type ) { case VMT_CONST_STRING: vmconst.type = VMT_STRING; vmconst.val.s = new String(&(aof.constants[oconst.offset])); vmconstant_table.add(vmconst); reloc_table[i] = vmconstant_table.length()-1; // Cout << "Added string " << *vmconst.val.s <<" at vmc_table " << reloc_table[i] <<endl; break; case VMT_IMPORT_FUN: reloc_table[i] = deflookup_vmfun_number( &aof.constants[oconst.offset] ); // Cout << "Added import fun at vmf_table " <<reloc_table[i] <<endl; break; case VMT_EXPORT_FUN: vmff = *((vmfilefun*)aof.constants.getStruct(oconst.offset)); // if we don't get name constant first - crash :( memptr = new memorycell[vmff.end - vmff.start]; memcpy( memptr, &aof[vmff.start], (vmff.end - vmff.start) * sizeof(memorycell) ); // Cout << "Index name of fun " << vmff.name << " and relocated " << reloc_table[vmff.name] <<endl; add_vmfun( vmconstant_table[reloc_table[vmff.name]].val.s->chars(), memptr, memptr + (vmff.end - vmff.start)); vfm.low_offset = vmff.start; vfm.high_offset = vmff.end; vfm.fun_ptr = memptr; funmap.add(vfm); reloc_table[i] = -1; // Cout << "Added fun." <<endl; break; case VMT_IMPORT_INTERFACE: if ( (reloc_table[i] = lookup_interface_number( &aof.constants[oconst.offset] )) == 0 ) { Cout << "AsmLoader:: Unknown interface call "<< endl; mudpp_exit(1); } // Cout << "Added interface fun " << " at vmi_table " << reloc_table[i] <<endl; break; case VMT_IMPORT_STATIC: reloc_table[i] = lookup_static_number( &aof.constants[oconst.offset] ); break; case VMT_FIELD_DATA: buf = &aof.constants[oconst.offset]; itmp = vmtype_lookup( buf ); if ( itmp < 0 ) { Cout << "AsmLoader::field data unknown class"; mudpp_exit(1); } j = fieldname_lookup( (vmtype) itmp, buf + strlen(buf) +1); /* Cout << "Fieldname lookup of " << buf+strlen(buf) +1 << " at constant nr " << i << " resulted in " << j << endl;*/ if ( j < 0 ) { Cout << "AsmLoader::field data unknown field"; mudpp_exit(1); } reloc_table[i] = j; break; case VMT_CLASS_TYPE: buf = &aof.constants[oconst.offset]; itmp = vmtype_lookup( buf ); if ( itmp < 0 ) { Cout << "AsmLoader::class type - unknown class"; mudpp_exit(1); } reloc_table[i] = itmp; break; case VMT_IMPORT_FUN_OR_INTERFACE: if ( (reloc_table[i] = lookup_interface_number( &aof.constants[oconst.offset] )) == 0 ) { reloc_table[i] = deflookup_vmfun_number( &aof.constants[oconst.offset] ); reloc_funfound_table[i] = MUDASM; } else { reloc_funfound_table[i] = INTERFACE; } break; default: reloc_table[i] = -1; Cout << "AsmLoader::Unknown type of constant"<<endl; mudpp_exit(1); break; } } size = aof.relocation_table.length(); mapsize = funmap.length(); for (i = 0; i < size; i++ ) { memptr =NULL; itmp = aof.relocation_table[i]; for ( j=0; j < mapsize; j++ ) { if ( (funmap[j].low_offset <= itmp) && (funmap[j].high_offset >= itmp ) ) { memptr = funmap[j].fun_ptr + (itmp - funmap[j].low_offset); break; } } if ( memptr == NULL ) { Cout << "Relocation for cell not belonging to any function" <<endl; mudpp_exit(1); } cnumber = memptr->s.u.number; memptr->s.u.number = reloc_table[cnumber]; if ( reloc_funfound_table[cnumber] != NOT_NEEDED ) { switch( reloc_funfound_table[cnumber] ) { case MUDASM: memptr->s.opcode = VMOPC_FCALL; break; case INTERFACE: memptr->s.opcode = VMOPC_ICALL; break; default: abort(); } } // Cout << "Relocating call " << cnumber<< " to use " << reloc_table[cnumber] <<endl; } delete [] reloc_table; createVMs(); vmachine_enabled = true; return true; }