2
0

impdef.pas 9.5 KB

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