linker: Formatting

This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2019-01-18 17:03:57 +01:00
parent a16218e1d5
commit cc1340190e
8 changed files with 499 additions and 405 deletions
+49 -41
View File
@@ -1,69 +1,78 @@
#include "std.hpp"
#include "dlltoexe.hpp" #include "dlltoexe.hpp"
#include "std.hpp"
using namespace std; using namespace std;
#pragma pack( push,1 ) #pragma pack(push, 1)
struct Head{ struct Head {
short machine,num_sects; short machine, num_sects;
int timedata,sym_table,num_syms; int timedata, sym_table, num_syms;
short opt_size,chars; short opt_size, chars;
}; };
struct Opt1{ struct Opt1 {
short magic; short magic;
char major,minor; char major, minor;
int code_size,data_size,udata_size; int code_size, data_size, udata_size;
int entry,code_base,data_base; int entry, code_base, data_base;
}; };
struct Sect{ struct Sect {
char name[8]; char name[8];
int virt_size,virt_addr; //in mem int virt_size, virt_addr; //in mem
int data_size,data_addr; //on disk int data_size, data_addr; //on disk
int relocs,lines; //file ptrs int relocs, lines; //file ptrs
short num_relocs,num_lines; short num_relocs, num_lines;
int chars; int chars;
}; };
#pragma pack( pop ) #pragma pack(pop)
bool dllToExe( const char *exe_file,const char *dll_file,const char *entry_func ){
bool dllToExe(const char* exe_file, const char* dll_file, const char* entry_func)
{
//find proc address of bbWinMain //find proc address of bbWinMain
HMODULE hmod=LoadLibrary( dll_file );if( !hmod ) return false; HMODULE hmod = LoadLibrary(dll_file);
int proc=(int)GetProcAddress( hmod,entry_func ); if (!hmod)
int entry=proc-(int)hmod;FreeLibrary( hmod ); return false;
if( !proc ) return false; int proc = (int)GetProcAddress(hmod, entry_func);
int entry = proc - (int)hmod;
FreeLibrary(hmod);
if (!proc)
return false;
//Convert dll to exe //Convert dll to exe
fstream in( dll_file,ios_base::binary|ios_base::in );if( !in.is_open() ) return false; fstream in(dll_file, ios_base::binary | ios_base::in);
fstream out( exe_file,ios::binary|ios_base::out|ios_base::trunc );if( !out.is_open() ) return false; 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; int offs;
in.seekg( 0x3c ); in.seekg(0x3c);
in.read( (char*)&offs,4 ); in.read((char*)&offs, 4);
//copy first bit... //copy first bit...
in.seekg( 0 ); in.seekg(0);
for( int k=0;k<offs+4;++k ) out.put( in.get() ); for (int k = 0; k < offs + 4; ++k)
out.put(in.get());
//reader file header //reader file header
Head head={0}; Head head = {0};
in.read( (char*)&head,sizeof(head) ); in.read((char*)&head, sizeof(head));
//change DLL to EXE //change DLL to EXE
head.chars=0x10e; head.chars = 0x10e;
out.write( (char*)&head,sizeof(head) ); out.write((char*)&head, sizeof(head));
//read opts 1 //read opts 1
Opt1 opt1={0}; Opt1 opt1 = {0};
in.read( (char*)&opt1,sizeof(opt1) ); in.read((char*)&opt1, sizeof(opt1));
opt1.entry=entry; opt1.entry = entry;
out.write( (char*)&opt1,sizeof(opt1) ); out.write((char*)&opt1, sizeof(opt1));
//copy rest of file... //copy rest of file...
while( !in.eof() ){ while (!in.eof()) {
out.put( in.get() ); out.put(in.get());
} }
out.close(); out.close();
@@ -71,4 +80,3 @@ bool dllToExe( const char *exe_file,const char *dll_file,const char *entry_func
return true; return true;
} }
+1 -1
View File
@@ -2,6 +2,6 @@
#ifndef DLLTOEXE_H #ifndef DLLTOEXE_H
#define DLLTOEXE_H #define DLLTOEXE_H
bool dllToExe( const char *exe_file,const char *dll_file,const char *entry ); bool dllToExe(const char* exe_file, const char* dll_file, const char* entry);
#endif #endif
+246 -213
View File
@@ -1,367 +1,400 @@
#include "std.hpp"
#include "image_util.hpp" #include "image_util.hpp"
#include "std.hpp"
using namespace std; using namespace std;
#ifndef DEMO #ifndef DEMO
#pragma pack( push,1 ) #pragma pack(push, 1)
struct Head{ struct Head {
short machine,num_sects; short machine, num_sects;
int timedata,sym_table,num_syms; int timedata, sym_table, num_syms;
short opt_size,chars; short opt_size, chars;
}; };
struct Opts{ struct Opts {
short magic; short magic;
char major,minor; char major, minor;
int code_size,data_size,udata_size; int code_size, data_size, udata_size;
int entry,code_base,data_base; int entry, code_base, data_base;
int image_base,sect_align,file_align; int image_base, sect_align, file_align;
short major_os,minor_os,major_image,minor_image,major_subsys,minor_subsys; short major_os, minor_os, major_image, minor_image, major_subsys, minor_subsys;
int reserved; int reserved;
int image_size,headers_size,checksum; int image_size, headers_size, checksum;
short subsys,dllchars; short subsys, dllchars;
int stack_reserve, stack_commit, heap_reserve, heap_commit, loadflags;
int stack_reserve,stack_commit,heap_reserve,heap_commit,loadflags;
int dir_entries; int dir_entries;
}; };
struct DDir{ struct DDir {
int rva,size; int rva, size;
}; };
struct Sect{ struct Sect {
char name[8]; char name[8];
int virt_size,virt_addr; //in mem int virt_size, virt_addr; //in mem
int data_size,data_addr; //on disk int data_size, data_addr; //on disk
int relocs,lines; //file ptrs int relocs, lines; //file ptrs
short num_relocs,num_lines; short num_relocs, num_lines;
int chars; int chars;
}; };
struct Rdir{ struct Rdir {
int chars,timedata; int chars, timedata;
short major,minor,num_names,num_ids; short major, minor, num_names, num_ids;
}; };
struct Rent{ struct Rent {
int id,data; int id, data;
}; };
struct Rdat{ struct Rdat {
int addr,size,cp,zero; int addr, size, cp, zero;
}; };
#pragma pack( pop ) #pragma pack(pop)
struct Rsrc{ struct Rsrc {
int id; int id;
void *data; void* data;
int data_sz; int data_sz;
vector<Rsrc*> kids; vector<Rsrc*> kids;
Rsrc( int id,Rsrc *p ):id(id),data(0),data_sz(0){ 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; if (p)
p->kids.push_back(this);
// cout<<"res id:"<<dec<<id<<hex<<endl;
} }
~Rsrc(){ ~Rsrc()
for( ;kids.size();kids.pop_back() ) delete kids.back(); {
for (; kids.size(); kids.pop_back())
delete kids.back();
delete data; delete data;
} }
}; };
struct Section{ struct Section {
Sect sect; Sect sect;
char *data; char* data;
Section():data(0){} Section() : data(0) {}
~Section(){ delete[] data; } ~Section()
{
delete[] data;
}
}; };
static char *stub; static char* stub;
static int stub_sz; static int stub_sz;
static Head *head; static Head* head;
static int head_sz; static int head_sz;
static Opts *opts; static Opts* opts;
static int opts_sz; static int opts_sz;
static DDir *ddir; static DDir* ddir;
static int ddir_sz; static int ddir_sz;
static vector<Section*> sections; static vector<Section*> sections;
static Rsrc *rsrc_root; static Rsrc* rsrc_root;
static const char *img_file; static const char* img_file;
static void openRsrcDir( Section *s,int off,Rsrc *p ){ static void openRsrcDir(Section* s, int off, Rsrc* p)
char *data=(char*)s->data; {
char* data = (char*)s->data;
Rdir *dir=(Rdir*)(data+off); Rdir* dir = (Rdir*)(data + off);
Rent *ent=(Rent*)(dir+1); Rent* ent = (Rent*)(dir + 1);
for( int k=0;k<dir->num_ids;++ent,++k ){ for (int k = 0; k < dir->num_ids; ++ent, ++k) {
Rsrc *r=new Rsrc( ent->id,p ); Rsrc* r = new Rsrc(ent->id, p);
if( ent->data<0 ){ //a node - offset is another dir if (ent->data < 0) { //a node - offset is another dir
openRsrcDir( s,ent->data&0x7fffffff,r ); openRsrcDir(s, ent->data & 0x7fffffff, r);
}else{ //a leaf } else { //a leaf
Rdat *dat=(Rdat*)( data+ent->data ); Rdat* dat = (Rdat*)(data + ent->data);
// cout<<"dat addr:"<<dat->addr<<" size:"<<dat->size<<endl; // cout<<"dat addr:"<<dat->addr<<" size:"<<dat->size<<endl;
int sz=dat->size; int sz = dat->size;
void *src=dat->addr-s->sect.virt_addr+data; void* src = dat->addr - s->sect.virt_addr + data;
void *dest=new char[sz]; void* dest = new char[sz];
memcpy( dest,src,sz ); memcpy(dest, src, sz);
r->data=dest; r->data = dest;
r->data_sz=sz; r->data_sz = sz;
} }
} }
} }
static void openRsrcTree( Section *s ){ static void openRsrcTree(Section* s)
rsrc_root=new Rsrc( 0,0 ); {
openRsrcDir( s,0,rsrc_root ); rsrc_root = new Rsrc(0, 0);
openRsrcDir(s, 0, rsrc_root);
} }
static int rsrcSize( Rsrc *r ){ static int rsrcSize(Rsrc* r)
if( r->data ) return (sizeof(Rdat)+r->data_sz+7)&~7; {
int sz=sizeof( Rdir ); if (r->data)
for( int k=0;k<r->kids.size();++k ){ return (sizeof(Rdat) + r->data_sz + 7) & ~7;
sz+=sizeof( Rent )+rsrcSize( r->kids[k] ); int sz = sizeof(Rdir);
for (int k = 0; k < r->kids.size(); ++k) {
sz += sizeof(Rent) + rsrcSize(r->kids[k]);
} }
return sz; return sz;
} }
static void closeRsrcDir( Section *s,int off,Rsrc *p ){ static void closeRsrcDir(Section* s, int off, Rsrc* p)
{
int t, k;
int t,k; char* data = (char*)s->data;
char *data=(char*)s->data; Rdir* dir = (Rdir*)(data + off);
memset(dir, 0, sizeof(Rdir));
Rdir *dir=(Rdir*)(data+off); dir->num_ids = p->kids.size();
memset( dir,0,sizeof(Rdir) ); Rent* ent = (Rent*)(dir + 1);
dir->num_ids=p->kids.size();
Rent *ent=(Rent*)(dir+1);
//to end of dir... //to end of dir...
off+=sizeof(Rdir)+sizeof(Rent)*p->kids.size(); off += sizeof(Rdir) + sizeof(Rent) * p->kids.size();
t=off; t = off;
//write entries //write entries
for( k=0;k<p->kids.size();++ent,++k ){ for (k = 0; k < p->kids.size(); ++ent, ++k) {
Rsrc *r=p->kids[k]; Rsrc* r = p->kids[k];
ent->id=r->id; ent->id = r->id;
ent->data=t; ent->data = t;
if( !r->data ) ent->data|=0x80000000; if (!r->data)
t+=rsrcSize( r ); ent->data |= 0x80000000;
t += rsrcSize(r);
} }
t=off; t = off;
//write kids... //write kids...
for( k=0;k<p->kids.size();++k ){ for (k = 0; k < p->kids.size(); ++k) {
Rsrc *r=p->kids[k]; Rsrc* r = p->kids[k];
if( !r->data ){ if (!r->data) {
closeRsrcDir( s,t,r ); closeRsrcDir(s, t, r);
}else{ } else {
Rdat *dat=(Rdat*)(data+t); Rdat* dat = (Rdat*)(data + t);
dat->addr=s->sect.virt_addr+t+sizeof(Rdat); dat->addr = s->sect.virt_addr + t + sizeof(Rdat);
dat->size=r->data_sz; dat->size = r->data_sz;
dat->zero=dat->cp=0; dat->zero = dat->cp = 0;
memcpy( data+t+sizeof(Rdat),r->data,r->data_sz ); memcpy(data + t + sizeof(Rdat), r->data, r->data_sz);
} }
t+=rsrcSize( r ); t += rsrcSize(r);
} }
} }
static int fileAlign( int n ){ static int fileAlign(int n)
return (n+(opts->file_align-1))&~(opts->file_align-1); {
return (n + (opts->file_align - 1)) & ~(opts->file_align - 1);
} }
static int sectAlign( int n ){ static int sectAlign(int n)
return (n+(opts->sect_align-1))&~(opts->sect_align-1); {
return (n + (opts->sect_align - 1)) & ~(opts->sect_align - 1);
} }
static void closeRsrcTree( Section *s ){ static void closeRsrcTree(Section* s)
{
int virt_sz = rsrcSize(rsrc_root);
int data_sz = fileAlign(virt_sz);
int virt_sz=rsrcSize( rsrc_root ); int virt_delta = sectAlign(virt_sz) - sectAlign(s->sect.virt_size);
int data_sz=fileAlign( virt_sz ); int data_delta = fileAlign(virt_sz) - fileAlign(s->sect.virt_size);
int virt_delta=sectAlign(virt_sz)-sectAlign(s->sect.virt_size); for (int k = 0; k < sections.size(); ++k) {
int data_delta=fileAlign(virt_sz)-fileAlign(s->sect.virt_size); Section* t = sections[k];
if (t->sect.virt_addr > s->sect.virt_addr) {
t->sect.virt_addr += virt_delta;
for( int k=0;k<sections.size();++k ){ if (!strcmp(t->sect.name, ".reloc")) {
Section *t=sections[k]; ddir[5].rva = t->sect.virt_addr;
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 ){ if (t->sect.data_addr > s->sect.data_addr) {
t->sect.data_addr+=data_delta; t->sect.data_addr += data_delta;
} }
} }
ddir[2].size=virt_sz; ddir[2].size = virt_sz;
opts->image_size+=virt_delta; opts->image_size += virt_delta;
s->sect.virt_size=virt_sz; s->sect.virt_size = virt_sz;
s->sect.data_size=data_sz; s->sect.data_size = data_sz;
delete[] s->data; delete[] s->data;
s->data=new char[data_sz]; s->data = new char[data_sz];
closeRsrcDir( s,0,rsrc_root ); closeRsrcDir(s, 0, rsrc_root);
delete rsrc_root; delete rsrc_root;
rsrc_root=0; rsrc_root = 0;
} }
static Rsrc *findRsrc( int id,Rsrc *p ){ 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]; for (int k = 0; k < p->kids.size(); ++k) {
if (p->kids[k]->id == id)
return p->kids[k];
} }
return 0; return 0;
} }
static Rsrc *findRsrc( int type,int id,int lang ){ 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; Rsrc* r = findRsrc(type, rsrc_root);
return findRsrc( lang,r ); if (!r)
return 0;
r = findRsrc(id, r);
if (!r)
return 0;
return findRsrc(lang, r);
} }
static void loadImage( istream &in ){ static void loadImage(istream& in)
{
int k; int k;
//read stub //read stub
in.seekg( 0x3c ); in.seekg(0x3c);
in.read( (char*)&stub_sz,4 ); in.read((char*)&stub_sz, 4);
stub_sz+=4;stub=new char[stub_sz]; stub_sz += 4;
in.seekg( 0 );in.read( stub,stub_sz ); stub = new char[stub_sz];
in.seekg(0);
in.read(stub, stub_sz);
//read head //read head
head=new Head; head = new Head;
head_sz=sizeof(Head); head_sz = sizeof(Head);
in.read( (char*)head,head_sz ); in.read((char*)head, head_sz);
//read opts //read opts
opts=new Opts; opts = new Opts;
opts_sz=sizeof(Opts); opts_sz = sizeof(Opts);
in.read( (char*)opts,opts_sz ); in.read((char*)opts, opts_sz);
//read data dirs //read data dirs
ddir_sz=opts->dir_entries * sizeof(DDir); ddir_sz = opts->dir_entries * sizeof(DDir);
ddir=(DDir*)new char[ddir_sz]; ddir = (DDir*)new char[ddir_sz];
in.read( (char*)ddir,ddir_sz ); in.read((char*)ddir, ddir_sz);
//read sects... //read sects...
for( k=0;k<head->num_sects;++k ){ for (k = 0; k < head->num_sects; ++k) {
Section *s=new Section; Section* s = new Section;
in.read( (char*)&s->sect,sizeof(Sect) ); in.read((char*)&s->sect, sizeof(Sect));
sections.push_back( s ); sections.push_back(s);
} }
for( k=0;k<head->num_sects;++k ){ for (k = 0; k < head->num_sects; ++k) {
Section *s=sections[k]; Section* s = sections[k];
if( !s->sect.data_addr ) continue; if (!s->sect.data_addr)
int data_sz=s->sect.data_size; continue;
s->data=new char[data_sz];//char[s->sect.virt_size]; 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 ); //memset( s->data,0,s->sect.virt_size );
in.seekg( s->sect.data_addr ); in.seekg(s->sect.data_addr);
in.read( s->data,data_sz ); in.read(s->data, data_sz);
} }
} }
static void saveImage( ostream &out ){ static void saveImage(ostream& out)
{
int k; int k;
out.write( (char*)stub,stub_sz ); out.write((char*)stub, stub_sz);
out.write( (char*)head,head_sz ); out.write((char*)head, head_sz);
out.write( (char*)opts,opts_sz ); out.write((char*)opts, opts_sz);
out.write( (char*)ddir,ddir_sz ); out.write((char*)ddir, ddir_sz);
for( k=0;k<head->num_sects;++k ){ for (k = 0; k < head->num_sects; ++k) {
Section *s=sections[k]; Section* s = sections[k];
out.write( (char*)&s->sect,sizeof(Sect) ); out.write((char*)&s->sect, sizeof(Sect));
} }
for( k=0;k<head->num_sects;++k ){ for (k = 0; k < head->num_sects; ++k) {
Section *s=sections[k]; Section* s = sections[k];
if( !s->sect.data_addr ) continue; if (!s->sect.data_addr)
continue;
//assumes sect data is in order!!!!! //assumes sect data is in order!!!!!
while( out.tellp()<s->sect.data_addr ) out.put( (char)0xbb ); while (out.tellp() < s->sect.data_addr)
out.seekp( s->sect.data_addr ); out.put((char)0xbb);
out.write( s->data,s->sect.data_size ); out.seekp(s->sect.data_addr);
out.write(s->data, s->sect.data_size);
} }
} }
/********************** PUBLIC STUFF ***********************/ /********************** PUBLIC STUFF ***********************/
bool openImage( const char *img ){ bool openImage(const char* img)
img_file=img; {
img_file = img;
fstream in( img_file,ios_base::binary|ios_base::in ); fstream in(img_file, ios_base::binary | ios_base::in);
loadImage( in ); loadImage(in);
in.close(); in.close();
return true; return true;
} }
bool makeExe( int entry ){ bool makeExe(int entry)
if( !img_file ) return false; {
if (!img_file)
return false;
head->chars|=0x0002; //executable head->chars |= 0x0002; //executable
head->chars&=~0x2000; //not Dll head->chars &= ~0x2000; //not Dll
opts->entry=entry; opts->entry = entry;
// opts->image_base=0x400000; //have to deal to fix-ups to do this properly. // opts->image_base=0x400000; //have to deal to fix-ups to do this properly.
return true; return true;
} }
bool replaceRsrc( int type,int id,int lang,void *data,int data_sz ){ bool replaceRsrc(int type, int id, int lang, void* data, int data_sz)
if( !img_file ) return false; {
if (!img_file)
return false;
for( int k=0;k<sections.size();++k ){ for (int k = 0; k < sections.size(); ++k) {
Section *s=sections[k]; Section* s = sections[k];
if( strcmp( s->sect.name,".rsrc" ) ) continue; if (strcmp(s->sect.name, ".rsrc"))
continue;
openRsrcTree( s ); openRsrcTree(s);
if( Rsrc *r=findRsrc( type,id,lang ) ){ if (Rsrc* r = findRsrc(type, id, lang)) {
delete[] r->data; delete[] r->data;
r->data_sz=data_sz; r->data_sz = data_sz;
r->data=new char[data_sz]; r->data = new char[data_sz];
memcpy( r->data,data,data_sz ); memcpy(r->data, data, data_sz);
closeRsrcTree( s ); closeRsrcTree(s);
return true; return true;
} }
closeRsrcTree( s ); closeRsrcTree(s);
} }
return false; return false;
} }
void closeImage(){ void closeImage()
if( !img_file ) return; {
if (!img_file)
return;
fstream out( img_file,ios_base::binary|ios_base::out|ios_base::trunc ); fstream out(img_file, ios_base::binary | ios_base::out | ios_base::trunc);
saveImage( out ); saveImage(out);
out.close(); out.close();
for( ;sections.size();sections.pop_back() ) delete sections.back(); for (; sections.size(); sections.pop_back())
delete sections.back();
delete[] ddir; delete[] ddir;
delete opts; delete opts;
delete head; delete head;
delete[] stub; delete[] stub;
img_file=0; img_file = 0;
} }
#endif #endif
+3 -3
View File
@@ -2,9 +2,9 @@
#ifndef IMAGE_UTIL_H #ifndef IMAGE_UTIL_H
#define IMAGE_UTIL_H #define IMAGE_UTIL_H
bool openImage( const char *img ); bool openImage(const char* img);
bool makeExe( int entry ); bool makeExe(int entry);
bool replaceRsrc( int type,int id,int land,void *data,int data_sz ); bool replaceRsrc(int type, int id, int land, void* data, int data_sz);
void closeImage(); void closeImage();
#endif #endif
+165 -111
View File
@@ -1,137 +1,172 @@
#include "std.hpp"
#include "linker.hpp" #include "linker.hpp"
#include "image_util.hpp" #include "image_util.hpp"
#include "std.hpp"
using namespace std; using namespace std;
class BBModule : public Module{ class BBModule : public Module {
public: public:
BBModule(); BBModule();
BBModule( istream &in ); BBModule(istream& in);
~BBModule(); ~BBModule();
void *link( Module *libs ); void* link(Module* libs);
bool createExe( const char *exe_file,const char *dll_file ); bool createExe(const char* exe_file, const char* dll_file);
int getPC(); int getPC();
void emit( int byte ); void emit(int byte);
void emitw( int word ); void emitw(int word);
void emitd( int dword ); void emitd(int dword);
void emitx( void *mem,int sz ); void emitx(void* mem, int sz);
bool addSymbol( const char *sym,int pc ); bool addSymbol(const char* sym, int pc);
bool addReloc( const char *dest_sym,int pc,bool pcrel ); bool addReloc(const char* dest_sym, int pc, bool pcrel);
bool findSymbol( const char *sym,int *pc ); bool findSymbol(const char* sym, int* pc);
private: private:
char *data; char* data;
int data_sz,pc; int data_sz, pc;
bool linked; bool linked;
map<string,int> symbols; map<string, int> symbols;
map<int,string> rel_relocs,abs_relocs; map<int, string> rel_relocs, abs_relocs;
bool findSym( const string &t,Module *libs,int *n ){ 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; if (findSymbol(t.c_str(), n))
string err="Symbol '"+t+"' not found"; return true;
MessageBox( GetDesktopWindow(),err.c_str(),"Blitz Linker Error",MB_TOPMOST|MB_SETFOREGROUND ); 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; return false;
} }
void ensure( int n ){ void ensure(int n)
if( pc+n<=data_sz ) return; {
data_sz=data_sz/2+data_sz; if (pc + n <= data_sz)
if( data_sz<pc+n ) data_sz=pc+n; return;
char *old_data=data; data_sz = data_sz / 2 + data_sz;
data=new char[data_sz]; if (data_sz < pc + n)
memcpy( data,old_data,pc ); data_sz = pc + n;
char* old_data = data;
data = new char[data_sz];
memcpy(data, old_data, pc);
delete old_data; delete old_data;
} }
}; };
BBModule::BBModule():data(0),data_sz(0),pc(0),linked(false){ BBModule::BBModule() : data(0), data_sz(0), pc(0), linked(false) {}
BBModule::~BBModule()
{
if (linked)
VirtualFree(data, 0, MEM_RELEASE);
else
delete[] data;
} }
BBModule::~BBModule(){ void* BBModule::link(Module* libs)
if( linked ) VirtualFree( data,0,MEM_RELEASE ); {
else delete[] data; if (linked)
} return data;
void *BBModule::link( Module *libs ){ int dest;
map<int, string>::iterator it;
if( linked ) return data; char* p = (char*)VirtualAlloc(0, pc, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(p, data, pc);
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; delete[] data;
data=p; data = p;
linked=true; linked = true;
for( it=rel_relocs.begin();it!=rel_relocs.end();++it ){ for (it = rel_relocs.begin(); it != rel_relocs.end(); ++it) {
if( !findSym( it->second,libs,&dest ) ) return 0; if (!findSym(it->second, libs, &dest))
int *p=(int*)(data+it->first);*p+=(dest-(int)p); return 0;
int* p = (int*)(data + it->first);
*p += (dest - (int)p);
} }
for( it=abs_relocs.begin();it!=abs_relocs.end();++it ){ for (it = abs_relocs.begin(); it != abs_relocs.end(); ++it) {
if( !findSym( it->second,libs,&dest ) ) return 0; if (!findSym(it->second, libs, &dest))
int *p=(int*)(data+it->first);*p+=dest; return 0;
int* p = (int*)(data + it->first);
*p += dest;
} }
return data; return data;
} }
int BBModule::getPC(){ int BBModule::getPC()
{
return pc; return pc;
} }
void BBModule::emit( int byte ){ void BBModule::emit(int byte)
ensure(1);data[pc++]=byte; {
ensure(1);
data[pc++] = byte;
} }
void BBModule::emitw( int word ){ void BBModule::emitw(int word)
ensure(2);*(short*)(data+pc)=word;pc+=2; {
ensure(2);
*(short*)(data + pc) = word;
pc += 2;
} }
void BBModule::emitd( int dword ){ void BBModule::emitd(int dword)
ensure(4);*(int*)(data+pc)=dword;pc+=4; {
ensure(4);
*(int*)(data + pc) = dword;
pc += 4;
} }
void BBModule::emitx( void *mem,int sz ){ void BBModule::emitx(void* mem, int sz)
ensure(sz);memcpy( data+pc,mem,sz );pc+=sz; {
ensure(sz);
memcpy(data + pc, mem, sz);
pc += sz;
} }
bool BBModule::addSymbol( const char *sym,int pc ){ bool BBModule::addSymbol(const char* sym, int pc)
{
string t(sym); string t(sym);
if( symbols.find( t )!=symbols.end() ) return false; if (symbols.find(t) != symbols.end())
symbols[t]=pc;return true; return false;
} symbols[t] = pc;
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; return true;
} }
int Linker::version(){ 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; return VERSION;
} }
bool Linker::canCreateExe(){ bool Linker::canCreateExe()
{
#ifdef DEMO #ifdef DEMO
return false; return false;
#else #else
@@ -139,34 +174,45 @@ bool Linker::canCreateExe(){
#endif #endif
} }
Module *Linker::createModule(){ Module* Linker::createModule()
{
return new BBModule(); return new BBModule();
} }
void Linker::deleteModule( Module *mod ){ void Linker::deleteModule(Module* mod)
{
delete mod; delete mod;
} }
Linker *_cdecl linkerGetLinker(){ Linker* _cdecl linkerGetLinker()
static Linker linker;return &linker; {
static Linker linker;
return &linker;
} }
bool BBModule::createExe( const char *exe_file,const char *dll_file ){ bool BBModule::createExe(const char* exe_file, const char* dll_file)
{
#ifdef DEMO #ifdef DEMO
return false; return false;
#else #else
//find proc address of bbWinMain //find proc address of bbWinMain
HMODULE hmod=LoadLibrary( dll_file );if( !hmod ) return false; HMODULE hmod = LoadLibrary(dll_file);
int proc=(int)GetProcAddress( hmod,"_bbWinMain@0" ); if (!hmod)
int entry=proc-(int)hmod;FreeLibrary( hmod );if( !proc ) return false; 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 (!CopyFile(dll_file, exe_file, false))
return false;
if( !openImage( exe_file ) ) return false; if (!openImage(exe_file))
return false;
makeExe( entry ); makeExe(entry);
//create module //create module
//code size: code... //code size: code...
@@ -175,39 +221,47 @@ bool BBModule::createExe( const char *exe_file,const char *dll_file ){
//num_abss: name,val... //num_abss: name,val...
// //
qstreambuf buf; qstreambuf buf;
iostream out( &buf ); iostream out(&buf);
map<string,int>::iterator it; map<string, int>::iterator it;
map<int,string>::iterator rit; map<int, string>::iterator rit;
//write the code //write the code
int sz=pc;out.write( (char*)&sz,4 );out.write( data,pc ); int sz = pc;
out.write((char*)&sz, 4);
out.write(data, pc);
//write symbols //write symbols
sz=symbols.size();out.write( (char*)&sz,4 ); sz = symbols.size();
for( it=symbols.begin();it!=symbols.end();++it ){ out.write((char*)&sz, 4);
string t=it->first+'\0'; for (it = symbols.begin(); it != symbols.end(); ++it) {
out.write( t.data(),t.size() ); string t = it->first + '\0';
sz=it->second;out.write( (char*)&sz,4 ); out.write(t.data(), t.size());
sz = it->second;
out.write((char*)&sz, 4);
} }
//write relative relocs //write relative relocs
sz=rel_relocs.size();out.write( (char*)&sz,4 ); sz = rel_relocs.size();
for( rit=rel_relocs.begin();rit!=rel_relocs.end();++rit ){ out.write((char*)&sz, 4);
string t=rit->second+'\0'; for (rit = rel_relocs.begin(); rit != rel_relocs.end(); ++rit) {
out.write( t.data(),t.size() ); string t = rit->second + '\0';
sz=rit->first;out.write( (char*)&sz,4 ); out.write(t.data(), t.size());
sz = rit->first;
out.write((char*)&sz, 4);
} }
//write absolute relocs //write absolute relocs
sz=abs_relocs.size();out.write( (char*)&sz,4 ); sz = abs_relocs.size();
for( rit=abs_relocs.begin();rit!=abs_relocs.end();++rit ){ out.write((char*)&sz, 4);
string t=rit->second+'\0'; for (rit = abs_relocs.begin(); rit != abs_relocs.end(); ++rit) {
out.write( t.data(),t.size() ); string t = rit->second + '\0';
sz=rit->first;out.write( (char*)&sz,4 ); out.write(t.data(), t.size());
sz = rit->first;
out.write((char*)&sz, 4);
} }
replaceRsrc( 10,1111,1033,buf.data(),buf.size() ); replaceRsrc(10, 1111, 1033, buf.data(), buf.size());
closeImage(); closeImage();
+20 -20
View File
@@ -2,34 +2,34 @@
#ifndef LINKER_H #ifndef LINKER_H
#define LINKER_H #define LINKER_H
class Module{ class Module {
public: public:
virtual ~Module(){} virtual ~Module() {}
virtual void *link( Module *libs )=0; virtual void* link(Module* libs) = 0;
virtual bool createExe( const char *exe_file,const char *dll_file )=0; virtual bool createExe(const char* exe_file, const char* dll_file) = 0;
virtual int getPC()=0; virtual int getPC() = 0;
virtual void emit( int byte )=0; virtual void emit(int byte) = 0;
virtual void emitw( int word )=0; virtual void emitw(int word) = 0;
virtual void emitd( int dword )=0; virtual void emitd(int dword) = 0;
virtual void emitx( void *data,int sz )=0; virtual void emitx(void* data, int sz) = 0;
virtual bool addSymbol( const char *sym,int pc )=0; virtual bool addSymbol(const char* sym, int pc) = 0;
virtual bool addReloc( const char *dest_sym,int pc,bool pcrel )=0; virtual bool addReloc(const char* dest_sym, int pc, bool pcrel) = 0;
virtual bool findSymbol( const char *sym,int *pc )=0; virtual bool findSymbol(const char* sym, int* pc) = 0;
}; };
class Linker{ class Linker {
public: public:
virtual int version(); virtual int version();
virtual bool canCreateExe(); virtual bool canCreateExe();
virtual Module *createModule(); virtual Module* createModule();
virtual void deleteModule( Module *mod ); virtual void deleteModule(Module* mod);
}; };
extern "C" _declspec(dllexport) Linker * _cdecl linkerGetLinker(); extern "C" _declspec(dllexport) Linker* _cdecl linkerGetLinker();
#endif #endif
+4 -4
View File
@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <map> #include <fstream>
#include <iomanip>
#include <iostream>
#include <list> #include <list>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <fstream>
#include <iostream>
#include <iomanip>
#include "stdutil.hpp" #include "stdutil.hpp"
#include <windows.h> #include <windows.h>
+11 -12
View File
@@ -1,20 +1,19 @@
#include "std.hpp"
#include "linker.hpp" #include "linker.hpp"
#include "std.hpp"
#include <windows.h> #include <windows.h>
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch( ul_reason_for_call ){ switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
linkerGetLinker(); linkerGetLinker();
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
default: default:;
; }
} return TRUE;
return TRUE;
} }