/*
....[@@@..[@@@..............[@.................. 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
------------------------------------------------------------------------------
asmobjfile.cc
*/
#include <string.h>
#include "config.h"
#include "io.h"
#include "asmobjfile.h"
#include "llist.h"
#define MEM_DELTA 100
int AsmObjFile::readFrom( StaticInput & in )
{
asmobjheader head;
constants_def.clr();
// HEADER
in.read( &head, sizeof(asmobjheader) );
if ( strncmp(head.magic, ASMOBJ_MAGIC, 4 ) )
{
in.error( "Bad magic number.\n\r");
return 1;
}
allocMemBlock(head.code_length);
constants.allocMemBlock(head.consts_length);
// EXEC CODE
in.read( getMem(), head.code_length * sizeof(memorycell) );
setOffset( head.code_length );
// CONST TABLE
constants_def.readFrom(in);
// RELOCATION TABLE
relocation_table.readFrom(in);
// CONSTS
in.read(constants.getMem(), head.consts_length);
constants.setOffset( head.consts_length );
return 0;
}
char emptybuf[] = "\0\0\0\0\0\0";
int AsmObjFile::writeTo( Output & out ) const
{
asmobjheader head;
// HEADER
strncpy( head.magic, ASMOBJ_MAGIC, 4);
head.code_length = getUsedSize();
head.consts_length = constants.getUsedSize();
out.write( &head, sizeof(asmobjheader) );
// CODE PART
out.write(getConstMem(), getUsedBytesize());
// CONST DEF TABLE
constants_def.writeTo( out );
// RELOCATION TABLE
relocation_table.writeTo( out );
// CONSTS
out.write(constants.getConstMem(), constants.getUsedBytesize() );
return 0;
}
int AsmObjFile::addConstant( vmtype type, const void * src_ptr, int size )
{
asmobjconst oconst;
int i;
if (
(type == VMT_IMPORT_INTERFACE) ||
(type == VMT_IMPORT_FUN ) ||
(type == VMT_IMPORT_STATIC) ||
(type == VMT_CLASS_TYPE)
)
{
if ( (i = importLookup( type, (const char*)src_ptr) ) > 0)
{
// Cout << "Reduced import constant for " << (const char*)src_ptr <<endl;
return i;
}
}
oconst.type = type;
oconst.offset = constants.getOffset();
constants.putStruct( src_ptr, size );
constants_def.add( oconst );
return (constants_def.length() - 1);
}
int AsmObjFile::importLookup( vmtype type, const char * name )
{
int i,size;
size = constants_def.length();
for ( i=0; i < size; i++ )
{
if ( constants_def[i].type == type )
if ( !strcmp( name, constants.getMem() + constants_def[i].offset ) )
return i;
}
return -1;
}
/*
* we have unsigned 16-bit constants numbers in object files
* it is one 16-bit numberspace for all types of constants
* after loading to mud it grows to 16-bit space for every main type of
* reference - normal, mudasm fun, interface fun, static
*/
bool AsmObjFile::canLink( AsmObjFile & linkee )
{
if ( (constants_def.length() + linkee.constants_def.length()) > 64000 )
return false;
return true;
}
void AsmObjFile::link( AsmObjFile & linkee )
{
int i,size,tmp;
int code_offset;
int consts_count;
asmobjconst oconst;
vmfilefun vmff;
int * reloc_now = new int[linkee.constants_def.length()];
char * cptr;
code_offset = getOffset();
consts_count = constants_def.length();
// copy code block
canCarryMore( linkee.getUsedSize() );
memcpy( getPtr(), linkee.getMem(), linkee.getUsedBytesize() );
movePtr( linkee.getUsedSize() );
// copy and update both constants definitions and constants themselves
size = linkee.constants_def.length();
for ( i=0; i < size; i++ )
{
oconst = linkee.constants_def[i];
switch ( oconst.type )
{
case VMT_CONST_STRING:
case VMT_IMPORT_FUN:
case VMT_IMPORT_INTERFACE:
case VMT_IMPORT_STATIC:
case VMT_CLASS_TYPE:
case VMT_IMPORT_FUN_OR_INTERFACE:
cptr = linkee.constants.getMem() + oconst.offset;
reloc_now[i] = addConstant( oconst.type,
cptr, strlen(cptr) + 1);
break;
case VMT_FIELD_DATA:
cptr = linkee.constants.getMem() + oconst.offset;
tmp = strlen( cptr );
tmp += strlen( &cptr[tmp+1] );
reloc_now[i] = addConstant( oconst.type,
cptr, tmp + 2);
break;
case VMT_EXPORT_FUN:
vmff = *((vmfilefun*)linkee.constants.getStruct(oconst.offset));
vmff.start += code_offset;
vmff.end += code_offset;
vmff.name = reloc_now[vmff.name];
reloc_now[i] = addConstant( oconst.type,
&vmff, sizeof(vmfilefun));
break;
default:
Cout << "Unknown type of asmobjfile constant" <<endl;
break;
}
}
// copy and update relocation table
// also update references in code
size = linkee.relocation_table.length();
for ( i=0; i < size; i++ )
{
tmp = linkee.relocation_table[i] + code_offset;
mem[tmp].s.u.number = reloc_now[mem[tmp].s.u.number];
relocation_table.add(tmp);
}
delete [] reloc_now;
}