| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include "std.h"
- #include "linker.h"
- #include "image_util.h"
- 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=d_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 d_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
- }
|