2
0

impdef.pas 9.5 KB

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