impdef.pas 9.8 KB

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