linker.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include "std.h"
  2. #include "linker.h"
  3. #include "image_util.h"
  4. class BBModule : public Module{
  5. public:
  6. BBModule();
  7. BBModule( istream &in );
  8. ~BBModule();
  9. void *link( Module *libs );
  10. bool createExe( const char *exe_file,const char *dll_file );
  11. int getPC();
  12. void emit( int byte );
  13. void emitw( int word );
  14. void emitd( int dword );
  15. void emitx( void *mem,int sz );
  16. bool addSymbol( const char *sym,int pc );
  17. bool addReloc( const char *dest_sym,int pc,bool pcrel );
  18. bool findSymbol( const char *sym,int *pc );
  19. private:
  20. char *data;
  21. int data_sz,pc;
  22. bool linked;
  23. map<string,int> symbols;
  24. map<int,string> rel_relocs,abs_relocs;
  25. bool findSym( const string &t,Module *libs,int *n ){
  26. if( findSymbol( t.c_str(),n ) ) return true;
  27. if( libs->findSymbol( t.c_str(),n ) ) return true;
  28. string err="Symbol '"+t+"' not found";
  29. MessageBox( GetDesktopWindow(),err.c_str(),"Blitz Linker Error",MB_TOPMOST|MB_SETFOREGROUND );
  30. return false;
  31. }
  32. void ensure( int n ){
  33. if( pc+n<=data_sz ) return;
  34. data_sz=data_sz/2+data_sz;
  35. if( data_sz<pc+n ) data_sz=pc+n;
  36. char *old_data=data;
  37. data=d_new char[data_sz];
  38. memcpy( data,old_data,pc );
  39. delete old_data;
  40. }
  41. };
  42. BBModule::BBModule():data(0),data_sz(0),pc(0),linked(false){
  43. }
  44. BBModule::~BBModule(){
  45. if( linked ) VirtualFree( data,0,MEM_RELEASE );
  46. else delete[] data;
  47. }
  48. void *BBModule::link( Module *libs ){
  49. if( linked ) return data;
  50. int dest;
  51. map<int,string>::iterator it;
  52. char *p=(char*)VirtualAlloc( 0,pc,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE );
  53. memcpy( p,data,pc );
  54. delete[] data;
  55. data=p;
  56. linked=true;
  57. for( it=rel_relocs.begin();it!=rel_relocs.end();++it ){
  58. if( !findSym( it->second,libs,&dest ) ) return 0;
  59. int *p=(int*)(data+it->first);*p+=(dest-(int)p);
  60. }
  61. for( it=abs_relocs.begin();it!=abs_relocs.end();++it ){
  62. if( !findSym( it->second,libs,&dest ) ) return 0;
  63. int *p=(int*)(data+it->first);*p+=dest;
  64. }
  65. return data;
  66. }
  67. int BBModule::getPC(){
  68. return pc;
  69. }
  70. void BBModule::emit( int byte ){
  71. ensure(1);data[pc++]=byte;
  72. }
  73. void BBModule::emitw( int word ){
  74. ensure(2);*(short*)(data+pc)=word;pc+=2;
  75. }
  76. void BBModule::emitd( int dword ){
  77. ensure(4);*(int*)(data+pc)=dword;pc+=4;
  78. }
  79. void BBModule::emitx( void *mem,int sz ){
  80. ensure(sz);memcpy( data+pc,mem,sz );pc+=sz;
  81. }
  82. bool BBModule::addSymbol( const char *sym,int pc ){
  83. string t(sym);
  84. if( symbols.find( t )!=symbols.end() ) return false;
  85. symbols[t]=pc;return true;
  86. }
  87. bool BBModule::addReloc( const char *dest_sym,int pc,bool pcrel ){
  88. map<int,string> &rel=pcrel ? rel_relocs : abs_relocs;
  89. if( rel.find( pc )!=rel.end() ) return false;
  90. rel[pc]=string(dest_sym);return true;
  91. }
  92. bool BBModule::findSymbol( const char *sym,int *pc ){
  93. string t=string(sym);
  94. map<string,int>::iterator it=symbols.find( t );
  95. if( it==symbols.end() ) return false;
  96. *pc=it->second + (int)data;
  97. return true;
  98. }
  99. int Linker::version(){
  100. return VERSION;
  101. }
  102. bool Linker::canCreateExe(){
  103. #ifdef DEMO
  104. return false;
  105. #else
  106. return true;
  107. #endif
  108. }
  109. Module *Linker::createModule(){
  110. return d_new BBModule();
  111. }
  112. void Linker::deleteModule( Module *mod ){
  113. delete mod;
  114. }
  115. Linker *_cdecl linkerGetLinker(){
  116. static Linker linker;return &linker;
  117. }
  118. bool BBModule::createExe( const char *exe_file,const char *dll_file ){
  119. #ifdef DEMO
  120. return false;
  121. #else
  122. //find proc address of bbWinMain
  123. HMODULE hmod=LoadLibrary( dll_file );if( !hmod ) return false;
  124. int proc=(int)GetProcAddress( hmod,"_bbWinMain@0" );
  125. int entry=proc-(int)hmod;FreeLibrary( hmod );if( !proc ) return false;
  126. if( !CopyFile( dll_file,exe_file,false ) ) return false;
  127. if( !openImage( exe_file ) ) return false;
  128. makeExe( entry );
  129. //create module
  130. //code size: code...
  131. //num_syms: name,val...
  132. //num_rels: name,val...
  133. //num_abss: name,val...
  134. //
  135. qstreambuf buf;
  136. iostream out( &buf );
  137. map<string,int>::iterator it;
  138. map<int,string>::iterator rit;
  139. //write the code
  140. int sz=pc;out.write( (char*)&sz,4 );out.write( data,pc );
  141. //write symbols
  142. sz=symbols.size();out.write( (char*)&sz,4 );
  143. for( it=symbols.begin();it!=symbols.end();++it ){
  144. string t=it->first+'\0';
  145. out.write( t.data(),t.size() );
  146. sz=it->second;out.write( (char*)&sz,4 );
  147. }
  148. //write relative relocs
  149. sz=rel_relocs.size();out.write( (char*)&sz,4 );
  150. for( rit=rel_relocs.begin();rit!=rel_relocs.end();++rit ){
  151. string t=rit->second+'\0';
  152. out.write( t.data(),t.size() );
  153. sz=rit->first;out.write( (char*)&sz,4 );
  154. }
  155. //write absolute relocs
  156. sz=abs_relocs.size();out.write( (char*)&sz,4 );
  157. for( rit=abs_relocs.begin();rit!=abs_relocs.end();++rit ){
  158. string t=rit->second+'\0';
  159. out.write( t.data(),t.size() );
  160. sz=rit->first;out.write( (char*)&sz,4 );
  161. }
  162. replaceRsrc( 10,1111,1033,buf.data(),buf.size() );
  163. closeImage();
  164. return true;
  165. #endif
  166. }