2
0

impdef.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Pavel
  4. This unit finds the export defs from PE files
  5. C source code of DEWIN Windows disassembler (written by A. Milukov) was
  6. partially used
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit imtdef;
  21. {$ifndef STANDALONE}
  22. {$i fpcdefs.inc}
  23. {$endif}
  24. interface
  25. uses
  26. {$ifdef Delphi}
  27. SysUtils,
  28. Dmisc;
  29. {$else}
  30. Dos;
  31. {$endif}
  32. var
  33. as_name,
  34. ar_name : string;
  35. function makedef(const binname,
  36. {$IFDEF STANDALONE}
  37. textname,
  38. {$ENDIF}
  39. libname:string):longbool;
  40. implementation
  41. {$IFDEF STANDALONE}
  42. var
  43. __textname : string;
  44. const
  45. kind : array[longbool] of pchar=('',' DATA');
  46. {$ENDIF}
  47. var
  48. f:file;
  49. {$IFDEF STANDALONE}
  50. t:text;
  51. FileCreated:longbool;
  52. {$ENDIF}
  53. lname:string;
  54. impname:string;
  55. TheWord:array[0..1]of char;
  56. PEoffset:cardinal;
  57. loaded:longint;
  58. function DOSstubOK(var x:longint):longbool;
  59. begin
  60. blockread(f,TheWord,2,loaded);
  61. if loaded<>2 then
  62. DOSstubOK:=false
  63. else
  64. begin
  65. DOSstubOK:=TheWord='MZ';
  66. seek(f,$3C);
  67. blockread(f,x,4,loaded);
  68. if(loaded<>4)or(x>filesize(f))then
  69. DOSstubOK:=false;
  70. end;
  71. end;
  72. function isPE(x:longint):longbool;
  73. begin
  74. seek(f,x);
  75. blockread(f,TheWord,2,loaded);
  76. isPE:=(loaded=2)and(TheWord='PE');
  77. end;
  78. var
  79. cstring : array[0..127]of char;
  80. function GetEdata(PE:cardinal):longbool;
  81. type
  82. TObjInfo=packed record
  83. ObjName:array[0..7]of char;
  84. VirtSize,
  85. VirtAddr,
  86. RawSize,
  87. RawOffset,
  88. Reloc,
  89. LineNum:cardinal;
  90. RelCount,
  91. LineCount:word;
  92. flags:cardinal;
  93. end;
  94. var
  95. i:cardinal;
  96. ObjOfs:cardinal;
  97. Obj:TObjInfo;
  98. APE_obj,APE_Optsize:word;
  99. ExportRVA:cardinal;
  100. delta:cardinal;
  101. const
  102. IMAGE_SCN_CNT_CODE=$00000020;
  103. const
  104. {$ifdef unix}
  105. DirSep = '/';
  106. {$else}
  107. {$ifdef amiga}
  108. DirSep = '/';
  109. {$else}
  110. DirSep = '\';
  111. {$endif}
  112. {$endif}
  113. var
  114. path:string;
  115. _d:dirstr;
  116. _n:namestr;
  117. _e:extstr;
  118. common_created:longbool;
  119. procedure cleardir(const s,ext:string);
  120. var
  121. ff:file;
  122. dir:searchrec;
  123. attr:word;
  124. begin
  125. findfirst(s+dirsep+ext,anyfile,dir);
  126. while (doserror=0) do
  127. begin
  128. assign(ff,s+dirsep+dir.name);
  129. GetFattr(ff,attr);
  130. if not((DOSError<>0)or(Attr and Directory<>0))then
  131. Erase(ff);
  132. findnext(dir);
  133. end;
  134. findclose(dir);
  135. end;
  136. procedure CreateTempDir(const s:string);
  137. var
  138. attr:word;
  139. ff:file;
  140. begin
  141. assign(ff,s);
  142. GetFattr(ff,attr);
  143. if DosError=0 then
  144. begin
  145. cleardir(s,'*.sw');
  146. cleardir(s,'*.swo');
  147. end
  148. else
  149. begin
  150. {$I-}
  151. mkdir(s);
  152. {$I+}
  153. if ioresult<>0 then;
  154. end;
  155. end;
  156. procedure call_as(const name:string);
  157. begin
  158. exec(utilsprefix+as_name,'-o '+name+'o '+name);
  159. end;
  160. procedure call_ar;
  161. var
  162. f:file;
  163. attr:word;
  164. begin
  165. {$IFDEF STANDALONE}
  166. if impname='' then
  167. exit;
  168. {$ENDIF}
  169. assign(f,impname);
  170. GetFAttr(f,attr);
  171. If DOSError=0 then
  172. erase(f);
  173. exec(utilsprefix+ar_name,'rs '+impname+' '+path+dirsep+'*.swo');
  174. cleardir(path,'*.sw');
  175. cleardir(path,'*.swo');
  176. {$i-}
  177. RmDir(path);
  178. {$i+}
  179. if ioresult<>0 then;
  180. end;
  181. procedure makeasm(index:cardinal;name:pchar;isData:longbool);
  182. type
  183. tt=array[1..1]of pchar;
  184. pt=^tt;
  185. const
  186. fn_template:array[1..24]of pchar=(
  187. '.section .idata$2',
  188. '.rva .L4',
  189. '.long 0,0',
  190. '.rva ',
  191. '.rva .L5',
  192. '.section .idata$4',
  193. '.L4:',
  194. '.rva .L6',
  195. '.long 0',
  196. '.section .idata$5',
  197. '.L5:',
  198. '.text',
  199. '.globl ',
  200. ':',
  201. 'jmp *.L7',
  202. '.balign 4,144',
  203. '.section .idata$5',
  204. '.L7:',
  205. '.rva .L6',
  206. '.long 0',
  207. '.section .idata$6',
  208. '.L6:',
  209. '.short 0',
  210. '.ascii "\000"'
  211. );
  212. var_template:array[1..19]of pchar=(
  213. '.section .idata$2',
  214. '.rva .L7',
  215. '.long 0,0',
  216. '.rva ',
  217. '.rva .L8',
  218. '.section .idata$4',
  219. '.L7:',
  220. '.rva .L9',
  221. '.long 0',
  222. '.section .idata$5',
  223. '.L8:',
  224. '.globl ',
  225. ':',
  226. '.rva .L9',
  227. '.long 0',
  228. '.section .idata$6',
  229. '.L9:',
  230. '.short 0',
  231. '.ascii "\000"'
  232. );
  233. __template:array[longbool]of pointer=(@fn_template,@var_template);
  234. common_part:array[1..5]of pchar=(
  235. '.balign 2,0',
  236. '.section .idata$7',
  237. '.globl ',
  238. ':',
  239. '.ascii "\000"'
  240. );
  241. posit:array[longbool,1..4]of longint=((4,13,14,24),(4,12,13,19));
  242. var
  243. template:array[longbool]of pt absolute __template;
  244. f:text;
  245. s:string;
  246. i:longint;
  247. n:string;
  248. common_name,asmout:string;
  249. __d:dirstr;
  250. __n:namestr;
  251. __x:extstr;
  252. begin
  253. if not common_created then
  254. begin
  255. common_name:='_$'+_n+'@common';
  256. asmout:=path+dirsep+'0.sw';
  257. assign(f,asmout);
  258. rewrite(f);
  259. for i:=1 to 5 do
  260. begin
  261. s:=StrPas(Common_part[i]);
  262. case i of
  263. 3:
  264. s:=s+common_name;
  265. 4:
  266. s:=common_name+s;
  267. 5:
  268. begin
  269. fsplit(lname,__d,__n,__x);
  270. insert(__n+__x,s,9);
  271. end;
  272. end;
  273. writeln(f,s);
  274. end;
  275. close(f);
  276. call_as(asmout);
  277. common_created:=true;
  278. end;
  279. n:=strpas(name);
  280. str(succ(index):0,s);
  281. asmout:=path+dirsep+s+'.sw';
  282. assign(f,asmout);
  283. rewrite(f);
  284. for i:=1 to posit[isData,4]do
  285. begin
  286. s:=StrPas(template[isData]^[i]);
  287. if i=posit[isData,1]then
  288. s:=s+common_name
  289. else if i=posit[isData,2]then
  290. s:=s+n
  291. else if i=posit[isData,3]then
  292. s:=n+s
  293. else if i=posit[isData,4]then
  294. insert(n,s,9);
  295. writeln(f,s);
  296. end;
  297. close(f);
  298. call_as(asmout);
  299. end;
  300. procedure ProcessEdata;
  301. type
  302. a8=array[0..7]of char;
  303. function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
  304. var
  305. i:cardinal;
  306. LocObjOfs:cardinal;
  307. LocObj:TObjInfo;
  308. begin
  309. GetSectionName:='';
  310. Flags:=0;
  311. LocObjOfs:=APE_OptSize+PEoffset+24;
  312. for i:=1 to APE_obj do
  313. begin
  314. seek(f,LocObjOfs);
  315. blockread(f,LocObj,sizeof(LocObj));
  316. if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
  317. begin
  318. GetSectionName:=a8(LocObj.ObjName);
  319. Flags:=LocObj.flags;
  320. end;
  321. end;
  322. end;
  323. var
  324. j,Fl:cardinal;
  325. ulongval,procEntry:cardinal;
  326. Ordinal:word;
  327. isData:longbool;
  328. ExpDir:packed record
  329. flag,
  330. stamp:cardinal;
  331. Major,
  332. Minor:word;
  333. Name,
  334. Base,
  335. NumFuncs,
  336. NumNames,
  337. AddrFuncs,
  338. AddrNames,
  339. AddrOrds:cardinal;
  340. end;
  341. begin
  342. with Obj do
  343. begin
  344. seek(f,RawOffset+delta);
  345. blockread(f,ExpDir,sizeof(ExpDir));
  346. fsplit(impname,_d,_n,_e);
  347. path:=_d+_n+'.ils';
  348. {$IFDEF STANDALONE}
  349. if impname<>'' then
  350. {$ENDIF}
  351. CreateTempDir(path);
  352. Common_created:=false;
  353. for j:=0 to pred(ExpDir.NumNames)do
  354. begin
  355. seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
  356. blockread(f,Ordinal,2);
  357. seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+Cardinal(Ordinal*4));
  358. blockread(f,ProcEntry,4);
  359. seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
  360. blockread(f,ulongval,4);
  361. seek(f,RawOffset-VirtAddr+ulongval);
  362. blockread(f,cstring,sizeof(cstring));
  363. {$IFDEF STANDALONE}
  364. if not FileCreated then
  365. begin
  366. FileCreated:=true;
  367. if(__textname<>'')or(impname='')then
  368. begin
  369. rewrite(t);
  370. writeln(t,'EXPORTS');
  371. end;
  372. end;
  373. {$ENDIF}
  374. isData:=GetSectionName(procentry,Fl)='';
  375. if not isData then
  376. isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
  377. {$IFDEF STANDALONE}
  378. if(__textname<>'')or(impname='')then
  379. writeln(t,cstring,' @',succ(ordinal):0,' ',kind[isData]);
  380. if impname<>''then
  381. {$ENDIF}
  382. makeasm(j,cstring,isData);
  383. end;
  384. call_ar;
  385. end;
  386. end;
  387. begin
  388. GetEdata:=false;
  389. {$IFDEF STANDALONE}
  390. FileCreated:=false;
  391. {$ENDIF}
  392. seek(f,PE+120);
  393. blockread(f,ExportRVA,4);
  394. seek(f,PE+6);
  395. blockread(f,APE_Obj,2);
  396. seek(f,PE+20);
  397. blockread(f,APE_OptSize,2);
  398. ObjOfs:=APE_OptSize+PEoffset+24;
  399. for i:=1 to APE_obj do
  400. begin
  401. seek(f,ObjOfs);
  402. blockread(f,Obj,sizeof(Obj));
  403. inc(ObjOfs,sizeof(Obj));
  404. with Obj do
  405. if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
  406. begin
  407. delta:=ExportRva-VirtAddr;
  408. ProcessEdata;
  409. GetEdata:=true;
  410. end;
  411. end;
  412. end;
  413. function makedef(const binname,
  414. {$IFDEF STANDALONE}
  415. textname,
  416. {$ENDIF}
  417. libname:string):longbool;
  418. var
  419. OldFileMode:longint;
  420. begin
  421. assign(f,binname);
  422. {$IFDEF STANDALONE}
  423. FileCreated:=false;
  424. assign(t,textname);
  425. __textname:=textname;
  426. {$ENDIF}
  427. impname:=libname;
  428. lname:=binname;
  429. OldFileMode:=filemode;
  430. {$I-}
  431. filemode:=0;
  432. reset(f,1);
  433. filemode:=OldFileMode;
  434. {$I+}
  435. if IOResult<>0 then
  436. begin
  437. makedef:=false;
  438. exit;
  439. end;
  440. if not DOSstubOK(PEoffset)then
  441. makedef:=false
  442. else if not IsPE(PEoffset)then
  443. makedef:=false
  444. else
  445. makedef:=GetEdata(PEoffset);
  446. close(f);
  447. {$IFDEF STANDALONE}
  448. if FileCreated then
  449. if(textname<>'')or(impname='')then
  450. close(t);
  451. {$ENDIF}
  452. end;
  453. end.
  454. {
  455. $Log$
  456. Revision 1.12 2003-10-03 14:16:48 marco
  457. * -XP<prefix> support
  458. Revision 1.11 2003/10/02 21:17:08 peter
  459. * use as,ld,ar instead of asw,ldw,arw for win32
  460. Revision 1.10 2002/10/05 12:43:24 carl
  461. * fixes for Delphi 6 compilation
  462. (warning : Some features do not work under Delphi)
  463. Revision 1.9 2002/05/18 13:34:08 peter
  464. * readded missing revisions
  465. Revision 1.8 2002/05/16 19:46:37 carl
  466. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  467. + try to fix temp allocation (still in ifdef)
  468. + generic constructor calls
  469. + start of tassembler / tmodulebase class cleanup
  470. }