image_util.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #include "std.h"
  2. #include "image_util.h"
  3. #ifndef DEMO
  4. #pragma pack( push,1 )
  5. struct Head{
  6. short machine,num_sects;
  7. int timedata,sym_table,num_syms;
  8. short opt_size,chars;
  9. };
  10. struct Opts{
  11. short magic;
  12. char major,minor;
  13. int code_size,data_size,udata_size;
  14. int entry,code_base,data_base;
  15. int image_base,sect_align,file_align;
  16. short major_os,minor_os,major_image,minor_image,major_subsys,minor_subsys;
  17. int reserved;
  18. int image_size,headers_size,checksum;
  19. short subsys,dllchars;
  20. int stack_reserve,stack_commit,heap_reserve,heap_commit,loadflags;
  21. int dir_entries;
  22. };
  23. struct DDir{
  24. int rva,size;
  25. };
  26. struct Sect{
  27. char name[8];
  28. int virt_size,virt_addr; //in mem
  29. int data_size,data_addr; //on disk
  30. int relocs,lines; //file ptrs
  31. short num_relocs,num_lines;
  32. int chars;
  33. };
  34. struct Rdir{
  35. int chars,timedata;
  36. short major,minor,num_names,num_ids;
  37. };
  38. struct Rent{
  39. int id,data;
  40. };
  41. struct Rdat{
  42. int addr,size,cp,zero;
  43. };
  44. #pragma pack( pop )
  45. struct Rsrc{
  46. int id;
  47. void *data;
  48. int data_sz;
  49. vector<Rsrc*> kids;
  50. Rsrc( int id,Rsrc *p ):id(id),data(0),data_sz(0){
  51. if( p ) p->kids.push_back( this );
  52. // cout<<"res id:"<<dec<<id<<hex<<endl;
  53. }
  54. ~Rsrc(){
  55. for( ;kids.size();kids.pop_back() ) delete kids.back();
  56. delete data;
  57. }
  58. };
  59. struct Section{
  60. Sect sect;
  61. char *data;
  62. Section():data(0){}
  63. ~Section(){ delete[] data; }
  64. };
  65. static char *stub;
  66. static int stub_sz;
  67. static Head *head;
  68. static int head_sz;
  69. static Opts *opts;
  70. static int opts_sz;
  71. static DDir *ddir;
  72. static int ddir_sz;
  73. static vector<Section*> sections;
  74. static Rsrc *rsrc_root;
  75. static const char *img_file;
  76. static void openRsrcDir( Section *s,int off,Rsrc *p ){
  77. char *data=(char*)s->data;
  78. Rdir *dir=(Rdir*)(data+off);
  79. Rent *ent=(Rent*)(dir+1);
  80. for( int k=0;k<dir->num_ids;++ent,++k ){
  81. Rsrc *r=d_new Rsrc( ent->id,p );
  82. if( ent->data<0 ){ //a node - offset is another dir
  83. openRsrcDir( s,ent->data&0x7fffffff,r );
  84. }else{ //a leaf
  85. Rdat *dat=(Rdat*)( data+ent->data );
  86. // cout<<"dat addr:"<<dat->addr<<" size:"<<dat->size<<endl;
  87. int sz=dat->size;
  88. void *src=dat->addr-s->sect.virt_addr+data;
  89. void *dest=d_new char[sz];
  90. memcpy( dest,src,sz );
  91. r->data=dest;
  92. r->data_sz=sz;
  93. }
  94. }
  95. }
  96. static void openRsrcTree( Section *s ){
  97. rsrc_root=d_new Rsrc( 0,0 );
  98. openRsrcDir( s,0,rsrc_root );
  99. }
  100. static int rsrcSize( Rsrc *r ){
  101. if( r->data ) return (sizeof(Rdat)+r->data_sz+7)&~7;
  102. int sz=sizeof( Rdir );
  103. for( int k=0;k<r->kids.size();++k ){
  104. sz+=sizeof( Rent )+rsrcSize( r->kids[k] );
  105. }
  106. return sz;
  107. }
  108. static void closeRsrcDir( Section *s,int off,Rsrc *p ){
  109. int t,k;
  110. char *data=(char*)s->data;
  111. Rdir *dir=(Rdir*)(data+off);
  112. memset( dir,0,sizeof(Rdir) );
  113. dir->num_ids=p->kids.size();
  114. Rent *ent=(Rent*)(dir+1);
  115. //to end of dir...
  116. off+=sizeof(Rdir)+sizeof(Rent)*p->kids.size();
  117. t=off;
  118. //write entries
  119. for( k=0;k<p->kids.size();++ent,++k ){
  120. Rsrc *r=p->kids[k];
  121. ent->id=r->id;
  122. ent->data=t;
  123. if( !r->data ) ent->data|=0x80000000;
  124. t+=rsrcSize( r );
  125. }
  126. t=off;
  127. //write kids...
  128. for( k=0;k<p->kids.size();++k ){
  129. Rsrc *r=p->kids[k];
  130. if( !r->data ){
  131. closeRsrcDir( s,t,r );
  132. }else{
  133. Rdat *dat=(Rdat*)(data+t);
  134. dat->addr=s->sect.virt_addr+t+sizeof(Rdat);
  135. dat->size=r->data_sz;
  136. dat->zero=dat->cp=0;
  137. memcpy( data+t+sizeof(Rdat),r->data,r->data_sz );
  138. }
  139. t+=rsrcSize( r );
  140. }
  141. }
  142. static int fileAlign( int n ){
  143. return (n+(opts->file_align-1))&~(opts->file_align-1);
  144. }
  145. static int sectAlign( int n ){
  146. return (n+(opts->sect_align-1))&~(opts->sect_align-1);
  147. }
  148. static void closeRsrcTree( Section *s ){
  149. int virt_sz=rsrcSize( rsrc_root );
  150. int data_sz=fileAlign( virt_sz );
  151. int virt_delta=sectAlign(virt_sz)-sectAlign(s->sect.virt_size);
  152. int data_delta=fileAlign(virt_sz)-fileAlign(s->sect.virt_size);
  153. for( int k=0;k<sections.size();++k ){
  154. Section *t=sections[k];
  155. if( t->sect.virt_addr>s->sect.virt_addr ){
  156. t->sect.virt_addr+=virt_delta;
  157. if( !strcmp( t->sect.name,".reloc" ) ){
  158. ddir[5].rva=t->sect.virt_addr;
  159. }
  160. }
  161. if( t->sect.data_addr>s->sect.data_addr ){
  162. t->sect.data_addr+=data_delta;
  163. }
  164. }
  165. ddir[2].size=virt_sz;
  166. opts->image_size+=virt_delta;
  167. s->sect.virt_size=virt_sz;
  168. s->sect.data_size=data_sz;
  169. delete[] s->data;
  170. s->data=d_new char[data_sz];
  171. closeRsrcDir( s,0,rsrc_root );
  172. delete rsrc_root;
  173. rsrc_root=0;
  174. }
  175. static Rsrc *findRsrc( int id,Rsrc *p ){
  176. for( int k=0;k<p->kids.size();++k ){
  177. if( p->kids[k]->id==id ) return p->kids[k];
  178. }
  179. return 0;
  180. }
  181. static Rsrc *findRsrc( int type,int id,int lang ){
  182. Rsrc *r=findRsrc( type,rsrc_root );if( !r ) return 0;
  183. r=findRsrc( id,r );if( !r ) return 0;
  184. return findRsrc( lang,r );
  185. }
  186. static void loadImage( istream &in ){
  187. int k;
  188. //read stub
  189. in.seekg( 0x3c );
  190. in.read( (char*)&stub_sz,4 );
  191. stub_sz+=4;stub=d_new char[stub_sz];
  192. in.seekg( 0 );in.read( stub,stub_sz );
  193. //read head
  194. head=d_new Head;
  195. head_sz=sizeof(Head);
  196. in.read( (char*)head,head_sz );
  197. //read opts
  198. opts=d_new Opts;
  199. opts_sz=sizeof(Opts);
  200. in.read( (char*)opts,opts_sz );
  201. //read data dirs
  202. ddir_sz=opts->dir_entries * sizeof(DDir);
  203. ddir=(DDir*)d_new char[ddir_sz];
  204. in.read( (char*)ddir,ddir_sz );
  205. //read sects...
  206. for( k=0;k<head->num_sects;++k ){
  207. Section *s=d_new Section;
  208. in.read( (char*)&s->sect,sizeof(Sect) );
  209. sections.push_back( s );
  210. }
  211. for( k=0;k<head->num_sects;++k ){
  212. Section *s=sections[k];
  213. if( !s->sect.data_addr ) continue;
  214. int data_sz=s->sect.data_size;
  215. s->data=d_new char[data_sz];//char[s->sect.virt_size];
  216. //memset( s->data,0,s->sect.virt_size );
  217. in.seekg( s->sect.data_addr );
  218. in.read( s->data,data_sz );
  219. }
  220. }
  221. static void saveImage( ostream &out ){
  222. int k;
  223. out.write( (char*)stub,stub_sz );
  224. out.write( (char*)head,head_sz );
  225. out.write( (char*)opts,opts_sz );
  226. out.write( (char*)ddir,ddir_sz );
  227. for( k=0;k<head->num_sects;++k ){
  228. Section *s=sections[k];
  229. out.write( (char*)&s->sect,sizeof(Sect) );
  230. }
  231. for( k=0;k<head->num_sects;++k ){
  232. Section *s=sections[k];
  233. if( !s->sect.data_addr ) continue;
  234. //assumes sect data is in order!!!!!
  235. while( out.tellp()<s->sect.data_addr ) out.put( (char)0xbb );
  236. out.seekp( s->sect.data_addr );
  237. out.write( s->data,s->sect.data_size );
  238. }
  239. }
  240. /********************** PUBLIC STUFF ***********************/
  241. bool openImage( const char *img ){
  242. img_file=img;
  243. fstream in( img_file,ios_base::binary|ios_base::in );
  244. loadImage( in );
  245. in.close();
  246. return true;
  247. }
  248. bool makeExe( int entry ){
  249. if( !img_file ) return false;
  250. head->chars|=0x0002; //executable
  251. head->chars&=~0x2000; //not Dll
  252. opts->entry=entry;
  253. // opts->image_base=0x400000; //have to deal to fix-ups to do this properly.
  254. return true;
  255. }
  256. bool replaceRsrc( int type,int id,int lang,void *data,int data_sz ){
  257. if( !img_file ) return false;
  258. for( int k=0;k<sections.size();++k ){
  259. Section *s=sections[k];
  260. if( strcmp( s->sect.name,".rsrc" ) ) continue;
  261. openRsrcTree( s );
  262. if( Rsrc *r=findRsrc( type,id,lang ) ){
  263. delete[] r->data;
  264. r->data_sz=data_sz;
  265. r->data=d_new char[data_sz];
  266. memcpy( r->data,data,data_sz );
  267. closeRsrcTree( s );
  268. return true;
  269. }
  270. closeRsrcTree( s );
  271. }
  272. return false;
  273. }
  274. void closeImage(){
  275. if( !img_file ) return;
  276. fstream out( img_file,ios_base::binary|ios_base::out|ios_base::trunc );
  277. saveImage( out );
  278. out.close();
  279. for( ;sections.size();sections.pop_back() ) delete sections.back();
  280. delete[] ddir;
  281. delete opts;
  282. delete head;
  283. delete[] stub;
  284. img_file=0;
  285. }
  286. #endif