linker: CMake-ify
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
project(linker_lib)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
"dlltoexe.cpp"
|
||||
"dlltoexe.hpp"
|
||||
"image_util.cpp"
|
||||
"image_util.hpp"
|
||||
"linker.cpp"
|
||||
"linker.hpp"
|
||||
"std.cpp"
|
||||
"std.hpp"
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
stdutil
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
# windows.h
|
||||
WIN32_LEAN_AND_MEAN
|
||||
NOGPICAPMASKS
|
||||
NOVIRTUALKEYCODES
|
||||
NOWINMESSAGES
|
||||
NOWINSTYLES
|
||||
NOSYSMETRICS
|
||||
NOMENUS
|
||||
NOICONS
|
||||
NOKEYSTATES
|
||||
NOSYSCOMMANDS
|
||||
NORASTEROPS
|
||||
NOSHOWWINDOW
|
||||
NOATOM
|
||||
NOCLIPBOARD
|
||||
NOCOLOR
|
||||
NOCTLMGR
|
||||
NODRAWTEXT
|
||||
NOGDI
|
||||
NOKERNEL
|
||||
#NOUSER
|
||||
NONLS
|
||||
#NOMB
|
||||
NOMEMMGR
|
||||
NOMETAFILE
|
||||
NOMINMAX
|
||||
NOMSG
|
||||
NOOPENFILE
|
||||
NOSCROLL
|
||||
NOSERVICE
|
||||
NOSOUND
|
||||
NOTEXTMETRIC
|
||||
NOWH
|
||||
NOWINOFFSETS
|
||||
NOCOMM
|
||||
NOKANJI
|
||||
NOHELP
|
||||
NOPROFILER
|
||||
NODEFERWINDOWPOS
|
||||
NOMCX
|
||||
NOIME
|
||||
NOMDI
|
||||
NOINOUT
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "dlltoexe.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#pragma pack( push,1 )
|
||||
struct Head{
|
||||
short machine,num_sects;
|
||||
int timedata,sym_table,num_syms;
|
||||
short opt_size,chars;
|
||||
};
|
||||
|
||||
struct Opt1{
|
||||
short magic;
|
||||
char major,minor;
|
||||
int code_size,data_size,udata_size;
|
||||
int entry,code_base,data_base;
|
||||
};
|
||||
|
||||
struct Sect{
|
||||
char name[8];
|
||||
int virt_size,virt_addr; //in mem
|
||||
int data_size,data_addr; //on disk
|
||||
int relocs,lines; //file ptrs
|
||||
short num_relocs,num_lines;
|
||||
int chars;
|
||||
};
|
||||
#pragma pack( pop )
|
||||
|
||||
bool dllToExe( const char *exe_file,const char *dll_file,const char *entry_func ){
|
||||
|
||||
//find proc address of bbWinMain
|
||||
HMODULE hmod=LoadLibrary( dll_file );if( !hmod ) return false;
|
||||
int proc=(int)GetProcAddress( hmod,entry_func );
|
||||
int entry=proc-(int)hmod;FreeLibrary( hmod );
|
||||
if( !proc ) return false;
|
||||
|
||||
//Convert dll to exe
|
||||
fstream in( dll_file,ios_base::binary|ios_base::in );if( !in.is_open() ) return false;
|
||||
fstream out( exe_file,ios::binary|ios_base::out|ios_base::trunc );if( !out.is_open() ) return false;
|
||||
|
||||
int offs;
|
||||
in.seekg( 0x3c );
|
||||
in.read( (char*)&offs,4 );
|
||||
|
||||
//copy first bit...
|
||||
in.seekg( 0 );
|
||||
for( int k=0;k<offs+4;++k ) out.put( in.get() );
|
||||
|
||||
//reader file header
|
||||
Head head={0};
|
||||
in.read( (char*)&head,sizeof(head) );
|
||||
//change DLL to EXE
|
||||
head.chars=0x10e;
|
||||
out.write( (char*)&head,sizeof(head) );
|
||||
|
||||
//read opts 1
|
||||
Opt1 opt1={0};
|
||||
in.read( (char*)&opt1,sizeof(opt1) );
|
||||
opt1.entry=entry;
|
||||
out.write( (char*)&opt1,sizeof(opt1) );
|
||||
|
||||
//copy rest of file...
|
||||
while( !in.eof() ){
|
||||
out.put( in.get() );
|
||||
}
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef DLLTOEXE_H
|
||||
#define DLLTOEXE_H
|
||||
|
||||
bool dllToExe( const char *exe_file,const char *dll_file,const char *entry );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,367 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "image_util.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifndef DEMO
|
||||
|
||||
#pragma pack( push,1 )
|
||||
struct Head{
|
||||
short machine,num_sects;
|
||||
int timedata,sym_table,num_syms;
|
||||
short opt_size,chars;
|
||||
};
|
||||
|
||||
struct Opts{
|
||||
short magic;
|
||||
char major,minor;
|
||||
int code_size,data_size,udata_size;
|
||||
int entry,code_base,data_base;
|
||||
|
||||
int image_base,sect_align,file_align;
|
||||
short major_os,minor_os,major_image,minor_image,major_subsys,minor_subsys;
|
||||
|
||||
int reserved;
|
||||
int image_size,headers_size,checksum;
|
||||
|
||||
short subsys,dllchars;
|
||||
|
||||
int stack_reserve,stack_commit,heap_reserve,heap_commit,loadflags;
|
||||
|
||||
int dir_entries;
|
||||
};
|
||||
|
||||
struct DDir{
|
||||
int rva,size;
|
||||
};
|
||||
|
||||
struct Sect{
|
||||
char name[8];
|
||||
int virt_size,virt_addr; //in mem
|
||||
int data_size,data_addr; //on disk
|
||||
int relocs,lines; //file ptrs
|
||||
short num_relocs,num_lines;
|
||||
int chars;
|
||||
};
|
||||
|
||||
struct Rdir{
|
||||
int chars,timedata;
|
||||
short major,minor,num_names,num_ids;
|
||||
};
|
||||
|
||||
struct Rent{
|
||||
int id,data;
|
||||
};
|
||||
|
||||
struct Rdat{
|
||||
int addr,size,cp,zero;
|
||||
};
|
||||
|
||||
#pragma pack( pop )
|
||||
|
||||
struct Rsrc{
|
||||
int id;
|
||||
void *data;
|
||||
int data_sz;
|
||||
vector<Rsrc*> kids;
|
||||
|
||||
Rsrc( int id,Rsrc *p ):id(id),data(0),data_sz(0){
|
||||
if( p ) p->kids.push_back( this );
|
||||
// cout<<"res id:"<<dec<<id<<hex<<endl;
|
||||
}
|
||||
|
||||
~Rsrc(){
|
||||
for( ;kids.size();kids.pop_back() ) delete kids.back();
|
||||
delete data;
|
||||
}
|
||||
};
|
||||
|
||||
struct Section{
|
||||
Sect sect;
|
||||
char *data;
|
||||
|
||||
Section():data(0){}
|
||||
~Section(){ delete[] data; }
|
||||
};
|
||||
|
||||
static char *stub;
|
||||
static int stub_sz;
|
||||
|
||||
static Head *head;
|
||||
static int head_sz;
|
||||
|
||||
static Opts *opts;
|
||||
static int opts_sz;
|
||||
|
||||
static DDir *ddir;
|
||||
static int ddir_sz;
|
||||
|
||||
static vector<Section*> sections;
|
||||
|
||||
static Rsrc *rsrc_root;
|
||||
|
||||
static const char *img_file;
|
||||
|
||||
static void openRsrcDir( Section *s,int off,Rsrc *p ){
|
||||
char *data=(char*)s->data;
|
||||
|
||||
Rdir *dir=(Rdir*)(data+off);
|
||||
Rent *ent=(Rent*)(dir+1);
|
||||
for( int k=0;k<dir->num_ids;++ent,++k ){
|
||||
Rsrc *r=new Rsrc( ent->id,p );
|
||||
if( ent->data<0 ){ //a node - offset is another dir
|
||||
openRsrcDir( s,ent->data&0x7fffffff,r );
|
||||
}else{ //a leaf
|
||||
Rdat *dat=(Rdat*)( data+ent->data );
|
||||
// cout<<"dat addr:"<<dat->addr<<" size:"<<dat->size<<endl;
|
||||
int sz=dat->size;
|
||||
void *src=dat->addr-s->sect.virt_addr+data;
|
||||
void *dest=new char[sz];
|
||||
memcpy( dest,src,sz );
|
||||
r->data=dest;
|
||||
r->data_sz=sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void openRsrcTree( Section *s ){
|
||||
rsrc_root=new Rsrc( 0,0 );
|
||||
openRsrcDir( s,0,rsrc_root );
|
||||
}
|
||||
|
||||
static int rsrcSize( Rsrc *r ){
|
||||
if( r->data ) return (sizeof(Rdat)+r->data_sz+7)&~7;
|
||||
int sz=sizeof( Rdir );
|
||||
for( int k=0;k<r->kids.size();++k ){
|
||||
sz+=sizeof( Rent )+rsrcSize( r->kids[k] );
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void closeRsrcDir( Section *s,int off,Rsrc *p ){
|
||||
|
||||
int t,k;
|
||||
|
||||
char *data=(char*)s->data;
|
||||
|
||||
Rdir *dir=(Rdir*)(data+off);
|
||||
memset( dir,0,sizeof(Rdir) );
|
||||
dir->num_ids=p->kids.size();
|
||||
Rent *ent=(Rent*)(dir+1);
|
||||
|
||||
//to end of dir...
|
||||
off+=sizeof(Rdir)+sizeof(Rent)*p->kids.size();
|
||||
|
||||
t=off;
|
||||
|
||||
//write entries
|
||||
for( k=0;k<p->kids.size();++ent,++k ){
|
||||
Rsrc *r=p->kids[k];
|
||||
ent->id=r->id;
|
||||
ent->data=t;
|
||||
if( !r->data ) ent->data|=0x80000000;
|
||||
t+=rsrcSize( r );
|
||||
}
|
||||
|
||||
t=off;
|
||||
|
||||
//write kids...
|
||||
for( k=0;k<p->kids.size();++k ){
|
||||
Rsrc *r=p->kids[k];
|
||||
if( !r->data ){
|
||||
closeRsrcDir( s,t,r );
|
||||
}else{
|
||||
Rdat *dat=(Rdat*)(data+t);
|
||||
dat->addr=s->sect.virt_addr+t+sizeof(Rdat);
|
||||
dat->size=r->data_sz;
|
||||
dat->zero=dat->cp=0;
|
||||
memcpy( data+t+sizeof(Rdat),r->data,r->data_sz );
|
||||
}
|
||||
t+=rsrcSize( r );
|
||||
}
|
||||
}
|
||||
|
||||
static int fileAlign( int n ){
|
||||
return (n+(opts->file_align-1))&~(opts->file_align-1);
|
||||
}
|
||||
|
||||
static int sectAlign( int n ){
|
||||
return (n+(opts->sect_align-1))&~(opts->sect_align-1);
|
||||
}
|
||||
|
||||
static void closeRsrcTree( Section *s ){
|
||||
|
||||
int virt_sz=rsrcSize( rsrc_root );
|
||||
int data_sz=fileAlign( virt_sz );
|
||||
|
||||
int virt_delta=sectAlign(virt_sz)-sectAlign(s->sect.virt_size);
|
||||
int data_delta=fileAlign(virt_sz)-fileAlign(s->sect.virt_size);
|
||||
|
||||
|
||||
for( int k=0;k<sections.size();++k ){
|
||||
Section *t=sections[k];
|
||||
if( t->sect.virt_addr>s->sect.virt_addr ){
|
||||
t->sect.virt_addr+=virt_delta;
|
||||
if( !strcmp( t->sect.name,".reloc" ) ){
|
||||
ddir[5].rva=t->sect.virt_addr;
|
||||
}
|
||||
}
|
||||
if( t->sect.data_addr>s->sect.data_addr ){
|
||||
t->sect.data_addr+=data_delta;
|
||||
}
|
||||
}
|
||||
|
||||
ddir[2].size=virt_sz;
|
||||
opts->image_size+=virt_delta;
|
||||
|
||||
s->sect.virt_size=virt_sz;
|
||||
s->sect.data_size=data_sz;
|
||||
|
||||
delete[] s->data;
|
||||
s->data=new char[data_sz];
|
||||
closeRsrcDir( s,0,rsrc_root );
|
||||
|
||||
delete rsrc_root;
|
||||
rsrc_root=0;
|
||||
}
|
||||
|
||||
static Rsrc *findRsrc( int id,Rsrc *p ){
|
||||
for( int k=0;k<p->kids.size();++k ){
|
||||
if( p->kids[k]->id==id ) return p->kids[k];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Rsrc *findRsrc( int type,int id,int lang ){
|
||||
Rsrc *r=findRsrc( type,rsrc_root );if( !r ) return 0;
|
||||
r=findRsrc( id,r );if( !r ) return 0;
|
||||
return findRsrc( lang,r );
|
||||
}
|
||||
|
||||
static void loadImage( istream &in ){
|
||||
|
||||
int k;
|
||||
|
||||
//read stub
|
||||
in.seekg( 0x3c );
|
||||
in.read( (char*)&stub_sz,4 );
|
||||
stub_sz+=4;stub=new char[stub_sz];
|
||||
in.seekg( 0 );in.read( stub,stub_sz );
|
||||
|
||||
//read head
|
||||
head=new Head;
|
||||
head_sz=sizeof(Head);
|
||||
in.read( (char*)head,head_sz );
|
||||
|
||||
//read opts
|
||||
opts=new Opts;
|
||||
opts_sz=sizeof(Opts);
|
||||
in.read( (char*)opts,opts_sz );
|
||||
|
||||
//read data dirs
|
||||
ddir_sz=opts->dir_entries * sizeof(DDir);
|
||||
ddir=(DDir*)new char[ddir_sz];
|
||||
in.read( (char*)ddir,ddir_sz );
|
||||
|
||||
//read sects...
|
||||
for( k=0;k<head->num_sects;++k ){
|
||||
Section *s=new Section;
|
||||
in.read( (char*)&s->sect,sizeof(Sect) );
|
||||
sections.push_back( s );
|
||||
}
|
||||
|
||||
for( k=0;k<head->num_sects;++k ){
|
||||
Section *s=sections[k];
|
||||
if( !s->sect.data_addr ) continue;
|
||||
int data_sz=s->sect.data_size;
|
||||
s->data=new char[data_sz];//char[s->sect.virt_size];
|
||||
//memset( s->data,0,s->sect.virt_size );
|
||||
in.seekg( s->sect.data_addr );
|
||||
in.read( s->data,data_sz );
|
||||
}
|
||||
}
|
||||
|
||||
static void saveImage( ostream &out ){
|
||||
|
||||
int k;
|
||||
|
||||
out.write( (char*)stub,stub_sz );
|
||||
out.write( (char*)head,head_sz );
|
||||
out.write( (char*)opts,opts_sz );
|
||||
out.write( (char*)ddir,ddir_sz );
|
||||
|
||||
for( k=0;k<head->num_sects;++k ){
|
||||
Section *s=sections[k];
|
||||
out.write( (char*)&s->sect,sizeof(Sect) );
|
||||
}
|
||||
|
||||
for( k=0;k<head->num_sects;++k ){
|
||||
Section *s=sections[k];
|
||||
if( !s->sect.data_addr ) continue;
|
||||
//assumes sect data is in order!!!!!
|
||||
while( out.tellp()<s->sect.data_addr ) out.put( (char)0xbb );
|
||||
out.seekp( s->sect.data_addr );
|
||||
out.write( s->data,s->sect.data_size );
|
||||
}
|
||||
}
|
||||
|
||||
/********************** PUBLIC STUFF ***********************/
|
||||
|
||||
bool openImage( const char *img ){
|
||||
img_file=img;
|
||||
|
||||
fstream in( img_file,ios_base::binary|ios_base::in );
|
||||
loadImage( in );
|
||||
in.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool makeExe( int entry ){
|
||||
if( !img_file ) return false;
|
||||
|
||||
head->chars|=0x0002; //executable
|
||||
head->chars&=~0x2000; //not Dll
|
||||
opts->entry=entry;
|
||||
// opts->image_base=0x400000; //have to deal to fix-ups to do this properly.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replaceRsrc( int type,int id,int lang,void *data,int data_sz ){
|
||||
if( !img_file ) return false;
|
||||
|
||||
for( int k=0;k<sections.size();++k ){
|
||||
Section *s=sections[k];
|
||||
if( strcmp( s->sect.name,".rsrc" ) ) continue;
|
||||
|
||||
openRsrcTree( s );
|
||||
if( Rsrc *r=findRsrc( type,id,lang ) ){
|
||||
delete[] r->data;
|
||||
r->data_sz=data_sz;
|
||||
r->data=new char[data_sz];
|
||||
memcpy( r->data,data,data_sz );
|
||||
closeRsrcTree( s );
|
||||
return true;
|
||||
}
|
||||
closeRsrcTree( s );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void closeImage(){
|
||||
if( !img_file ) return;
|
||||
|
||||
fstream out( img_file,ios_base::binary|ios_base::out|ios_base::trunc );
|
||||
saveImage( out );
|
||||
out.close();
|
||||
|
||||
for( ;sections.size();sections.pop_back() ) delete sections.back();
|
||||
delete[] ddir;
|
||||
delete opts;
|
||||
delete head;
|
||||
delete[] stub;
|
||||
img_file=0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
#ifndef IMAGE_UTIL_H
|
||||
#define IMAGE_UTIL_H
|
||||
|
||||
bool openImage( const char *img );
|
||||
bool makeExe( int entry );
|
||||
bool replaceRsrc( int type,int id,int land,void *data,int data_sz );
|
||||
void closeImage();
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef LINKER_H
|
||||
#define LINKER_H
|
||||
|
||||
class Module{
|
||||
public:
|
||||
virtual ~Module(){}
|
||||
|
||||
virtual void *link( Module *libs )=0;
|
||||
virtual bool createExe( const char *exe_file,const char *dll_file )=0;
|
||||
|
||||
virtual int getPC()=0;
|
||||
|
||||
virtual void emit( int byte )=0;
|
||||
virtual void emitw( int word )=0;
|
||||
virtual void emitd( int dword )=0;
|
||||
virtual void emitx( void *data,int sz )=0;
|
||||
|
||||
virtual bool addSymbol( const char *sym,int pc )=0;
|
||||
virtual bool addReloc( const char *dest_sym,int pc,bool pcrel )=0;
|
||||
|
||||
virtual bool findSymbol( const char *sym,int *pc )=0;
|
||||
};
|
||||
|
||||
class Linker{
|
||||
public:
|
||||
virtual int version();
|
||||
virtual bool canCreateExe();
|
||||
virtual Module *createModule();
|
||||
virtual void deleteModule( Module *mod );
|
||||
};
|
||||
|
||||
extern "C" _declspec(dllexport) Linker * _cdecl linkerGetLinker();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#include "std.hpp"
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "stdutil.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
Reference in New Issue
Block a user