PCOFPE.Mod 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816
  1. (* Aos Runtime: PE object file plug-in, Copyright 2004, Emil J. Zeller, ETH Zürich *)
  2. (* Paco, Copyright 2000 - 2002, Patrik Reali, ETH Zurich *)
  3. MODULE PCOFPE; (** AUTHOR "ejz"; PURPOSE "Parallel Compiler: PE object file plug-in"; *)
  4. IMPORT SYSTEM, KernelLog, StringPool, PCDebug, PCBT, PCLIR, PCM, PCT, PCOM, Dates, Strings, Streams, Files, Clock, Diagnostics;
  5. CONST
  6. Loader = "AosRuntime"; Heap = "AosRuntime"; Active = "Objects";
  7. ImageDosSignature = 05A4DH; (* MZ *)
  8. ImageNtSignature = 000004550H; (* PE00 *)
  9. EXEImageBase = 0400000H; DLLImageBase = 010000000H;
  10. ImageSubsystemUnknown = 0;
  11. ImageSubsystemNative = 1;
  12. ImageSubsystemWindowsGui = 2;
  13. ImageSubsystemWindowsCui = 3;
  14. ImageNumberOfDirectoryEntries = 16;
  15. ImageFileRelocsStripped = 0;
  16. ImageFileExecutableImage = 1;
  17. ImageFileLineNumsStripped = 2;
  18. ImageFileLocalSymsStripped = 3;
  19. ImageFile32BitMachine = 8;
  20. ImageFileDll = 13;
  21. ImageFileMachineI386 = 014CH;
  22. ImageOptionalMagic = 010BH;
  23. MajorLinkerVersion = 0X; MinorLinkerVersion = 0X;
  24. ImageSizeOfShortName = 8;
  25. ImageScnCntCode = 5;
  26. ImageScnCntInitializedData = 6;
  27. ImageScnMemDiscardable = 25;
  28. ImageScnMemExecute = 29;
  29. ImageScnMemRead = 30;
  30. ImageScnMemWrite = 31;
  31. PageSize = 01000H; SectorSize = 0200H;
  32. DefaultFileAlign = SectorSize; DefaultSectionAlign = PageSize;
  33. BaseRVA = DefaultSectionAlign;
  34. DefaultHeapSize = 64*1024; DefaultStackSize = 1024*1024;
  35. ImageDirectoryEntryExport = 0;
  36. ImageDirectoryEntryImport = 1;
  37. ImageDirectoryEntryBasereloc = 5;
  38. ImageDirectoryEntryIAT = 12;
  39. ImageRelBasedHighLow = 3;
  40. ModeDef = 0; ModeDLL = 1; ModeEXE = 2;
  41. EUEnd = 0X; EURecord = 1X; EUProcFlag = LONGINT(080000000H);
  42. TYPE
  43. ImageFileHeader = RECORD
  44. Machine: INTEGER;
  45. NumberOfSections: INTEGER;
  46. TimeDateStamp: LONGINT;
  47. PointerToSymbolTable: LONGINT;
  48. NumberOfSymbols: LONGINT;
  49. SizeOfOptionalHeader: INTEGER;
  50. Characteristics: INTEGER
  51. END;
  52. ImageDataDirectory = RECORD
  53. VirtualAddress, Size: LONGINT
  54. END;
  55. ImageOptionalHeader = RECORD
  56. Magic: INTEGER;
  57. MajorLinkerVersion, MinorLinkerVersion: CHAR;
  58. SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData,
  59. AddressOfEntryPoint,
  60. BaseOfCode, BaseOfData, ImageBase,
  61. SectionAlignment, FileAlignment: LONGINT;
  62. MajorOperatingSystemVersion, MinorOperatingSystemVersion,
  63. MajorImageVersion, MinorImageVersion,
  64. MajorSubsystemVersion, MinorSubsystemVersion: INTEGER;
  65. Win32VersionValue,
  66. SizeOfImage, SizeOfHeaders,
  67. CheckSum: LONGINT;
  68. Subsystem,
  69. DllCharacteristics: INTEGER;
  70. SizeOfStackReserve, SizeOfStackCommit,
  71. SizeOfHeapReserve, SizeOfHeapCommit,
  72. LoaderFlags, NumberOfRvaAndSizes: LONGINT;
  73. DataDirectory: ARRAY ImageNumberOfDirectoryEntries OF ImageDataDirectory
  74. END;
  75. ImageSectionHeader = RECORD
  76. Name: ARRAY ImageSizeOfShortName OF CHAR;
  77. VirtualSize: LONGINT;
  78. VirtualAddress: LONGINT;
  79. SizeOfRawData: LONGINT;
  80. PointerToRawData: LONGINT;
  81. PointerToRelocations: LONGINT;
  82. PointerToLinenumbers: LONGINT;
  83. NumberOfRelocations: INTEGER;
  84. NumberOfLinenumbers: INTEGER;
  85. Characteristics: SET
  86. END;
  87. ImageExportDirectory = RECORD
  88. Characteristics, TimeDateStamp: LONGINT;
  89. MajorVersion, MinorVersion: INTEGER;
  90. Name, Base, NumberOfFunctions, NumberOfNames,
  91. AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals: LONGINT
  92. END;
  93. ImageImportDescriptor = RECORD
  94. Characteristics, TimeDateStamp, ForwarderChain, Name, FirstThunk: LONGINT
  95. END;
  96. Bytes = POINTER TO ARRAY OF CHAR;
  97. Name = ARRAY 256 OF CHAR;
  98. ExportFPList = POINTER TO ARRAY OF LONGINT;
  99. SectionReader = OBJECT (Streams.Reader)
  100. VAR sect: Section; org, ofs: LONGINT;
  101. PROCEDURE Receive(VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
  102. BEGIN
  103. len := sect.used - SELF.ofs;
  104. IF len > 0 THEN
  105. IF len > size THEN len := size END;
  106. SYSTEM.MOVE(ADDRESSOF(sect.data[SELF.ofs]), ADDRESSOF(buf[ofs]), len);
  107. INC(SELF.ofs, len)
  108. END;
  109. IF len < min THEN
  110. res := Streams.EOF
  111. ELSE
  112. res := Streams.Ok
  113. END
  114. END Receive;
  115. PROCEDURE Pos*(): Streams.Position;
  116. BEGIN
  117. RETURN org + Pos^()
  118. END Pos;
  119. PROCEDURE SetPos*(ofs: Streams.Position);
  120. BEGIN
  121. Reset();
  122. SELF.org := ofs; SELF.ofs := ofs
  123. END SetPos;
  124. PROCEDURE &Open*(sect: Section; ofs: LONGINT);
  125. BEGIN
  126. InitReader(SELF.Receive, 4); (* is only used for small fixups *)
  127. SELF.sect := sect; SELF.org := ofs; SELF.ofs := ofs
  128. END Open;
  129. END SectionReader;
  130. SectionWriter = OBJECT (Streams.Writer)
  131. VAR sect: Section; org, ofs: LONGINT;
  132. PROCEDURE Send(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  133. BEGIN
  134. res := Streams.Ok; IF len <= 0 THEN RETURN END;
  135. IF (SELF.ofs + len) > sect.len THEN sect.Resize(SELF.ofs + len) END;
  136. SYSTEM.MOVE(ADDRESSOF(buf[ofs]), ADDRESSOF(sect.data[SELF.ofs]), len);
  137. INC(SELF.ofs, len);
  138. IF SELF.ofs > sect.used THEN sect.used := SELF.ofs END
  139. END Send;
  140. PROCEDURE Pos*(): Streams.Position;
  141. BEGIN
  142. RETURN org + Pos^()
  143. END Pos;
  144. PROCEDURE SetPos*(ofs: Streams.Position);
  145. BEGIN
  146. Update(); Reset();
  147. SELF.org := ofs; SELF.ofs := ofs
  148. END SetPos;
  149. PROCEDURE &Open*(sect: Section; ofs: LONGINT);
  150. BEGIN
  151. InitWriter(SELF.Send, PageSize);
  152. SELF.sect := sect; SELF.org := ofs; SELF.ofs := ofs
  153. END Open;
  154. END SectionWriter;
  155. Section = OBJECT
  156. VAR
  157. head: ImageSectionHeader;
  158. data: Bytes; len, used: LONGINT;
  159. imports: ImportReloc; relocs: BaseReloc;
  160. W: SectionWriter; R: SectionReader;
  161. next: Section;
  162. PROCEDURE Resize(min: LONGINT);
  163. VAR data: Bytes; i: LONGINT;
  164. BEGIN
  165. ASSERT(min > len);
  166. min := Align(min, PageSize); NEW(data, min); i := len;
  167. IF i > 0 THEN
  168. SYSTEM.MOVE(ADDRESSOF(SELF.data[0]), ADDRESSOF(data[0]), i)
  169. END;
  170. WHILE i < min DO data[i] := 0X; INC(i) END;
  171. SELF.data := data; len := min
  172. END Resize;
  173. PROCEDURE SetBase(VAR base: LONGINT);
  174. VAR s: SET;
  175. BEGIN
  176. SELF.head.VirtualAddress := base;
  177. s := SYSTEM.VAL(SET, SELF.head.Characteristics);
  178. IF (ImageScnCntCode IN s) OR (ImageScnCntInitializedData IN s) THEN
  179. SELF.head.VirtualSize := SELF.used
  180. ELSE
  181. ASSERT(SELF.head.VirtualSize > 0)
  182. END;
  183. INC(base, Align(SELF.head.VirtualSize, DefaultSectionAlign))
  184. END SetBase;
  185. PROCEDURE &New*(pe: PEModule; name: ARRAY OF CHAR; chars: SET);
  186. VAR p, s: Section;
  187. BEGIN
  188. SELF.W := NIL; SELF.R := NIL;
  189. SELF.next := NIL;
  190. p := NIL; s := pe.sects;
  191. WHILE s # NIL DO
  192. p := s; s := s.next
  193. END;
  194. IF p # NIL THEN
  195. p.next := SELF
  196. ELSE
  197. pe.sects := SELF
  198. END;
  199. INC(pe.fileHdr.NumberOfSections);
  200. SELF.data := NIL; SELF.used := 0; SELF.len := 0;
  201. COPY(name, SELF.head.Name); SELF.head.Characteristics := chars;
  202. SELF.head.VirtualSize := 0; SELF.head.VirtualAddress := 0;
  203. SELF.head.SizeOfRawData := 0; SELF.head.PointerToRawData := 0;
  204. SELF.head.NumberOfRelocations := 0; SELF.head.PointerToRelocations := 0;
  205. SELF.head.NumberOfLinenumbers := 0; SELF.head.PointerToLinenumbers := 0;
  206. SELF.imports := NIL; SELF.relocs := NIL;
  207. NEW(W, SELF, 0); NEW(R, SELF, 0)
  208. END New;
  209. END Section;
  210. BaseReloc = POINTER TO RECORD
  211. ofs: LONGINT; base: Section;
  212. next: BaseReloc
  213. END;
  214. ImportMod = POINTER TO RECORD
  215. desc: ImageImportDescriptor;
  216. name: Name; objs: ImportObj;
  217. next: ImportMod
  218. END;
  219. ImportObj = POINTER TO RECORD
  220. name: Name; next: ImportObj;
  221. iat: LONGINT
  222. END;
  223. ImportReloc = POINTER TO RECORD
  224. ofs: LONGINT; obj: ImportObj;
  225. next: ImportReloc;
  226. iat, abs, uofs: BOOLEAN
  227. END;
  228. ExportObj = POINTER TO RECORD
  229. name: Name;
  230. sect: Section; ofs: LONGINT;
  231. next: ExportObj
  232. END;
  233. PEModule = OBJECT
  234. VAR
  235. name: Files.FileName;
  236. mod: PCT.Module; adr: PCBT.Module;
  237. codearr: PCLIR.CodeArray; hdrCodeSize, addressFactor: LONGINT;
  238. fileHdr: ImageFileHeader; optHdr: ImageOptionalHeader;
  239. sects, type, var, const, code, idata, edata, reloc: Section;
  240. exports: ExportObj; imports: ImportMod;
  241. explist: ExportFPList; exppos, explen, nofstr, nofImp, count: LONGINT;
  242. desc: RECORD
  243. modules, commands, methods, pointers, exports, imports, types: LONGINT;
  244. iatfix: LONGINT
  245. END;
  246. PROCEDURE AddImportMod(name: ARRAY OF CHAR): ImportMod;
  247. VAR mod: ImportMod;
  248. BEGIN
  249. mod := imports;
  250. WHILE (mod # NIL) & (mod.name # name) DO
  251. mod := mod.next
  252. END;
  253. IF mod = NIL THEN
  254. NEW(mod); COPY(name, mod.name); mod.objs := NIL;
  255. mod.desc.Characteristics := 0; mod.desc.TimeDateStamp := fileHdr.TimeDateStamp;
  256. mod.desc.ForwarderChain := 0; mod.desc.Name := 0; mod.desc.FirstThunk := 0;
  257. mod.next := imports; imports := mod
  258. END;
  259. RETURN mod
  260. END AddImportMod;
  261. PROCEDURE FixupSysCall(l: PCBT.Fixup; entry: LONGINT);
  262. VAR
  263. rt: ImportMod; name: Name; obj: ImportObj; W: SectionWriter; p: PCT.Proc; offset: LONGINT;
  264. idx: StringPool.Index;
  265. BEGIN
  266. rt := NIL;
  267. CASE entry OF
  268. |246: name := "Unlock"
  269. |247: name := "Lock"
  270. |249: name := "Await"
  271. |250: name := "CreateProcess"
  272. |251: name := "NewArr"
  273. |252: name := "NewSys"
  274. |253: name := "NewRec"
  275. ELSE
  276. HALT(99)
  277. END;
  278. IF (entry >= 246) & (entry <= 250) & (SELF.name # Active) THEN
  279. rt := AddImportMod(Active)
  280. END;
  281. IF (entry >= 251) & (entry <= 253) & (SELF.name # Heap) THEN
  282. rt := AddImportMod(Heap)
  283. END;
  284. IF rt # NIL THEN
  285. obj := AddImportObj(rt, name); p := NIL
  286. ELSE
  287. StringPool.GetIndex(name, idx);
  288. p := mod.scope.firstProc;
  289. WHILE (p # NIL) & (p.name # idx) DO
  290. p := p.nextProc
  291. END;
  292. ASSERT(p # NIL)
  293. END;
  294. W := code.W;
  295. WHILE l # NIL DO
  296. offset := l.offset*addressFactor;
  297. W.SetPos(offset);
  298. IF rt # NIL THEN
  299. AddImportReloc(code, offset, obj, FALSE, FALSE, FALSE);
  300. W.RawLInt(0)
  301. ELSE
  302. W.RawLInt(p.adr(PCBT.Procedure).codeoffset-(offset+4))
  303. END;
  304. l := l.next
  305. END;
  306. W.Update()
  307. END FixupSysCall;
  308. PROCEDURE FixupCase(l: PCBT.Fixup);
  309. VAR offset: LONGINT;
  310. BEGIN
  311. WHILE l # NIL DO
  312. offset := l.offset*addressFactor;
  313. AddOfsReloc(const, offset, code);
  314. l := l.next
  315. END
  316. END FixupCase;
  317. PROCEDURE FixupLinks;
  318. VAR entry, i: LONGINT;
  319. BEGIN
  320. i := 0;
  321. WHILE i < PCBT.NofSysCalls DO
  322. IF adr.syscalls[i] # NIL THEN
  323. entry := ORD(PCLIR.CG.SysCallMap[i]);
  324. CASE entry OF
  325. 246..253: FixupSysCall(adr.syscalls[i], entry)
  326. |255: FixupCase(adr.syscalls[i])
  327. ELSE
  328. HALT(99) (* unknown entry *)
  329. END
  330. END;
  331. INC(i)
  332. END
  333. END FixupLinks;
  334. PROCEDURE TypeAlign4;
  335. VAR W: SectionWriter; n: LONGINT;
  336. BEGIN
  337. n := type.used MOD 4;
  338. IF n # 0 THEN
  339. W := type.W; W.SetPos(type.used);
  340. n := 4-n;
  341. WHILE n > 0 DO W.Char(0X); DEC(n) END;
  342. W.Update()
  343. END
  344. END TypeAlign4;
  345. PROCEDURE Commands;
  346. VAR W: SectionWriter; proc: PCT.Proc; name: Name; ofs: LONGINT;
  347. BEGIN
  348. TypeAlign4(); desc.commands := type.used;
  349. (* possible improvment: store only export ordinal, name and address from edata export table *)
  350. W := type.W; W.SetPos(type.used);
  351. proc := mod.scope.firstProc;
  352. WHILE (proc # NIL) DO
  353. IF (proc.vis = PCT.Public) & ~(PCT.Inline IN proc.flags) THEN
  354. ofs := proc.adr(PCBT.Procedure).codeoffset;
  355. IF (proc.scope.firstPar = NIL) & (proc.type = PCT.NoType) THEN
  356. StringPool.GetString(proc.name, name);
  357. W.Bytes(name, 0, 32);
  358. AddOfsReloc(type, W.Pos(), code);
  359. W.RawLInt(ofs); W.RawLInt(0)
  360. ELSIF (proc.scope.firstPar # NIL) & (proc.scope.firstPar.nextPar = NIL) & (proc.scope.firstPar.type = PCT.Ptr) & (proc.type = PCT.Ptr) THEN
  361. StringPool.GetString(proc.name, name);
  362. W.Bytes(name, 0, 32);
  363. AddOfsReloc(type, W.Pos()+4, code);
  364. W.RawLInt(0); W.RawLInt(ofs)
  365. END
  366. END;
  367. proc := proc.nextProc
  368. END;
  369. name := "";
  370. W.Bytes(name, 0, 32); (* sentinel *)
  371. W.RawLInt(0); W.RawLInt(0);
  372. W.Update()
  373. END Commands;
  374. PROCEDURE UseModule(m: PCBT.Module);
  375. BEGIN
  376. IF m.nr = 0 THEN INC(nofImp); m.nr := -1 END
  377. END UseModule;
  378. PROCEDURE UseModules;
  379. VAR
  380. o: PCT.Symbol; p: PCBT.GlobalVariable; rec: PCT.Record; bsym: PCOM.Struct; i, j: LONGINT;
  381. m: PCT.Module; adr: PCBT.Module; name: Name; im: ImportMod; W: SectionWriter;
  382. BEGIN
  383. TypeAlign4(); desc.modules := type.used;
  384. W := type.W; W.SetPos(type.used);
  385. (* detect imported modules *)
  386. IF mod.imports = NIL THEN W.RawLInt(0); W.Update(); RETURN END;
  387. i := 0;
  388. WHILE (i < LEN(mod.imports)) & (mod.imports[i] # NIL) DO
  389. mod.imports[i].adr(PCBT.Module).nr := 0;
  390. INC(i)
  391. END;
  392. nofImp := 0;
  393. o := mod.scope.sorted;
  394. WHILE o # NIL DO
  395. IF (o IS PCT.Module) & (o.adr # PCT.System.adr) THEN UseModule(o.adr(PCBT.Module)) END;
  396. o := o.sorted;
  397. END;
  398. p := SELF.adr.ExtVars;
  399. WHILE p # PCBT.sentinel DO
  400. IF p.link # NIL THEN UseModule(p.owner) END;
  401. p := p.next
  402. END;
  403. rec := mod.scope.records;
  404. WHILE rec # NIL DO
  405. IF (rec.brec # NIL) & (rec.brec.sym # NIL) THEN
  406. bsym := rec.brec.sym(PCOM.Struct);
  407. IF bsym.mod # mod.scope.owner THEN UseModule(bsym.mod.adr(PCBT.Module)) END
  408. END;
  409. rec := rec.link
  410. END;
  411. W.RawLInt(nofImp);
  412. i := 0; j := 0;
  413. WHILE (i < LEN(mod.imports)) & (mod.imports[i] # NIL) DO
  414. m := mod.imports[i];
  415. adr := m.adr(PCBT.Module);
  416. IF adr.nr = -1 THEN
  417. INC(j); adr.nr := SHORT(j);
  418. StringPool.GetString(m.name, name);
  419. W.RawString(name);
  420. im := AddImportMod(name)
  421. END;
  422. INC(i)
  423. END;
  424. W.Update()
  425. END UseModules;
  426. PROCEDURE FixupProc(p: PCBT.Procedure);
  427. VAR W: SectionWriter; l: PCBT.Fixup; offset: LONGINT;
  428. BEGIN
  429. W := code.W; l := p.link;
  430. WHILE l # NIL DO
  431. offset := l.offset*addressFactor;
  432. ASSERT(code.data[offset-1] # 0E8X);
  433. AddOfsReloc(code, offset, code);
  434. W.SetPos(offset); W.RawLInt(p.codeoffset);
  435. l := l.next
  436. END;
  437. W.Update()
  438. END FixupProc;
  439. PROCEDURE FixupOwnProcs;
  440. VAR W: SectionWriter; p: PCBT.Procedure; nofMethods: LONGINT;
  441. BEGIN
  442. TypeAlign4(); desc.methods := type.used;
  443. W := type.W; W.SetPos(type.used);
  444. nofMethods := 0;
  445. p := adr.OwnProcs;
  446. WHILE p # PCBT.psentinel DO
  447. IF (p.public) OR (p.link # NIL) OR (p IS PCBT.Method) THEN
  448. IF p IS PCBT.Method THEN
  449. p.entryNr := nofMethods; INC(nofMethods);
  450. AddOfsReloc(type, W.Pos(), code);
  451. W.RawLInt(p.codeoffset)
  452. END;
  453. IF p.link # NIL THEN FixupProc(p) END
  454. END;
  455. p := p.next
  456. END;
  457. W.RawLInt(0); (* sentinel *)
  458. W.Update()
  459. END FixupOwnProcs;
  460. PROCEDURE PtrAdr(W: SectionWriter; offset: LONGINT; type: PCT.Struct; fixadr: BOOLEAN);
  461. VAR i, n, off: LONGINT; f: PCT.Variable; scope: PCT.Scope; base: PCT.Struct; size: PCBT.Size;
  462. BEGIN
  463. IF ~type.size(PCBT.Size).containPtrs THEN RETURN END;
  464. IF PCT.IsPointer(type) THEN
  465. IF fixadr THEN AddOfsReloc(SELF.type, W.Pos(), var) END;
  466. W.RawLInt(offset)
  467. ELSIF (type IS PCT.Delegate) & ~(PCT.StaticMethodsOnly IN type.flags) THEN
  468. IF fixadr THEN AddOfsReloc(SELF.type, W.Pos(), var) END;
  469. W.RawLInt(offset+4)
  470. ELSIF type IS PCT.Record THEN
  471. WITH type: PCT.Record DO
  472. IF type.brec # NIL THEN PtrAdr(W, offset, type.brec, fixadr) END;
  473. scope := type.scope;
  474. END;
  475. f := scope.firstVar;
  476. WHILE f # NIL DO
  477. IF ~(PCM.Untraced IN f.flags) THEN
  478. ASSERT(scope.state >= PCT.structallocated);
  479. type := f.type; off := f.adr(PCBT.Variable).offset;
  480. PtrAdr(W, offset+off, type, fixadr)
  481. END;
  482. f := f.nextVar
  483. END
  484. ELSIF type IS PCT.Array THEN
  485. WITH type: PCT.Array DO
  486. IF type.mode = PCT.static THEN
  487. n := type.len;
  488. base := type.base;
  489. WHILE (base IS PCT.Array) DO
  490. type := base(PCT.Array); base := type.base;
  491. ASSERT(type.mode = PCT.static);
  492. n := n * type.len
  493. END;
  494. size := base.size(PCBT.Size);
  495. IF size.containPtrs THEN
  496. FOR i := 0 TO n-1 DO PtrAdr(W, offset+i*size.size, base, fixadr) END
  497. END
  498. ELSE
  499. PCDebug.ToDo(PCDebug.NotImplemented); (*find pointers in the array, call NewPtr for each one*)
  500. END
  501. END
  502. END
  503. END PtrAdr;
  504. PROCEDURE Pointers;
  505. VAR W: SectionWriter; p: PCT.Variable;
  506. BEGIN
  507. TypeAlign4(); desc.pointers := type.used;
  508. W := type.W; W.SetPos(type.used);
  509. p := mod.scope.firstVar;
  510. WHILE p # NIL DO
  511. IF ~(PCM.Untraced IN p.flags) THEN
  512. PtrAdr(W, var.head.VirtualSize + p.adr(PCBT.GlobalVariable).offset, p.type, TRUE)
  513. END;
  514. p := p.nextVar
  515. END;
  516. W.RawLInt(0); (* sentinel *)
  517. W.Update()
  518. END Pointers;
  519. PROCEDURE FixupVar(p: PCBT.GlobalVariable);
  520. VAR W: SectionWriter; R: SectionReader; l: PCBT.Fixup; offset, x: LONGINT;
  521. BEGIN
  522. W := code.W; R := code.R; l := p.link;
  523. WHILE l # NIL DO
  524. offset := l.offset*addressFactor;
  525. R.SetPos(offset); R.RawLInt(x);
  526. W.SetPos(offset);
  527. IF p.offset < 0 THEN (* var *)
  528. AddOfsReloc(code, offset, var);
  529. W.RawLInt(var.head.VirtualSize + x)
  530. ELSE (* const *)
  531. AddOfsReloc(code, offset, const);
  532. W.RawLInt(x)
  533. END;
  534. l := l.next
  535. END;
  536. W.Update()
  537. END FixupVar;
  538. PROCEDURE FixupOwnVars;
  539. VAR p: PCBT.GlobalVariable;
  540. BEGIN
  541. p := adr.OwnVars;
  542. WHILE p # PCBT.sentinel DO
  543. IF p.link # NIL THEN FixupVar(p) END;
  544. ASSERT(p.entryNo = PCBT.UndefEntryNo);
  545. p := p.next
  546. END
  547. END FixupOwnVars;
  548. PROCEDURE AddExport(sect: Section; ofs: LONGINT; name: ARRAY OF CHAR);
  549. VAR p, n, e: ExportObj;
  550. BEGIN
  551. p := NIL; n := exports;
  552. WHILE (n # NIL) & (n.name < name) DO
  553. p := n; n := n.next
  554. END;
  555. IF (n = NIL) OR (n.name > name) THEN
  556. NEW(e); COPY(name, e.name);
  557. e.sect := sect; e.ofs := ofs;
  558. e.next := n;
  559. IF p # NIL THEN
  560. p.next := e
  561. ELSE
  562. exports := e
  563. END
  564. ELSE
  565. HALT(99)
  566. END
  567. END AddExport;
  568. PROCEDURE ExportType(W: SectionWriter; t: PCT.Struct);
  569. VAR sym: PCOM.Struct; p: PCT.Proc; v: PCT.Variable; count, pos, bak: LONGINT;
  570. BEGIN
  571. WHILE (t IS PCT.Pointer) OR (t IS PCT.Array) DO
  572. IF t IS PCT.Pointer THEN t := t(PCT.Pointer).base ELSE t := t(PCT.Array).base END
  573. END;
  574. sym := t.sym(PCOM.Struct);
  575. IF (t IS PCT.Record) & ((sym.mod = NIL) OR (sym.mod = mod)) THEN
  576. WITH t: PCT.Record DO
  577. W.Char(EURecord);
  578. IF sym.uref # 0 THEN
  579. W.RawNum(-sym.uref)
  580. ELSE
  581. count := 0;
  582. INC(nofstr); sym.uref := nofstr; (*remember it's exported*)
  583. W.RawNum(t.size(PCBT.RecSize).td.offset); (* link address in the constant section*)
  584. pos := W.Pos(); W.RawInt(2); (* number of entries *)
  585. ExportType(W, t.btyp);
  586. W.RawNum(sym.pbfp); W.RawNum(sym.pvfp);
  587. v := t.scope.firstVar;
  588. WHILE p # NIL DO
  589. IF v.vis # PCT.Internal THEN
  590. W.RawNum(v.sym(PCOM.Symbol).fp); ExportType(W, v.type); INC(count)
  591. END;
  592. v := v.nextVar
  593. END;
  594. p := t.scope.firstProc;
  595. WHILE p # NIL DO
  596. IF (p.vis # PCT.Internal) & (p # t.scope.body) THEN
  597. W.RawNum(p.sym(PCOM.Symbol).fp); INC(count)
  598. END;
  599. p := p.nextProc
  600. END;
  601. IF count # 0 THEN
  602. bak := W.Pos(); W.SetPos(pos);
  603. W.RawInt(SHORT(count+2));
  604. W.SetPos(bak)
  605. END;
  606. W.Char(EUEnd)
  607. END
  608. END
  609. END
  610. END ExportType;
  611. PROCEDURE ExportSymbol(W: SectionWriter; p: PCT.Symbol; sect: Section; ofs: LONGINT);
  612. VAR i, fp: LONGINT; name: Name; explist2: ExportFPList;
  613. BEGIN
  614. StringPool.GetString(p.name, name);
  615. fp := p.sym(PCOM.Symbol).fp;
  616. FOR i := 0 TO exppos-1 DO
  617. IF fp = explist[i] THEN PCM.ErrorN(280, Diagnostics.Invalid, p.name) END
  618. END;
  619. IF exppos >= explen THEN
  620. NEW(explist2, 2*explen);
  621. SYSTEM.MOVE(ADDRESSOF(explist[0]), ADDRESSOF(explist2[0]), 4*explen);
  622. explist := explist2; explen := 2*explen
  623. END;
  624. explist[exppos] := fp; INC(exppos);
  625. IF sect # NIL THEN AddExport(sect, ofs, name) END;
  626. W.RawNum(fp); W.RawNum(ofs);
  627. INC(count)
  628. END ExportSymbol;
  629. PROCEDURE ExportConsts(W: SectionWriter);
  630. VAR c: PCT.Value;
  631. BEGIN
  632. c := mod.scope.firstValue;
  633. WHILE c # NIL DO
  634. IF c.vis # PCT.Internal THEN
  635. IF (c.adr # NIL) & (c.adr IS PCBT.GlobalVariable) THEN
  636. ExportSymbol(W, c, const, c.adr(PCBT.GlobalVariable).offset)
  637. ELSE
  638. ExportSymbol(W, c, NIL, 0)
  639. END
  640. END;
  641. c := c.nextVal
  642. END
  643. END ExportConsts;
  644. PROCEDURE ExportVars(W: SectionWriter);
  645. VAR v: PCT.Variable;
  646. BEGIN
  647. v := mod.scope.firstVar;
  648. WHILE v # NIL DO
  649. IF v.vis # PCT.Internal THEN
  650. ExportSymbol(W, v, var, var.head.VirtualSize + v.adr(PCBT.GlobalVariable).offset);
  651. ExportType(W, v.type)
  652. END;
  653. v := v.nextVar
  654. END
  655. END ExportVars;
  656. PROCEDURE ExportTypes(W: SectionWriter);
  657. VAR t: PCT.Type;
  658. BEGIN
  659. t := mod.scope.firstType;
  660. WHILE t # NIL DO
  661. IF t.vis # PCT.Internal THEN
  662. ExportSymbol(W, t, NIL, 0);
  663. ExportType(W, t.type)
  664. END;
  665. t := t.nextType
  666. END
  667. END ExportTypes;
  668. PROCEDURE ExportProcs(W: SectionWriter);
  669. VAR p: PCT.Proc;
  670. BEGIN
  671. p := mod.scope.firstProc;
  672. WHILE p # NIL DO
  673. IF p.vis # PCT.Internal THEN
  674. ExportSymbol(W, p, code, p.adr(PCBT.Procedure).codeoffset);
  675. END;
  676. p := p.nextProc
  677. END
  678. END ExportProcs;
  679. PROCEDURE CheckExport(name: ARRAY OF CHAR);
  680. VAR e: ExportObj; idx: StringPool.Index; p: PCT.Proc;
  681. BEGIN
  682. e := exports;
  683. WHILE (e # NIL) & (e.name < name) DO
  684. e := e.next
  685. END;
  686. IF (e # NIL) & (e.name = name) THEN RETURN END;
  687. StringPool.GetIndex(name, idx);
  688. p := mod.scope.firstProc;
  689. WHILE (p # NIL) & (p.name # idx) DO
  690. p := p.nextProc
  691. END;
  692. ASSERT(p # NIL);
  693. AddExport(code, p.adr(PCBT.Procedure).codeoffset, name)
  694. END CheckExport;
  695. PROCEDURE Exports;
  696. VAR W: SectionWriter; i, pos: LONGINT;
  697. BEGIN
  698. TypeAlign4(); desc.exports := type.used;
  699. NEW(explist, 256); exppos := 0; explen := 256;
  700. nofstr := 0; count := 0; pos := type.used;
  701. W := type.W; W.SetPos(pos); W.RawInt(0);
  702. ExportConsts(W);
  703. ExportVars(W);
  704. ExportTypes(W);
  705. ExportProcs(W);
  706. IF count # 0 THEN
  707. i := W.Pos(); W.SetPos(pos);
  708. W.RawInt(SHORT(count));
  709. W.SetPos(i)
  710. END;
  711. W.Char(EUEnd);
  712. W.Update();
  713. IF name = Loader THEN
  714. CheckExport("DllMain"); CheckExport("WinMain")
  715. END;
  716. IF name = Heap THEN
  717. CheckExport("NewArr"); CheckExport("NewSys"); CheckExport("NewRec")
  718. END;
  719. IF name = Active THEN
  720. CheckExport("Unlock"); CheckExport("Lock"); CheckExport("Await"); CheckExport("CreateProcess")
  721. END
  722. END Exports;
  723. PROCEDURE UseEntry(W: SectionWriter; m: PCT.Module; p: PCT.Symbol; offset: LONGINT; imp: ImportMod): ImportObj;
  724. VAR name: Name;
  725. BEGIN
  726. StringPool.GetString(p.name, name);
  727. PCOM.FPrintObj(p, m);
  728. W.RawNum(p.sym(PCOM.Symbol).fp);
  729. W.RawString(name);
  730. W.RawNum(offset);
  731. IF imp # NIL THEN
  732. RETURN AddImportObj(imp, name)
  733. END;
  734. RETURN NIL
  735. END UseEntry;
  736. PROCEDURE UseType(W: SectionWriter; m: PCT.Module; i: LONGINT; t: PCT.Struct);
  737. VAR size: PCBT.RecSize; sym: PCOM.Struct; j: LONGINT;
  738. BEGIN
  739. LOOP
  740. IF t IS PCT.Pointer THEN t := t(PCT.Pointer).base
  741. ELSIF t IS PCT.Array THEN t := t(PCT.Array).base
  742. ELSE EXIT
  743. END
  744. END;
  745. IF ~(t IS PCT.Record) THEN RETURN END;
  746. WITH t: PCT.Record DO
  747. size := t.size(PCBT.RecSize);
  748. IF (size.td # NIL) THEN
  749. IF (t.scope.module = m) THEN
  750. sym := t.sym(PCOM.Struct);
  751. IF (t.owner # NIL) & (t.owner.sym = NIL) THEN PCOM.FPrintObj(t.owner, m) END;
  752. W.Char(EURecord);
  753. W.RawNum(-size.td.offset);
  754. IF t.pvused THEN
  755. W.RawNum(sym.pvfp);
  756. W.RawString("@");
  757. ELSIF t.pbused THEN
  758. W.RawNum(sym.pbfp);
  759. W.RawString("@")
  760. END;
  761. W.Char(EUEnd);
  762. size.td := NIL (*avoid double tracing*)
  763. ELSE
  764. (* aliasing of imported type: schedule module for emission in use list *)
  765. j := i+1;
  766. LOOP
  767. IF j = LEN(mod.imports) THEN
  768. PCT.ExtendModArray(mod.imports);
  769. mod.imports[j] := t.scope.module;
  770. EXIT
  771. ELSIF mod.imports[j] = NIL THEN
  772. mod.imports[j] := t.scope.module;
  773. EXIT
  774. ELSIF mod.imports[j] = t.scope.module THEN
  775. EXIT
  776. END;
  777. INC(j)
  778. END
  779. END
  780. END
  781. END
  782. END UseType;
  783. PROCEDURE ImportConsts(W: SectionWriter; m: PCT.Module);
  784. VAR c: PCT.Value; obj: ImportObj;
  785. BEGIN
  786. c := m.scope.firstValue;
  787. WHILE c # NIL DO
  788. IF (PCT.used IN c.flags) & (c.vis # PCT.Internal) THEN obj := UseEntry(W, m, c, 0, NIL) END;
  789. EXCL(c.flags, PCT.used);
  790. c := c.nextVal
  791. END
  792. END ImportConsts;
  793. PROCEDURE ImportVars(W: SectionWriter; m: PCT.Module; i: LONGINT; imp: ImportMod);
  794. VAR
  795. p: PCBT.GlobalVariable; v: PCT.Variable; e: LONGINT; obj: ImportObj; nofVarCons: INTEGER;
  796. l: PCBT.Fixup; offset: LONGINT; F: SectionWriter;
  797. BEGIN
  798. nofVarCons := 1;
  799. p := adr.ExtVars;
  800. WHILE p # PCBT.sentinel DO
  801. IF p.link # NIL THEN
  802. p.entryNo := nofVarCons; INC(nofVarCons)
  803. END;
  804. p := p.next
  805. END;
  806. v := m.scope.firstVar;
  807. WHILE v # NIL DO
  808. e := v.adr(PCBT.GlobalVariable).entryNo;
  809. IF (e # PCBT.UndefEntryNo) THEN
  810. obj := UseEntry(W, m, v, e, imp); UseType(W, m, i, v.type);
  811. F := code.W;
  812. l := v.adr(PCBT.GlobalVariable).link;
  813. WHILE l # NIL DO
  814. offset := l.offset*addressFactor;
  815. F.SetPos(offset);
  816. AddImportReloc(code, offset, obj, FALSE, TRUE, SYSTEM.GET32(ADDRESSOF(code.data[offset])) # 0);
  817. l := l.next
  818. END;
  819. F.Update()
  820. END;
  821. v := v.nextVar
  822. END
  823. END ImportVars;
  824. PROCEDURE ImportTypes(W: SectionWriter; m: PCT.Module; i: LONGINT);
  825. VAR t: PCT.Type; obj: ImportObj;
  826. BEGIN
  827. t := m.scope.firstType;
  828. WHILE t # NIL DO
  829. IF (PCT.used IN t.flags) & (t.vis # PCT.Internal) THEN
  830. obj := UseEntry(W, m, t, 0, NIL); UseType(W, m, i, t.type)
  831. END;
  832. EXCL(t.flags, PCT.used);
  833. t := t.nextType
  834. END
  835. END ImportTypes;
  836. PROCEDURE ImportProcs(W: SectionWriter; m: PCT.Module; imp: ImportMod);
  837. VAR p: PCT.Proc; obj: ImportObj; l: PCBT.Fixup; offset: LONGINT; F: SectionWriter;
  838. BEGIN
  839. p := m.scope.firstProc;
  840. WHILE p # NIL DO
  841. IF (p.adr # NIL) & (p.adr(PCBT.Procedure).link # NIL) THEN
  842. obj := UseEntry(W, m, p, p.adr(PCBT.Procedure).link.offset + EUProcFlag, imp);
  843. F := code.W;
  844. l := p.adr(PCBT.Procedure).link;
  845. WHILE l # NIL DO
  846. offset := l.offset*addressFactor;
  847. F.SetPos(offset);
  848. IF code.data[offset-1] = 0E8X THEN (* call instruction relative *)
  849. AddImportReloc(code, offset, obj, FALSE, FALSE, FALSE)
  850. ELSE
  851. AddImportReloc(code, offset, obj, FALSE, TRUE, FALSE)
  852. END;
  853. l := l.next
  854. END;
  855. F.Update()
  856. ELSIF (p.flags * {PCT.used, PCT.Inline} = {PCT.used, PCT.Inline}) & (p.vis # PCT.Internal) THEN
  857. obj := UseEntry(W, m, p, 0, NIL)
  858. END;
  859. p := p.nextProc
  860. END
  861. END ImportProcs;
  862. PROCEDURE Imports;
  863. VAR W: SectionWriter; m: PCT.Module; name: Name; i: LONGINT; imp: ImportMod;
  864. BEGIN
  865. TypeAlign4(); desc.imports := type.used;
  866. W := type.W; W.SetPos(type.used);
  867. IF mod.imports = NIL THEN W.Char(0X); W.Update(); RETURN END;
  868. i := 0;
  869. WHILE (i < LEN(mod.imports)) & (mod.imports[i] # NIL) DO
  870. m := mod.imports[i];
  871. ASSERT(m = m.scope.owner);
  872. StringPool.GetString(m.name, name);
  873. imp := AddImportMod(name);
  874. W.RawString(name);
  875. ImportConsts(W, m);
  876. ImportVars(W, m, i, imp);
  877. ImportTypes(W, m, i);
  878. ImportProcs(W, m, imp);
  879. W.Char(0X);
  880. INC(i)
  881. END;
  882. W.Char(0X);
  883. W.Update()
  884. END Imports;
  885. PROCEDURE WriteType(W: SectionWriter; rec: PCT.Record);
  886. VAR
  887. size: PCBT.RecSize; pos, i, oldmth: LONGINT; base: PCT.Record; m: PCT.Method;
  888. adr: PCBT.Method; bsym: PCOM.Struct; name, name2: Name;
  889. basenr: INTEGER; baseid, nofptrs: LONGINT;
  890. BEGIN
  891. PCT.GetTypeName(rec, name);
  892. size := rec.size(PCBT.RecSize);
  893. W.RawLInt(size.size);
  894. W.RawInt(SHORT(size.td.offset));
  895. IF rec.brec = NIL THEN
  896. oldmth := 0;
  897. basenr := -1;
  898. baseid := -1
  899. ELSE
  900. base := rec.brec;
  901. basenr := 0;
  902. IF (base.sym # NIL) THEN
  903. bsym := base.sym(PCOM.Struct);
  904. ASSERT(bsym.mod # NIL);
  905. IF bsym.mod # mod.scope.owner THEN basenr := SHORT(bsym.mod.adr(PCBT.Module).nr) END
  906. END;
  907. IF basenr = 0 THEN
  908. baseid := base.size(PCBT.RecSize).td.offset
  909. ELSIF base.owner = NIL THEN
  910. baseid := base.ptr.owner.sym(PCOM.Symbol).fp
  911. ELSE
  912. StringPool.GetString(base.owner.name, name2);
  913. baseid := base.owner.sym(PCOM.Symbol).fp
  914. END;
  915. oldmth := base.size(PCBT.RecSize).nofMethods;
  916. END;
  917. W.RawInt(basenr);
  918. W.RawLInt(baseid);
  919. W.RawInt(SHORT(size.nofMethods)); (*NofMethods*)
  920. W.RawInt(SHORT(oldmth)); (*InheritedMethods*)
  921. W.RawInt(SHORT(size.nofLocalMethods)); (*NewMethods*)
  922. pos := W.Pos();
  923. W.RawInt(0);
  924. W.RawString(name);
  925. (*New Methods in Record*)
  926. i := 0; m := rec.scope.firstMeth;
  927. WHILE m # NIL DO
  928. adr := m.adr(PCBT.Method);
  929. W.RawInt(SHORT(adr.mthNo));
  930. W.RawInt(SHORT(adr.entryNr));
  931. INC(i);
  932. m := m.nextMeth
  933. END;
  934. ASSERT(i = size.nofLocalMethods, 500); (*sanity check*)
  935. (* Ptrs in Record *)
  936. i := W.Pos();
  937. PtrAdr(W, 0, rec, FALSE);
  938. nofptrs := (W.Pos() - i) DIV 4;
  939. IF nofptrs > MAX(INTEGER) THEN PCM.Error(221, Diagnostics.Invalid, "") END;
  940. IF nofptrs # 0 THEN
  941. i := W.Pos(); W.SetPos(pos);
  942. W.RawInt(SHORT(nofptrs));
  943. W.SetPos(i)
  944. END
  945. END WriteType;
  946. PROCEDURE Types;
  947. VAR W: SectionWriter; rec: PCT.Record;
  948. BEGIN
  949. TypeAlign4(); desc.types := type.used;
  950. W := type.W; W.SetPos(type.used);
  951. W.RawLInt(mod.scope.nofRecs);
  952. rec := mod.scope.records;
  953. WHILE rec # NIL DO
  954. IF PCT.interface IN rec.mode THEN
  955. HALT(99)
  956. ELSE
  957. WriteType(W, rec)
  958. END;
  959. rec := rec.link
  960. END;
  961. rec := mod.scope.records;
  962. WHILE rec # NIL DO
  963. rec.size(PCBT.RecSize).td := NIL;
  964. rec := rec.link
  965. END;
  966. W.Update()
  967. END Types;
  968. PROCEDURE PutName(W: SectionWriter; name: ARRAY OF CHAR);
  969. BEGIN
  970. W.RawString(name);
  971. IF (W.Pos() MOD 2) = 1 THEN W.Char(0X) END
  972. END PutName;
  973. PROCEDURE ModDesc;
  974. VAR W: SectionWriter; sect: Section; r: ImportReloc;
  975. BEGIN
  976. W := type.W; W.SetPos(type.used);
  977. W.RawLInt(0); (* hmod *)
  978. AddOfsReloc(type, W.Pos(), type); (* image base *)
  979. W.RawLInt(-BaseRVA);
  980. AddOfsReloc(type, W.Pos(), type);
  981. W.RawLInt(desc.modules);
  982. AddOfsReloc(type, W.Pos(), type);
  983. W.RawLInt(desc.commands);
  984. AddOfsReloc(type, W.Pos(), type);
  985. W.RawLInt(desc.methods);
  986. AddOfsReloc(type, W.Pos(), type);
  987. W.RawLInt(desc.pointers);
  988. AddOfsReloc(type, W.Pos(), type);
  989. W.RawLInt(desc.exports);
  990. AddOfsReloc(type, W.Pos(), type);
  991. W.RawLInt(desc.imports);
  992. AddOfsReloc(type, W.Pos(), type);
  993. W.RawLInt(desc.types);
  994. IF var # NIL THEN
  995. AddOfsReloc(type, W.Pos(), var)
  996. ELSE
  997. AddOfsReloc(type, W.Pos(), const)
  998. END;
  999. W.RawLInt(0);
  1000. AddOfsReloc(type, W.Pos(), const);
  1001. W.RawLInt(const.used-1);
  1002. AddOfsReloc(type, W.Pos(), code);
  1003. W.RawLInt(0);
  1004. AddOfsReloc(type, W.Pos(), code);
  1005. W.RawLInt(code.used-1);
  1006. AddOfsReloc(type, W.Pos(), const); (* SB *)
  1007. W.RawLInt(0);
  1008. AddOfsReloc(type, W.Pos(), idata);
  1009. W.RawLInt(0);
  1010. AddOfsReloc(type, W.Pos(), edata);
  1011. W.RawLInt(0);
  1012. desc.iatfix := W.Pos();
  1013. sect := sects;
  1014. WHILE sect # NIL DO
  1015. r := sect.imports;
  1016. WHILE r # NIL DO
  1017. IF ~r.iat THEN
  1018. W.RawInt(0); W.RawLInt(0); W.RawLInt(0)
  1019. END;
  1020. r := r.next
  1021. END;
  1022. sect := sect.next
  1023. END;
  1024. W.RawInt(-1); W.RawLInt(0); W.RawLInt(0);
  1025. W.Update()
  1026. END ModDesc;
  1027. PROCEDURE IATFix;
  1028. VAR W: SectionWriter; sect: Section; r: ImportReloc;
  1029. BEGIN
  1030. W := type.W; W.SetPos(desc.iatfix);
  1031. (*
  1032. iat fixup table
  1033. mode code-ofs
  1034. iat address
  1035. mode
  1036. 0: uofs
  1037. 1: abs
  1038. 2: 0 = code / 1 = data
  1039. 15: end
  1040. *)
  1041. sect := sects;
  1042. WHILE sect # NIL DO
  1043. r := sect.imports;
  1044. WHILE r # NIL DO
  1045. IF ~r.iat THEN
  1046. IF sect = code THEN
  1047. IF r.abs THEN
  1048. IF r.uofs THEN
  1049. W.RawInt(3)
  1050. ELSE
  1051. W.RawInt(2)
  1052. END
  1053. ELSE
  1054. ASSERT(~r.uofs);
  1055. W.RawInt(0)
  1056. END;
  1057. AddOfsReloc(type, W.Pos(), code);
  1058. W.RawLInt(r.ofs);
  1059. AddOfsReloc(type, W.Pos(), idata);
  1060. W.RawLInt(r.obj.iat - idata.head.VirtualAddress)
  1061. ELSE
  1062. HALT(99)
  1063. END
  1064. END;
  1065. r := r.next
  1066. END;
  1067. sect := sect.next
  1068. END;
  1069. W.RawInt(-1); W.RawLInt(0); W.RawLInt(0);
  1070. W.Update()
  1071. END IATFix;
  1072. PROCEDURE GenStub;
  1073. VAR
  1074. W: SectionWriter; loader: ImportMod; obj: ImportObj;
  1075. p: PCT.Proc; idx: StringPool.Index; main: ARRAY 8 OF CHAR;
  1076. BEGIN
  1077. optHdr.AddressOfEntryPoint := code.used;
  1078. (* EBX, ESI, EDI are caller saved, EAX & ECX are used for stack init *)
  1079. W := code.W; W.SetPos(code.used);
  1080. W.Char(0BAX); (* MOV EDX, mod *)
  1081. TypeAlign4();
  1082. AddOfsReloc(code, W.Pos(), type);
  1083. W.RawLInt(type.used); (* ModDesc *)
  1084. IF name # Loader THEN
  1085. loader := AddImportMod(Loader);
  1086. W.Char(0FFX); W.Char(025X); (* JMP Main *)
  1087. IF mode = ModeDLL THEN
  1088. obj := AddImportObj(loader, "DllMain")
  1089. ELSIF mode = ModeEXE THEN
  1090. obj := AddImportObj(loader, "WinMain")
  1091. ELSE
  1092. HALT(99)
  1093. END;
  1094. AddImportReloc(code, W.Pos(), obj, TRUE, TRUE, FALSE);
  1095. W.RawLInt(0)
  1096. ELSE
  1097. ASSERT(mode = ModeDLL);
  1098. main := "DllMain";
  1099. StringPool.GetIndex(main, idx);
  1100. p := mod.scope.firstProc;
  1101. WHILE (p # NIL) & (p.name # idx) DO
  1102. p := p.nextProc
  1103. END;
  1104. ASSERT(p # NIL);
  1105. W.Char(0E9X); (* JMP Main *)
  1106. W.RawLInt(p.adr(PCBT.Procedure).codeoffset-(W.Pos()+4))
  1107. END;
  1108. W.Update();
  1109. ModDesc()
  1110. END GenStub;
  1111. PROCEDURE GenIData(base: LONGINT);
  1112. VAR W: SectionWriter; p, mod: ImportMod; obj: ImportObj; sect: Section; r: ImportReloc; i, j, ofs: LONGINT;
  1113. BEGIN
  1114. IF name # Loader THEN
  1115. p := NIL; mod := imports;
  1116. WHILE (mod # NIL) & (mod.name # Loader) DO
  1117. p := mod; mod := mod.next
  1118. END;
  1119. ASSERT(mod # NIL);
  1120. IF p # NIL THEN
  1121. p.next := mod.next;
  1122. mod.next := imports;
  1123. imports := mod
  1124. END
  1125. END;
  1126. idata.head.VirtualAddress := base;
  1127. optHdr.DataDirectory[ImageDirectoryEntryImport].VirtualAddress := base;
  1128. W := idata.W; W.SetPos(0);
  1129. mod := imports;
  1130. WHILE mod # NIL DO
  1131. WriteImageImportDescriptor(W, mod.desc);
  1132. mod := mod.next
  1133. END;
  1134. i := 0;
  1135. WHILE i < SIZEOF(ImageImportDescriptor) DO
  1136. W.Char(0X); INC(i)
  1137. END;
  1138. optHdr.DataDirectory[ImageDirectoryEntryImport].Size := W.Pos();
  1139. mod := imports;
  1140. WHILE mod # NIL DO
  1141. mod.desc.Characteristics := W.Pos();
  1142. obj := mod.objs;
  1143. WHILE obj # NIL DO
  1144. W.RawLInt(0); obj := obj.next
  1145. END;
  1146. W.RawLInt(0);
  1147. mod := mod.next
  1148. END;
  1149. ofs := W.Pos();
  1150. optHdr.DataDirectory[ImageDirectoryEntryIAT].VirtualAddress := base + ofs;
  1151. mod := imports;
  1152. WHILE mod # NIL DO
  1153. mod.desc.FirstThunk := W.Pos();
  1154. obj := mod.objs;
  1155. WHILE obj # NIL DO
  1156. W.RawLInt(0); obj := obj.next
  1157. END;
  1158. W.RawLInt(0);
  1159. mod := mod.next
  1160. END;
  1161. W.Update();
  1162. optHdr.DataDirectory[ImageDirectoryEntryIAT].Size := W.Pos() - ofs;
  1163. mod := imports; i := 0;
  1164. WHILE mod # NIL DO
  1165. obj := mod.objs; j := 0;
  1166. WHILE obj # NIL DO
  1167. W.SetPos(mod.desc.Characteristics + j);
  1168. W.RawLInt(base + idata.used);
  1169. W.SetPos(mod.desc.FirstThunk + j);
  1170. obj.iat := base + mod.desc.FirstThunk + j;
  1171. W.RawLInt(base + idata.used);
  1172. W.SetPos(idata.used);
  1173. W.RawInt(0);
  1174. PutName(W, obj.name);
  1175. obj := obj.next; INC(j, 4)
  1176. END;
  1177. W.Update();
  1178. mod.desc.Characteristics := base + mod.desc.Characteristics;
  1179. mod.desc.Name := base + idata.used;
  1180. mod.desc.FirstThunk := base + mod.desc.FirstThunk;
  1181. W.SetPos(i);
  1182. WriteImageImportDescriptor(W, mod.desc);
  1183. W.SetPos(idata.used);
  1184. PutName(W, mod.name);
  1185. W.Update();
  1186. mod := mod.next; INC(i, SIZEOF(ImageImportDescriptor))
  1187. END;
  1188. sect := sects;
  1189. WHILE sect # NIL DO
  1190. r := sect.imports;
  1191. WHILE r # NIL DO
  1192. IF r.iat THEN
  1193. ASSERT(r.abs & ~r.uofs);
  1194. AddOfsReloc(sect, r.ofs, idata);
  1195. W := sect.W; W.SetPos(r.ofs);
  1196. W.RawLInt(r.obj.iat - base)
  1197. END;
  1198. r := r.next
  1199. END;
  1200. sect := sect.next
  1201. END;
  1202. W.Update()
  1203. END GenIData;
  1204. PROCEDURE GenEData(base: LONGINT);
  1205. VAR W: SectionWriter; dir: ImageExportDirectory; e: ExportObj; fix, i, n: LONGINT;
  1206. BEGIN
  1207. edata.head.VirtualAddress := base;
  1208. optHdr.DataDirectory[ImageDirectoryEntryExport].VirtualAddress := base;
  1209. e := exports; n := 0;
  1210. WHILE e # NIL DO
  1211. e := e.next; INC(n)
  1212. END;
  1213. dir.Characteristics := 0;
  1214. dir.TimeDateStamp := fileHdr.TimeDateStamp;
  1215. dir.MajorVersion := 0;
  1216. dir.MinorVersion := 0;
  1217. dir.Name := 0;
  1218. dir.Base := 1;
  1219. dir.NumberOfFunctions := n;
  1220. dir.NumberOfNames := n;
  1221. dir.AddressOfFunctions := 0;
  1222. dir.AddressOfNames := 0;
  1223. dir.AddressOfNameOrdinals := 0;
  1224. W := edata.W; W.SetPos(0);
  1225. WriteImageExportDirectory(W, dir);
  1226. dir.AddressOfFunctions := base + W.Pos();
  1227. e := exports;
  1228. WHILE e # NIL DO
  1229. W.RawLInt(e.sect.head.VirtualAddress + e.ofs);
  1230. e := e.next
  1231. END;
  1232. dir.AddressOfNames := base + W.Pos();
  1233. fix := W.Pos(); i := 0;
  1234. WHILE i < n DO
  1235. W.RawLInt(0); INC(i)
  1236. END;
  1237. dir.AddressOfNameOrdinals := base + W.Pos();
  1238. i := 0;
  1239. WHILE i < n DO
  1240. W.RawInt(SHORT(i)); INC(i)
  1241. END;
  1242. dir.Name := base + W.Pos();
  1243. PutName(W, name);
  1244. e := exports;
  1245. WHILE e # NIL DO
  1246. W.SetPos(fix);
  1247. W.RawLInt(base + edata.used);
  1248. W.SetPos(edata.used);
  1249. PutName(W, e.name);
  1250. W.Update();
  1251. e := e.next; INC(fix, 4)
  1252. END;
  1253. W.SetPos(0);
  1254. WriteImageExportDirectory(W, dir);
  1255. W.Update();
  1256. optHdr.DataDirectory[ImageDirectoryEntryExport].Size := edata.used
  1257. END GenEData;
  1258. PROCEDURE BeginBlock(W: SectionWriter; adr: LONGINT; VAR blockva, blocksize, blockfix: LONGINT);
  1259. BEGIN
  1260. blockva := adr - (adr MOD PageSize); blocksize := 8;
  1261. W.RawLInt(blockva);
  1262. blockfix := W.Pos();
  1263. W.RawLInt(blocksize)
  1264. END BeginBlock;
  1265. PROCEDURE EndBlock(W: SectionWriter; blockfix: LONGINT; VAR blocksize: LONGINT);
  1266. VAR ofs: LONGINT;
  1267. BEGIN
  1268. W.RawInt(0); INC(blocksize, 2);
  1269. IF (blocksize MOD 4) # 0 THEN
  1270. W.RawInt(0); INC(blocksize, 2)
  1271. END;
  1272. ofs := W.Pos(); W.SetPos(blockfix);
  1273. W.RawLInt(blocksize);
  1274. W.SetPos(ofs)
  1275. END EndBlock;
  1276. PROCEDURE LocalRelocs;
  1277. VAR W: SectionWriter; R: SectionReader; sect: Section; r: BaseReloc; x: LONGINT;
  1278. BEGIN
  1279. sect := sects;
  1280. WHILE sect # NIL DO
  1281. W := sect.W; R := sect.R;
  1282. r := sect.relocs;
  1283. WHILE r # NIL DO
  1284. R.SetPos(r.ofs);
  1285. R.RawLInt(x);
  1286. W.SetPos(r.ofs);
  1287. W.RawLInt(x + optHdr.ImageBase + r.base.head.VirtualAddress);
  1288. r := r.next
  1289. END;
  1290. W.Update();
  1291. sect := sect.next
  1292. END
  1293. END LocalRelocs;
  1294. PROCEDURE GenReloc(base: LONGINT);
  1295. VAR
  1296. W: SectionWriter; sect: Section; r: BaseReloc;
  1297. blockva, blocksize, blockfix, bak, x: LONGINT;
  1298. BEGIN
  1299. reloc.head.VirtualAddress := base;
  1300. optHdr.DataDirectory[ImageDirectoryEntryBasereloc].VirtualAddress := base;
  1301. LocalRelocs();
  1302. blockva := BaseRVA-PageSize; blocksize := 0; blockfix := -1;
  1303. W := reloc.W;
  1304. bak := 0; sect := sects;
  1305. WHILE sect # NIL DO
  1306. r := sect.relocs;
  1307. WHILE r # NIL DO
  1308. x := sect.head.VirtualAddress + r.ofs;
  1309. ASSERT(x > bak);
  1310. IF x >= (blockva+PageSize) THEN
  1311. IF blockfix >= 0 THEN EndBlock(W, blockfix, blocksize) END;
  1312. BeginBlock(W, x, blockva, blocksize, blockfix)
  1313. END;
  1314. bak := x; DEC(x, blockva);
  1315. W.RawInt(SHORT(x + LSH(SYSTEM.VAL(LONGINT, ImageRelBasedHighLow), 12)));
  1316. INC(blocksize, 2);
  1317. r := r.next
  1318. END;
  1319. sect := sect.next
  1320. END;
  1321. IF blockfix >= 0 THEN EndBlock(W, blockfix, blocksize) END;
  1322. W.Update();
  1323. optHdr.DataDirectory[ImageDirectoryEntryBasereloc].Size := reloc.used
  1324. END GenReloc;
  1325. PROCEDURE ToFile;
  1326. VAR file: Files.FileName; F: Files.File; W: Files.Writer; sect: Section; i, size: LONGINT; s: SET;
  1327. BEGIN
  1328. IF PCM.prefix # "" THEN
  1329. COPY(PCM.prefix, file);
  1330. Strings.Append(file, name)
  1331. ELSE
  1332. COPY(name, file)
  1333. END;
  1334. IF mode = ModeEXE THEN
  1335. Strings.Append(file, ".EXE")
  1336. ELSIF mode = ModeDLL THEN
  1337. Strings.Append(file, ".DLL")
  1338. ELSE
  1339. HALT(99)
  1340. END;
  1341. KernelLog.String("PCOFPE "); KernelLog.String(file);
  1342. SELF.optHdr.BaseOfCode := SELF.code.head.VirtualAddress;
  1343. F := Files.New(file);
  1344. Files.OpenWriter(W, F, 0);
  1345. W.RawInt(ImageDosSignature);
  1346. i := W.Pos(); WHILE i < 60 DO W.Char(0X); INC(i) END;
  1347. W.RawLInt(128);
  1348. i := W.Pos(); WHILE i < 128 DO W.Char(0X); INC(i) END;
  1349. size := 128 + 4 + SIZEOF(ImageFileHeader) + SIZEOF(ImageOptionalHeader) + SELF.fileHdr.NumberOfSections*SIZEOF(ImageSectionHeader);
  1350. size := Align(size, DefaultFileAlign);
  1351. SELF.optHdr.SizeOfHeaders := size;
  1352. size := Align(size, DefaultSectionAlign);
  1353. sect := SELF.sects;
  1354. WHILE sect # NIL DO
  1355. s := SYSTEM.VAL(SET, sect.head.Characteristics);
  1356. IF ImageScnCntCode IN s THEN
  1357. INC(SELF.optHdr.SizeOfCode, Align(sect.head.VirtualSize, DefaultSectionAlign))
  1358. ELSIF ImageScnCntInitializedData IN s THEN
  1359. INC(SELF.optHdr.SizeOfInitializedData, Align(sect.head.VirtualSize, DefaultSectionAlign))
  1360. ELSE
  1361. INC(SELF.optHdr.SizeOfUninitializedData, Align(sect.head.VirtualSize, DefaultSectionAlign))
  1362. END;
  1363. INC(size, Align(sect.head.VirtualSize, DefaultSectionAlign));
  1364. sect := sect.next
  1365. END;
  1366. SELF.optHdr.SizeOfImage := size;
  1367. W.RawLInt(ImageNtSignature);
  1368. WriteImageFileHeader(W, SELF.fileHdr);
  1369. WriteImageOptionalHeader(W, SELF.optHdr);
  1370. i := SELF.optHdr.SizeOfHeaders;
  1371. sect := SELF.sects;
  1372. WHILE sect # NIL DO
  1373. IF sect.used > 0 THEN
  1374. ASSERT(sect.head.VirtualSize = sect.used);
  1375. sect.head.SizeOfRawData := Align(sect.used, DefaultFileAlign);
  1376. sect.head.PointerToRawData := i; INC(i, sect.head.SizeOfRawData)
  1377. ELSE
  1378. sect.head.SizeOfRawData := 0; sect.head.PointerToRawData := 0
  1379. END;
  1380. WriteImageSectionHeader(W, sect.head);
  1381. sect := sect.next
  1382. END;
  1383. i := W.Pos(); WHILE i < SELF.optHdr.SizeOfHeaders DO W.Char(0X); INC(i) END;
  1384. sect := SELF.sects;
  1385. WHILE sect # NIL DO
  1386. IF sect.head.SizeOfRawData > 0 THEN
  1387. W.Bytes(sect.data^, 0, sect.used);
  1388. i := sect.used;
  1389. WHILE i < sect.head.SizeOfRawData DO W.Char(0X); INC(i) END
  1390. END;
  1391. sect := sect.next
  1392. END;
  1393. W.Update();
  1394. Files.Register(F)
  1395. ;KernelLog.String(" "); KernelLog.Int(F.Length(), 0); KernelLog.Ln()
  1396. END ToFile;
  1397. PROCEDURE &New*(mod: PCT.Module; adr: PCBT.Module);
  1398. VAR i: LONGINT; s: SET;
  1399. BEGIN
  1400. SELF.mod := mod; SELF.adr := adr;
  1401. SELF.fileHdr.Machine := ImageFileMachineI386;
  1402. SELF.fileHdr.NumberOfSections := 0;
  1403. SELF.fileHdr.TimeDateStamp := TimeDateStamp();
  1404. SELF.fileHdr.PointerToSymbolTable := 0;
  1405. SELF.fileHdr.NumberOfSymbols := 0;
  1406. SELF.fileHdr.SizeOfOptionalHeader := SIZEOF(ImageOptionalHeader);
  1407. s := {ImageFileExecutableImage, ImageFile32BitMachine, ImageFileLineNumsStripped, ImageFileLocalSymsStripped};
  1408. IF mode = ModeEXE THEN
  1409. INCL(s, ImageFileRelocsStripped)
  1410. ELSIF mode = ModeDLL THEN
  1411. INCL(s, ImageFileDll)
  1412. ELSE
  1413. HALT(99)
  1414. END;
  1415. SELF.fileHdr.Characteristics := SYSTEM.VAL(INTEGER, s);
  1416. SELF.optHdr.Magic := ImageOptionalMagic;
  1417. SELF.optHdr.MajorLinkerVersion := MajorLinkerVersion;
  1418. SELF.optHdr.MinorLinkerVersion := MinorLinkerVersion;
  1419. SELF.optHdr.SizeOfCode := 0;
  1420. SELF.optHdr.SizeOfInitializedData := 0;
  1421. SELF.optHdr.SizeOfUninitializedData := 0;
  1422. SELF.optHdr.AddressOfEntryPoint := 0;
  1423. SELF.optHdr.BaseOfCode := 0;
  1424. SELF.optHdr.BaseOfData := 0;
  1425. IF mode = ModeEXE THEN
  1426. SELF.optHdr.ImageBase := EXEImageBase
  1427. ELSIF mode = ModeDLL THEN
  1428. SELF.optHdr.ImageBase := DLLImageBase
  1429. ELSE
  1430. HALT(99)
  1431. END;
  1432. SELF.optHdr.SectionAlignment := DefaultSectionAlign;
  1433. SELF.optHdr.FileAlignment := DefaultFileAlign;
  1434. SELF.optHdr.MajorOperatingSystemVersion := 4;
  1435. SELF.optHdr.MinorOperatingSystemVersion := 0;
  1436. SELF.optHdr.MajorImageVersion := 0;
  1437. SELF.optHdr.MinorImageVersion := 0;
  1438. SELF.optHdr.MajorSubsystemVersion := 4;
  1439. SELF.optHdr.MinorSubsystemVersion := 0;
  1440. SELF.optHdr.Win32VersionValue := 0;
  1441. SELF.optHdr.SizeOfImage := 0;
  1442. SELF.optHdr.SizeOfHeaders := 0;
  1443. SELF.optHdr.CheckSum := 0;
  1444. IF mode = ModeEXE THEN
  1445. SELF.optHdr.Subsystem := SHORT(subsystem)
  1446. ELSIF mode = ModeDLL THEN
  1447. SELF.optHdr.Subsystem := ImageSubsystemUnknown
  1448. ELSE
  1449. HALT(99)
  1450. END;
  1451. SELF.optHdr.DllCharacteristics := 0;
  1452. SELF.optHdr.SizeOfStackReserve := DefaultStackSize;
  1453. SELF.optHdr.SizeOfStackCommit := PageSize;
  1454. SELF.optHdr.SizeOfHeapReserve := DefaultHeapSize;
  1455. SELF.optHdr.SizeOfHeapCommit := PageSize;
  1456. SELF.optHdr.LoaderFlags := 0;
  1457. SELF.optHdr.NumberOfRvaAndSizes := ImageNumberOfDirectoryEntries;
  1458. i := 0;
  1459. WHILE i < ImageNumberOfDirectoryEntries DO
  1460. SELF.optHdr.DataDirectory[i].VirtualAddress := 0;
  1461. SELF.optHdr.DataDirectory[i].Size := 0;
  1462. INC(i)
  1463. END;
  1464. SELF.sects := NIL; SELF.exports := NIL; SELF.imports := NIL;
  1465. NEW(SELF.type, SELF, ".type", {ImageScnCntInitializedData, ImageScnMemRead, ImageScnMemWrite});
  1466. IF adr.locsize > 0 THEN
  1467. NEW(SELF.var, SELF, ".var", {ImageScnMemRead, ImageScnMemWrite})
  1468. ELSE
  1469. SELF.var := NIL
  1470. END;
  1471. NEW(SELF.const, SELF, ".const", {ImageScnCntInitializedData, ImageScnMemRead, ImageScnMemWrite});
  1472. NEW(SELF.code, SELF, ".code", {ImageScnCntCode, ImageScnMemRead, ImageScnMemWrite, ImageScnMemExecute});
  1473. NEW(SELF.idata, SELF, ".idata", {ImageScnCntInitializedData, ImageScnMemRead});
  1474. NEW(SELF.edata, SELF, ".edata", {ImageScnCntInitializedData, ImageScnMemRead});
  1475. IF mode = ModeDLL THEN
  1476. NEW(SELF.reloc, SELF, ".reloc", {ImageScnCntInitializedData, ImageScnMemDiscardable, ImageScnMemRead})
  1477. ELSE
  1478. SELF.reloc := NIL
  1479. END;
  1480. END New;
  1481. END PEModule;
  1482. VAR
  1483. mode: LONGINT; (* ModeDef, ModeDLL, ModeEXE *)
  1484. subsystem: LONGINT; (* ImageSubsystemWindowsCui, ImageSubsystemWindowsGui *)
  1485. PROCEDURE WriteImageFileHeader(W: Streams.Writer; VAR head: ImageFileHeader);
  1486. BEGIN
  1487. W.RawInt(head.Machine);
  1488. W.RawInt(head.NumberOfSections);
  1489. W.RawLInt(head.TimeDateStamp);
  1490. W.RawLInt(head.PointerToSymbolTable);
  1491. W.RawLInt(head.NumberOfSymbols);
  1492. W.RawInt(head.SizeOfOptionalHeader);
  1493. W.RawInt(head.Characteristics)
  1494. END WriteImageFileHeader;
  1495. PROCEDURE WriteImageOptionalHeader(W: Streams.Writer; VAR head: ImageOptionalHeader);
  1496. VAR i: LONGINT;
  1497. BEGIN
  1498. W.RawInt(head.Magic);
  1499. W.Char(head.MajorLinkerVersion);
  1500. W.Char(head.MinorLinkerVersion);
  1501. W.RawLInt(head.SizeOfCode);
  1502. W.RawLInt(head.SizeOfInitializedData);
  1503. W.RawLInt(head.SizeOfUninitializedData);
  1504. W.RawLInt(head.AddressOfEntryPoint);
  1505. W.RawLInt(head.BaseOfCode);
  1506. W.RawLInt(head.BaseOfData);
  1507. W.RawLInt(head.ImageBase);
  1508. W.RawLInt(head.SectionAlignment);
  1509. W.RawLInt(head.FileAlignment);
  1510. W.RawInt(head.MajorOperatingSystemVersion);
  1511. W.RawInt(head.MinorOperatingSystemVersion);
  1512. W.RawInt(head.MajorImageVersion);
  1513. W.RawInt(head.MinorImageVersion);
  1514. W.RawInt(head.MajorSubsystemVersion);
  1515. W.RawInt(head.MinorSubsystemVersion);
  1516. W.RawLInt(head.Win32VersionValue);
  1517. W.RawLInt(head.SizeOfImage);
  1518. W.RawLInt(head.SizeOfHeaders);
  1519. W.RawLInt(head.CheckSum);
  1520. W.RawInt(head.Subsystem);
  1521. W.RawInt(head.DllCharacteristics);
  1522. W.RawLInt(head.SizeOfStackReserve);
  1523. W.RawLInt(head.SizeOfStackCommit);
  1524. W.RawLInt(head.SizeOfHeapReserve);
  1525. W.RawLInt(head.SizeOfHeapCommit);
  1526. W.RawLInt(head.LoaderFlags);
  1527. W.RawLInt(head.NumberOfRvaAndSizes);
  1528. i := 0;
  1529. WHILE i < ImageNumberOfDirectoryEntries DO
  1530. W.RawLInt(head.DataDirectory[i].VirtualAddress);
  1531. W.RawLInt(head.DataDirectory[i].Size);
  1532. INC(i)
  1533. END
  1534. END WriteImageOptionalHeader;
  1535. PROCEDURE WriteImageSectionHeader(W: Streams.Writer; VAR head: ImageSectionHeader);
  1536. BEGIN
  1537. W.Bytes(head.Name, 0, ImageSizeOfShortName);
  1538. W.RawLInt(head.VirtualSize);
  1539. W.RawLInt(head.VirtualAddress);
  1540. W.RawLInt(head.SizeOfRawData);
  1541. W.RawLInt(head.PointerToRawData);
  1542. W.RawLInt(head.PointerToRelocations);
  1543. W.RawLInt(head.PointerToLinenumbers);
  1544. W.RawInt(head.NumberOfRelocations);
  1545. W.RawInt(head.NumberOfLinenumbers);
  1546. W.RawSet(head.Characteristics)
  1547. END WriteImageSectionHeader;
  1548. PROCEDURE WriteImageImportDescriptor(W: Streams.Writer; VAR desc: ImageImportDescriptor);
  1549. BEGIN
  1550. W.RawLInt(desc.Characteristics);
  1551. W.RawLInt(desc.TimeDateStamp);
  1552. W.RawLInt(desc.ForwarderChain);
  1553. W.RawLInt(desc.Name);
  1554. W.RawLInt(desc.FirstThunk)
  1555. END WriteImageImportDescriptor;
  1556. PROCEDURE WriteImageExportDirectory(W: Streams.Writer; VAR dir: ImageExportDirectory);
  1557. BEGIN
  1558. W.RawLInt(dir.Characteristics);
  1559. W.RawLInt(dir.TimeDateStamp);
  1560. W.RawInt(dir.MajorVersion);
  1561. W.RawInt(dir.MinorVersion);
  1562. W.RawLInt(dir.Name);
  1563. W.RawLInt(dir.Base);
  1564. W.RawLInt(dir.NumberOfFunctions);
  1565. W.RawLInt(dir.NumberOfNames);
  1566. W.RawLInt(dir.AddressOfFunctions);
  1567. W.RawLInt(dir.AddressOfNames);
  1568. W.RawLInt(dir.AddressOfNameOrdinals)
  1569. END WriteImageExportDirectory;
  1570. PROCEDURE TimeDateStamp(): LONGINT;
  1571. (* number of seconds since 1.1.1970 UTC *)
  1572. VAR now: Dates.DateTime; A: ARRAY 12 OF LONGINT; y, days: LONGINT;
  1573. BEGIN
  1574. now := Dates.Now();
  1575. ASSERT((now.year >= 1970) & (now.year < 2100));
  1576. A[0] := 0; A[1] := 31; A[2] := 59; A[3] := 90; A[4] := 120; A[5] := 151; A[6] := 181;
  1577. A[7] := 212; A[8] := 243; A[9] := 273; A[10] := 304; A[11] := 334;
  1578. y := now.year - 1970;
  1579. days := y*365 + (y DIV 4) + A[now.month-1] + now.day - 1;
  1580. IF Dates.LeapYear(now.year) & (now.month > 2) THEN INC(days) END;
  1581. RETURN now.second + 60*(now.minute - Clock.tz + 60*(now.hour + 24*days))
  1582. END TimeDateStamp;
  1583. PROCEDURE AddOfsReloc(sect: Section; ofs: LONGINT; base: Section);
  1584. (* value at sect:ofs must be relocated to base + value *)
  1585. VAR p, r, n: BaseReloc;
  1586. BEGIN
  1587. p := NIL; r := sect.relocs;
  1588. WHILE (r # NIL) & (r.ofs < ofs) DO
  1589. p := r; r := r.next
  1590. END;
  1591. ASSERT((p = NIL) OR (p.ofs < ofs));
  1592. ASSERT((r = NIL) OR (r.ofs > ofs));
  1593. NEW(n); n.next := r; n.base := base; n.ofs := ofs;
  1594. IF p # NIL THEN p.next := n ELSE sect.relocs := n END
  1595. END AddOfsReloc;
  1596. PROCEDURE AddImportObj(mod: ImportMod; name: ARRAY OF CHAR): ImportObj;
  1597. VAR p, n, obj: ImportObj;
  1598. BEGIN
  1599. p := NIL; n := mod.objs;
  1600. WHILE (n # NIL) & (n.name < name) DO
  1601. p := n; n := n.next
  1602. END;
  1603. IF (n = NIL) OR (n.name > name) THEN
  1604. NEW(obj); COPY(name, obj.name); obj.iat := 0; obj.next := n;
  1605. IF p # NIL THEN p.next := obj ELSE mod.objs := obj END;
  1606. RETURN obj
  1607. ELSE
  1608. RETURN n
  1609. END
  1610. END AddImportObj;
  1611. PROCEDURE AddImportReloc(sect: Section; offset: LONGINT; obj: ImportObj; iat, abs, ofs: BOOLEAN);
  1612. (*
  1613. value at sect:ofs must be fixed up to iat[obj]
  1614. iat = TRUE iat relative
  1615. iat = FALSE absolute, copy value from iat table
  1616. *)
  1617. VAR p, i, n: ImportReloc;
  1618. BEGIN
  1619. ASSERT((iat & abs & ~ofs) OR (~iat & (abs OR ~ofs)));
  1620. p := NIL; i := sect.imports;
  1621. WHILE (i # NIL) & (i.ofs < offset) DO
  1622. p := i; i := i.next
  1623. END;
  1624. ASSERT((p = NIL) OR (p.ofs < offset));
  1625. ASSERT((i = NIL) OR (i.ofs > offset));
  1626. NEW(n); n.next := i; n.ofs := offset; n.obj := obj; n.iat := iat;
  1627. n.abs := abs; n.uofs := ofs;
  1628. IF p # NIL THEN p.next := n ELSE sect.imports := n END
  1629. END AddImportReloc;
  1630. PROCEDURE Align(value, align: LONGINT): LONGINT;
  1631. BEGIN
  1632. RETURN value + ((align-(value MOD align)) MOD align)
  1633. END Align;
  1634. PROCEDURE Generate*(VAR R: PCM.Rider; scope: PCT.ModScope; VAR codeSize: LONGINT);
  1635. VAR pe: PEModule; base: LONGINT; W: SectionWriter;
  1636. BEGIN
  1637. PCM.CloseObj(R); (* write symbol only object file *)
  1638. NEW(pe, scope.owner, scope.owner.adr(PCBT.Module)); base := BaseRVA;
  1639. StringPool.GetString(pe.mod.name, pe.name);
  1640. PCLIR.CG.GetCode(pe.codearr, codeSize, pe.hdrCodeSize, pe.addressFactor);
  1641. W := pe.const.W; W.SetPos(0);
  1642. W.Bytes(pe.adr.const^, 0, pe.adr.constsize);
  1643. W.Update();
  1644. W := pe.code.W; W.SetPos(0);
  1645. W.Bytes(pe.codearr^, 0, codeSize);
  1646. W.Update();
  1647. IF pe.var # NIL THEN
  1648. (* var: padding for proper sb offsets *)
  1649. pe.var.head.VirtualSize := Align(pe.adr.locsize, PageSize)
  1650. END;
  1651. pe.FixupLinks(); (* InsertFixupLists:, LinkBlock only SysCalls & Case *)
  1652. (*
  1653. CollectInfo: to do: ref block
  1654. *)
  1655. pe.Commands(); (* CollectInfo, CommandBlock *)
  1656. pe.UseModules(); (* CollectInfo, ImportBlock *)
  1657. pe.FixupOwnProcs(); (* EntryBlock, LinkBlock: entries only for methods *)
  1658. pe.Pointers(); (* PointerBlock *)
  1659. pe.FixupOwnVars(); (* VarConsBlock: only OwnVars *)
  1660. pe.Exports(); (* ExportBlock *)
  1661. pe.Imports(); (* UseBlock, InsertFixupLists, VarConsBlock *)
  1662. pe.Types(); (* TypeBlock *)
  1663. pe.GenStub();
  1664. pe.type.SetBase(base);
  1665. IF pe.var # NIL THEN
  1666. pe.var.SetBase(base)
  1667. END;
  1668. pe.const.SetBase(base);
  1669. INC(pe.optHdr.AddressOfEntryPoint, base);
  1670. pe.code.SetBase(base);
  1671. pe.GenIData(base);
  1672. pe.IATFix();
  1673. pe.idata.SetBase(base);
  1674. pe.GenEData(base);
  1675. pe.edata.SetBase(base);
  1676. IF mode = ModeDLL THEN
  1677. pe.GenReloc(base);
  1678. pe.reloc.SetBase(base)
  1679. ELSE
  1680. pe.LocalRelocs()
  1681. END;
  1682. pe.ToFile()
  1683. END Generate;
  1684. PROCEDURE SetDLL*;
  1685. BEGIN
  1686. mode := ModeDLL;
  1687. END SetDLL;
  1688. PROCEDURE SetEXE*;
  1689. BEGIN
  1690. mode := ModeEXE;
  1691. END SetEXE;
  1692. PROCEDURE SetCUI*;
  1693. BEGIN
  1694. subsystem := ImageSubsystemWindowsCui;
  1695. END SetCUI;
  1696. PROCEDURE SetGUI*;
  1697. BEGIN
  1698. subsystem := ImageSubsystemWindowsGui;
  1699. END SetGUI;
  1700. PROCEDURE Install*;
  1701. BEGIN
  1702. PCBT.generate := Generate
  1703. END Install;
  1704. BEGIN
  1705. mode := ModeDLL;
  1706. subsystem := ImageSubsystemWindowsCui
  1707. END PCOFPE.
  1708. System.Free PCOFPE ~
  1709. PC.Compile \s \.Syw \FPE * PC.Compile \s \.Syw \FPE \X *