linker: CMake-ify
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "linker.hpp"
|
||||
#include "image_util.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BBModule : public Module{
|
||||
public:
|
||||
BBModule();
|
||||
BBModule( istream &in );
|
||||
~BBModule();
|
||||
|
||||
void *link( Module *libs );
|
||||
bool createExe( const char *exe_file,const char *dll_file );
|
||||
|
||||
int getPC();
|
||||
|
||||
void emit( int byte );
|
||||
void emitw( int word );
|
||||
void emitd( int dword );
|
||||
void emitx( void *mem,int sz );
|
||||
bool addSymbol( const char *sym,int pc );
|
||||
bool addReloc( const char *dest_sym,int pc,bool pcrel );
|
||||
|
||||
bool findSymbol( const char *sym,int *pc );
|
||||
|
||||
private:
|
||||
char *data;
|
||||
int data_sz,pc;
|
||||
bool linked;
|
||||
|
||||
map<string,int> symbols;
|
||||
map<int,string> rel_relocs,abs_relocs;
|
||||
|
||||
bool findSym( const string &t,Module *libs,int *n ){
|
||||
if( findSymbol( t.c_str(),n ) ) return true;
|
||||
if( libs->findSymbol( t.c_str(),n ) ) return true;
|
||||
string err="Symbol '"+t+"' not found";
|
||||
MessageBox( GetDesktopWindow(),err.c_str(),"Blitz Linker Error",MB_TOPMOST|MB_SETFOREGROUND );
|
||||
return false;
|
||||
}
|
||||
|
||||
void ensure( int n ){
|
||||
if( pc+n<=data_sz ) return;
|
||||
data_sz=data_sz/2+data_sz;
|
||||
if( data_sz<pc+n ) data_sz=pc+n;
|
||||
char *old_data=data;
|
||||
data=new char[data_sz];
|
||||
memcpy( data,old_data,pc );
|
||||
delete old_data;
|
||||
}
|
||||
};
|
||||
|
||||
BBModule::BBModule():data(0),data_sz(0),pc(0),linked(false){
|
||||
}
|
||||
|
||||
BBModule::~BBModule(){
|
||||
if( linked ) VirtualFree( data,0,MEM_RELEASE );
|
||||
else delete[] data;
|
||||
}
|
||||
|
||||
void *BBModule::link( Module *libs ){
|
||||
|
||||
if( linked ) return data;
|
||||
|
||||
int dest;
|
||||
map<int,string>::iterator it;
|
||||
|
||||
char *p=(char*)VirtualAlloc( 0,pc,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE );
|
||||
memcpy( p,data,pc );
|
||||
delete[] data;
|
||||
data=p;
|
||||
|
||||
linked=true;
|
||||
|
||||
for( it=rel_relocs.begin();it!=rel_relocs.end();++it ){
|
||||
if( !findSym( it->second,libs,&dest ) ) return 0;
|
||||
int *p=(int*)(data+it->first);*p+=(dest-(int)p);
|
||||
}
|
||||
|
||||
for( it=abs_relocs.begin();it!=abs_relocs.end();++it ){
|
||||
if( !findSym( it->second,libs,&dest ) ) return 0;
|
||||
int *p=(int*)(data+it->first);*p+=dest;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int BBModule::getPC(){
|
||||
return pc;
|
||||
}
|
||||
|
||||
void BBModule::emit( int byte ){
|
||||
ensure(1);data[pc++]=byte;
|
||||
}
|
||||
|
||||
void BBModule::emitw( int word ){
|
||||
ensure(2);*(short*)(data+pc)=word;pc+=2;
|
||||
}
|
||||
|
||||
void BBModule::emitd( int dword ){
|
||||
ensure(4);*(int*)(data+pc)=dword;pc+=4;
|
||||
}
|
||||
|
||||
void BBModule::emitx( void *mem,int sz ){
|
||||
ensure(sz);memcpy( data+pc,mem,sz );pc+=sz;
|
||||
}
|
||||
|
||||
bool BBModule::addSymbol( const char *sym,int pc ){
|
||||
string t(sym);
|
||||
if( symbols.find( t )!=symbols.end() ) return false;
|
||||
symbols[t]=pc;return true;
|
||||
}
|
||||
|
||||
bool BBModule::addReloc( const char *dest_sym,int pc,bool pcrel ){
|
||||
map<int,string> &rel=pcrel ? rel_relocs : abs_relocs;
|
||||
if( rel.find( pc )!=rel.end() ) return false;
|
||||
rel[pc]=string(dest_sym);return true;
|
||||
}
|
||||
|
||||
bool BBModule::findSymbol( const char *sym,int *pc ){
|
||||
string t=string(sym);
|
||||
map<string,int>::iterator it=symbols.find( t );
|
||||
if( it==symbols.end() ) return false;
|
||||
*pc=it->second + (int)data;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Linker::version(){
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
bool Linker::canCreateExe(){
|
||||
#ifdef DEMO
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
Module *Linker::createModule(){
|
||||
return new BBModule();
|
||||
}
|
||||
|
||||
void Linker::deleteModule( Module *mod ){
|
||||
delete mod;
|
||||
}
|
||||
|
||||
Linker *_cdecl linkerGetLinker(){
|
||||
static Linker linker;return &linker;
|
||||
}
|
||||
|
||||
bool BBModule::createExe( const char *exe_file,const char *dll_file ){
|
||||
|
||||
#ifdef DEMO
|
||||
return false;
|
||||
#else
|
||||
|
||||
//find proc address of bbWinMain
|
||||
HMODULE hmod=LoadLibrary( dll_file );if( !hmod ) return false;
|
||||
int proc=(int)GetProcAddress( hmod,"_bbWinMain@0" );
|
||||
int entry=proc-(int)hmod;FreeLibrary( hmod );if( !proc ) return false;
|
||||
|
||||
if( !CopyFile( dll_file,exe_file,false ) ) return false;
|
||||
|
||||
if( !openImage( exe_file ) ) return false;
|
||||
|
||||
makeExe( entry );
|
||||
|
||||
//create module
|
||||
//code size: code...
|
||||
//num_syms: name,val...
|
||||
//num_rels: name,val...
|
||||
//num_abss: name,val...
|
||||
//
|
||||
qstreambuf buf;
|
||||
iostream out( &buf );
|
||||
|
||||
map<string,int>::iterator it;
|
||||
map<int,string>::iterator rit;
|
||||
|
||||
//write the code
|
||||
int sz=pc;out.write( (char*)&sz,4 );out.write( data,pc );
|
||||
|
||||
//write symbols
|
||||
sz=symbols.size();out.write( (char*)&sz,4 );
|
||||
for( it=symbols.begin();it!=symbols.end();++it ){
|
||||
string t=it->first+'\0';
|
||||
out.write( t.data(),t.size() );
|
||||
sz=it->second;out.write( (char*)&sz,4 );
|
||||
}
|
||||
|
||||
//write relative relocs
|
||||
sz=rel_relocs.size();out.write( (char*)&sz,4 );
|
||||
for( rit=rel_relocs.begin();rit!=rel_relocs.end();++rit ){
|
||||
string t=rit->second+'\0';
|
||||
out.write( t.data(),t.size() );
|
||||
sz=rit->first;out.write( (char*)&sz,4 );
|
||||
}
|
||||
|
||||
//write absolute relocs
|
||||
sz=abs_relocs.size();out.write( (char*)&sz,4 );
|
||||
for( rit=abs_relocs.begin();rit!=abs_relocs.end();++rit ){
|
||||
string t=rit->second+'\0';
|
||||
out.write( t.data(),t.size() );
|
||||
sz=rit->first;out.write( (char*)&sz,4 );
|
||||
}
|
||||
|
||||
replaceRsrc( 10,1111,1033,buf.data(),buf.size() );
|
||||
|
||||
closeImage();
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user