Linker0.Mod 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE Linker0; (* pjm *)
  3. (* Aos Bootlinfker auxiliary module *)
  4. (* fof: modifications for address sizes other than 4, mainly modified New* Procedures and offsets, tried to get some more documentation into the program text *)
  5. IMPORT SYSTEM, Streams, Files, KernelLog;
  6. CONST
  7. DefaultExtension = ".Obx";
  8. HeapSize = 1024*1024 (*630*1024;*); (* linker heap size *)
  9. AddressSize = SIZEOF (ADDRESS);
  10. LenOfs = 3 * AddressSize; (* offset of first array dimension in SysBlk or ArrayBlk *)
  11. Unmarked = 0; (* mark value of free block *)
  12. (* fixup identifiers - also see GetKernelProc *)
  13. MemBlockDescModule = "Machine"; MemBlockDescType = "MemoryBlockDesc";
  14. ModDescModule = "Modules"; ModDescType = "Module";
  15. TypeDescModule = "Modules"; TypeDescType = "TypeDesc";
  16. HdPtrDescModule = "Loader"; HdPtrDescType = "@HdPtrDesc";
  17. ExportDescModule = "Modules"; ExportDescType = "ExportDesc";
  18. InitPtrModule = "Modules"; InitPtrName = "initBlock";
  19. ModRootModule = "Modules"; ModRootName = "root";
  20. ProcOffsetsName = "procOffsets"; NumProcsName = "numProcs";
  21. PtrOffsetsName = "ptrOffsets"; NumPtrsName = "numPtrs";
  22. HeapModule = "Heaps";
  23. FreeBlockDescType = "FreeBlockDesc"; SystemBlockDescType = "SystemBlockDesc"; RecordBlockDescType = "RecordBlockDesc";
  24. ProtRecBlockDescType = "ProtRecBlockDesc"; ArrayBlockDescType = "ArrayBlockDesc";
  25. FreeBlockTagPtrName = "freeBlockTagPtr"; SystemBlockTagPtrName = "systemBlockTagPtr"; RecordBlockTagPtrName = "recordBlockTagPtr";
  26. ProtRecBlockTagPtrName = "protRecBlockTagPtr"; ArrayBlockTagPtrName = "arrayBlockTagPtr";
  27. CurrentMarkValueName = "currentMarkValue";
  28. StartModule = "Objects"; StartCommand = "Terminate";
  29. MainModule = "BootConsole";
  30. (* id field temporarily stored in tag field of heap block, fixup in FixupHeapBlockTags *)
  31. FreeBlockId = 0;
  32. SystemBlockId = 1;
  33. RecordBlockId = 2;
  34. ProtRecBlockId = 3;
  35. ArrayBlockId = 4;
  36. ProtectedModule = TRUE; (* is module descriptor protected? *)
  37. TraceDump = FALSE; (* should full dump be displayed? *)
  38. TraceRefs = TRUE & TraceDump; (* conservatively look for "missed" internal references? *)
  39. TraceDuplicates = FALSE & TraceDump; (* should duplicate relocates be allowed and highlighted? *)
  40. LogName = "Linker.Log";
  41. HeaderSize = 40H; (* HeaderSize MOD BlockSize = 0 *) (* ug *)
  42. EndBlockOfs = 38H; (* cf. Machine.GetStaticHeap *)
  43. NumPriorities* = 6;
  44. TYPE
  45. AdrTable = POINTER TO ARRAY OF ADDRESS;
  46. (** --- MODULE Heaps --- *)
  47. CONST
  48. MaxTags* = 16; (* in type descriptor *)
  49. (** type descriptor field offsets relative to root (middle) *)
  50. Tag0Ofs* = -2 * AddressSize; (** first tag *)
  51. Mth0Ofs* = Tag0Ofs - AddressSize * MaxTags; (** first method *)
  52. Ptr0Ofs* = AddressSize; (** first pointer offset *)
  53. (** flags in TypeDesc, RoundUp(log2(MaxTags)) low bits reserved for extLevel *)
  54. ProtTypeBit* = 31;
  55. BlockSize = 32; (* power of two, <= 32 for RegisterCandidates *)
  56. ArrayAlignment = 8;
  57. BlockHeaderSize = 2 * AddressSize;
  58. HeapBlockOffset = - 2 * AddressSize;
  59. TypeDescOffset = - AddressSize;
  60. MinPtrOfs = -40000000H; (* sentinel offset for ptrOfs *)
  61. MethodEndMarker* = MinPtrOfs; (* marks the end of the method addresses in the static type descriptor *)
  62. InitTableLen = 2048 + 256;
  63. InitPtrTableLen = 2048;
  64. TypeDescRecSize* = 5 * AddressSize + 32; (* needs to be changed in case TypeDesc is adapted *)
  65. NilVal* = 0;
  66. TYPE
  67. RootObject* = OBJECT
  68. VAR nextRoot: RootObject; (* for linking root objects during GC *)
  69. PROCEDURE FindRoots*; (** abstract *)
  70. BEGIN
  71. HALT(30101)
  72. END FindRoots;
  73. END RootObject;
  74. ProcessLink* = OBJECT (RootObject)
  75. VAR next*, prev*: ProcessLink
  76. END ProcessLink;
  77. ProcessQueue* = RECORD
  78. head*, tail*: ProcessLink
  79. END;
  80. MemoryBlock = POINTER TO MemoryBlockDesc;
  81. MemoryBlockDesc = RECORD
  82. next {UNTRACED}: MemoryBlock;
  83. startAdr: ADDRESS;
  84. size: SIZE;
  85. beginBlockAdr, endBlockAdr: ADDRESS
  86. END;
  87. HeapBlock = POINTER TO HeapBlockDesc; (* base object of all heap blocks *)
  88. HeapBlockDesc = RECORD
  89. mark: LONGINT;
  90. dataAdr: ADDRESS;
  91. size: SIZE;
  92. nextRealtime: HeapBlock;
  93. END;
  94. FreeBlock = POINTER TO FreeBlockDesc;
  95. FreeBlockDesc = RECORD (HeapBlockDesc)
  96. END;
  97. SystemBlock = POINTER TO SystemBlockDesc;
  98. SystemBlockDesc = RECORD (HeapBlockDesc)
  99. END;
  100. RecordBlock = POINTER TO RecordBlockDesc;
  101. RecordBlockDesc = RECORD (HeapBlockDesc)
  102. END;
  103. ProtRecBlock* = POINTER TO ProtRecBlockDesc;
  104. ProtRecBlockDesc* = RECORD (RecordBlockDesc)
  105. count*: LONGINT;
  106. locked*: BOOLEAN;
  107. awaitingLock*: ProcessQueue;
  108. awaitingCond*: ProcessQueue;
  109. lockedBy*: ANY;
  110. lock*: ANY; (* field used for Win32 system, unused for I386 *)
  111. waitingPriorities*: ARRAY NumPriorities OF LONGINT;
  112. END;
  113. ArrayBlock = POINTER TO ArrayBlockDesc;
  114. ArrayBlockDesc = RECORD (HeapBlockDesc)
  115. END;
  116. StaticTypeBlock*= POINTER TO StaticTypeDesc;
  117. StaticTypeDesc* = RECORD
  118. recSize: SIZE;
  119. pointerOffsets* {UNTRACED}: PointerOffsets;
  120. END;
  121. PointerOffsets = POINTER TO ARRAY OF SIZE;
  122. (** --- MODULE Modules --- *)
  123. TYPE
  124. (* definitions for object-model loader support *)
  125. Name* = ARRAY 32 OF CHAR;
  126. CommandProc* = PROCEDURE;
  127. CommandParProc* = PROCEDURE(par: ANY): ANY;
  128. Command* = RECORD
  129. name*: Name;
  130. argTdAdr*, retTdAdr* : ADDRESS;
  131. entryAdr* : ADDRESS;
  132. END;
  133. ExportDesc* = RECORD
  134. fp*: ADDRESS;
  135. adr*: ADDRESS;
  136. exports*: LONGINT;
  137. dsc*: ExportArray
  138. END;
  139. ExportArray* = POINTER TO ARRAY OF ExportDesc;
  140. Bytes* = POINTER TO ARRAY OF CHAR;
  141. TerminationHandler* = PROCEDURE;
  142. ExceptionTableEntry* = RECORD
  143. pcFrom*: ADDRESS;
  144. pcTo*: ADDRESS;
  145. pcHandler*: ADDRESS;
  146. END;
  147. ExceptionTable* = POINTER TO ARRAY OF ExceptionTableEntry;
  148. ProcTableEntry* = RECORD
  149. pcFrom*, pcLimit*, pcStatementBegin*, pcStatementEnd*: ADDRESS;
  150. noPtr*: LONGINT;
  151. END;
  152. ProcTable* = POINTER TO ARRAY OF ProcTableEntry;
  153. PtrTable* = POINTER TO ARRAY OF SIZE;
  154. ProcOffsetEntry* = RECORD
  155. data*: ProcTableEntry; (* code offsets of procedures *)
  156. startIndex: LONGINT; (* start index into global ptrOffset table *)
  157. END;
  158. ProcOffsetTable* = POINTER TO ARRAY OF ProcOffsetEntry;
  159. Module* = OBJECT (RootObject) (* cf. Linker0 & Heaps.WriteType *)
  160. VAR
  161. next*: Module;
  162. name*: Name;
  163. init, published: BOOLEAN;
  164. refcnt*: LONGINT;
  165. sb*: ADDRESS;
  166. entry*: POINTER TO ARRAY OF ADDRESS;
  167. command*: POINTER TO ARRAY OF Command;
  168. ptrAdr*: POINTER TO ARRAY OF ADDRESS;
  169. typeInfo*: POINTER TO ARRAY OF TypeDesc; (* traced explicitly in FindRoots *) (* ug *)
  170. module*: POINTER TO ARRAY OF Module;
  171. procTable*: ProcTable; (* information inserted by loader, removed after use in Publish, not used by linker *)
  172. ptrTable*: PtrTable; (* information inserted by loader, removed after use in Publish, not used by linker *)
  173. data*, code*, staticTypeDescs* (* ug *), refs*: Bytes;
  174. export*: ExportDesc;
  175. term*: TerminationHandler;
  176. exTable*: ExceptionTable;
  177. noProcs*: LONGINT;
  178. firstProc*: ADDRESS; (* procedure with lowest PC in module *)
  179. maxPtrs*: LONGINT;
  180. crc*: LONGINT;
  181. END Module;
  182. TypeDesc* = POINTER TO RECORD (* ug: adapt constant TypeDescRecSize if this type if this type is changed !!! *)
  183. descSize: LONGINT;
  184. sentinel: LONGINT; (* = MPO-4 *)
  185. tag*: ADDRESS; (* pointer to static type descriptor, only used by linker and loader *)
  186. flags*: SET;
  187. mod*: Module; (* hint only, because module may have been freed (at Heaps.ModOfs) *)
  188. name*: Name;
  189. END;
  190. VAR
  191. logWriter: Streams.Writer; logFile: Files.File;
  192. root-: ADDRESS;
  193. procOffsets {UNTRACED}: ProcOffsetTable; (* global table containing procedure code offsets and pointer offsets, sorted in ascending order of procedure code offsets *)
  194. numProcs: LONGINT; (* number of entries in procOffsets *)
  195. ptrOffsets {UNTRACED}: PtrTable; (* global table containing pointer offsets of procedures *)
  196. numPtrs: LONGINT; (* number of entries in ptrOffsets *)
  197. heap-: ANY;
  198. memBlock {UNTRACED}: MemoryBlock;
  199. beginMemBlockAdr, endMemBlockAdr: ADDRESS; (* block boundaries of linker heap (including memory block descriptor) *)
  200. beginAdr, freeAdr, baseAdr (* fof 071201 *) : ADDRESS;
  201. heapOfs: SIZE;
  202. exportTags, relocates: LONGINT;
  203. exportTagAdr: AdrTable;
  204. relocateAdr: AdrTable;
  205. curRelocate: LONGINT;
  206. refsMissed: LONGINT;
  207. prefix,suffix: Files.FileName; (* fof 071203 could be long filename *)
  208. loadObj*: PROCEDURE (name, fileName: ARRAY OF CHAR; VAR res: LONGINT;
  209. VAR msg: ARRAY OF CHAR): Module;
  210. getProcs: ARRAY 9 OF BOOLEAN;
  211. freeBlockTag, systemBlockTag, recordBlockTag, protRecBlockTag, arrayBlockTag: ADDRESS;
  212. initBlock {UNTRACED}: ANY; (* address of init block, i.e. block that contains calls to module bodies *)
  213. currentMarkValue: LONGINT; (* all objects allocated in the link phase receive this mark value *)
  214. (** --- MODULE Machine --- *)
  215. (** Fill4 - Fill "size" dwords at "destAdr" with "filler". *)
  216. PROCEDURE Fill4 (destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  217. BEGIN
  218. WHILE size > 0 DO
  219. SYSTEM.PUT (destAdr, filler);
  220. INC (destAdr, SIZEOF(LONGINT));
  221. DEC (size);
  222. END;
  223. END Fill4;
  224. (** --- MODULE KernelLog --- *)
  225. (** Char - Write a character to the trace output. *)
  226. PROCEDURE Char*(c: CHAR);
  227. BEGIN
  228. logWriter.Char(c);
  229. END Char;
  230. (** String - Write a string. *)
  231. PROCEDURE String*(CONST s: ARRAY OF CHAR);
  232. BEGIN
  233. logWriter.String(s);
  234. END String;
  235. (** Ln - Skip to the next line on trace output. *)
  236. PROCEDURE Ln*;
  237. BEGIN
  238. logWriter.Ln();
  239. END Ln;
  240. (** Int - Write "x" as a decimal number. "w" is the field width. *)
  241. PROCEDURE Int*(x, w: LONGINT);
  242. BEGIN
  243. logWriter.Int(x,w);
  244. END Int;
  245. (** Hex - Write "x" as a hexadecimal number. *)
  246. PROCEDURE Hex*(x: SIZE; w: LONGINT);
  247. BEGIN
  248. logWriter.Hex(x,w);
  249. END Hex;
  250. (** Address - Write "x" as an address. *)
  251. PROCEDURE Address*(x: ADDRESS);
  252. BEGIN
  253. logWriter.Address(x);
  254. END Address;
  255. (** Memory - Write a block of memory. *)
  256. PROCEDURE Memory*(adr: ADDRESS; size: SIZE); (* ug: not yet rewritten using ADDRESS and SIZE *)
  257. VAR i,j: SIZE; t: LONGINT; buf: ARRAY 4 OF CHAR; reset, missed: BOOLEAN;
  258. BEGIN
  259. (*
  260. Texts.SetFont(writer, Fonts.This("Courier10.Scn.Fnt"));
  261. *)
  262. buf[1] := 0X; size := adr+size-1;
  263. reset := FALSE;
  264. FOR i := adr TO size BY 16 DO
  265. Hex(i, 9); missed := FALSE;
  266. FOR j := i TO i+15 DO
  267. IF j <= size THEN
  268. IF curRelocate >= 0 THEN (* highlighting enabled *)
  269. IF (j >= relocateAdr[curRelocate]) & (j <= relocateAdr[curRelocate]+3) THEN
  270. (* Texts.SetColor(writer, 3); *) reset := TRUE
  271. ELSIF j = relocateAdr[curRelocate]+4 THEN
  272. INC(curRelocate);
  273. IF curRelocate # relocates THEN
  274. IF j = relocateAdr[curRelocate] THEN
  275. (* Texts.SetColor(writer, 3); *) reset := TRUE
  276. ELSIF TraceDuplicates & (j = relocateAdr[curRelocate]+4) THEN (* duplicate! *)
  277. (* Texts.SetColor(writer, 1); *) reset := TRUE;
  278. REPEAT
  279. INC(curRelocate)
  280. UNTIL (curRelocate = relocates) OR (j # relocateAdr[curRelocate]+4)
  281. END
  282. ELSE
  283. curRelocate := -1
  284. END
  285. ELSIF TraceRefs THEN
  286. IF j <= adr+size-4 THEN (* heuristic to check if all pointers were seen *)
  287. SYSTEM.GET(j, t);
  288. IF (t > beginMemBlockAdr) & (t < freeAdr) THEN
  289. INC(refsMissed); missed := TRUE;
  290. (* Texts.SetColor(writer, 4); *) reset := TRUE
  291. END
  292. END
  293. END
  294. END;
  295. SYSTEM.GET(j, buf[0]);
  296. Hex(SYSTEM.VAL(SHORTINT, buf[0]), -3);
  297. (*
  298. IF reset THEN Texts.SetColor(writer, 15) END
  299. *)
  300. ELSE
  301. buf := " "; String(buf); buf[1] := 0X
  302. END
  303. END;
  304. buf[0] := " "; String(buf);
  305. FOR j := i TO i+15 DO
  306. IF j <= size THEN
  307. SYSTEM.GET(j, buf[0]);
  308. IF (buf[0] < " ") OR (buf[0] >= CHR(127)) THEN
  309. buf[0] := "."
  310. END;
  311. String(buf)
  312. END
  313. END;
  314. IF missed THEN String(" <--missed?") END;
  315. Ln
  316. END;
  317. (*
  318. Texts.SetFont(writer, Fonts.Default);
  319. *)
  320. END Memory;
  321. (** Bits - Write bits (ofs..ofs+n-1) of x in binary. *)
  322. PROCEDURE Bits*(x: SET; ofs, n: LONGINT);
  323. BEGIN
  324. REPEAT
  325. DEC(n);
  326. IF (ofs+n) IN x THEN Char("1") ELSE Char("0") END
  327. UNTIL n = 0
  328. END Bits;
  329. (** Enter - Enter mutually exclusive region for writing. *)
  330. PROCEDURE Enter*;
  331. BEGIN
  332. Char("{")
  333. END Enter;
  334. (** Exit - Exit mutually exclusive region for writing. *)
  335. PROCEDURE Exit*;
  336. BEGIN
  337. Char("}"); Ln
  338. END Exit;
  339. (** --- MODULE Heaps --- *)
  340. (* initialize a free block *)
  341. PROCEDURE InitFreeBlock(freeBlock: FreeBlock; mark: LONGINT; dataAdr: ADDRESS; size: SIZE);
  342. VAR freeBlockAdr: ADDRESS;
  343. BEGIN
  344. freeBlock.mark := mark;
  345. freeBlock.dataAdr := dataAdr;
  346. freeBlock.size := size;
  347. freeBlock.nextRealtime := NIL;
  348. (* initialize free block header *)
  349. freeBlockAdr := SYSTEM.VAL(ADDRESS, freeBlock);
  350. SYSTEM.PUT(freeBlockAdr + TypeDescOffset, FreeBlockId); (* use temporary constant here, correct tags are filled in by FixupHeapBlockTags *)
  351. SYSTEM.PUT(freeBlockAdr + HeapBlockOffset, NilVal)
  352. END InitFreeBlock;
  353. (* NewBlock - Allocate a heap block. {(size MOD BlockSize = 0)} *)
  354. PROCEDURE NewBlock(size: SIZE): ADDRESS;
  355. VAR p, freeBlockAdr: ADDRESS; freeBlock: FreeBlock; blockSize: SIZE;
  356. BEGIN
  357. ASSERT(size MOD BlockSize = 0);
  358. freeBlock := SYSTEM.VAL(FreeBlock, freeAdr + BlockHeaderSize);
  359. blockSize := freeBlock.size;
  360. p := freeAdr; INC(freeAdr, size);
  361. ASSERT(freeAdr + BlockHeaderSize + SIZEOF(FreeBlockDesc) <= memBlock.endBlockAdr); (* there must be space for an empty heap block *)
  362. freeBlockAdr := freeAdr + BlockHeaderSize; (* address of remaining free block *)
  363. freeBlock := SYSTEM.VAL(FreeBlock, freeBlockAdr);
  364. InitFreeBlock(freeBlock, Unmarked, NilVal, blockSize - size);
  365. RETURN p
  366. END NewBlock;
  367. (** NewSys - Implementation of SYSTEM.NEW *)
  368. PROCEDURE NewSys*(VAR p: ANY; size: SIZE);
  369. VAR systemBlockSize, blockSize: SIZE; systemBlockAdr, dataBlockAdr: ADDRESS;
  370. systemBlock: SystemBlock;
  371. BEGIN
  372. ASSERT((BlockHeaderSize MOD ArrayAlignment = 0));
  373. systemBlockSize := BlockHeaderSize + SIZEOF(SystemBlockDesc);
  374. systemBlockSize := ((systemBlockSize + ArrayAlignment - 1) DIV ArrayAlignment) * ArrayAlignment; (* align SystemBlock such that first data element is aligned 0 MOD ArrayAlignment, required for arrays that do not contain pointers *)
  375. blockSize := systemBlockSize + BlockHeaderSize + size;
  376. INC(blockSize,(-blockSize) MOD BlockSize); (* round up to multiple of BlockSize *)
  377. systemBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
  378. SYSTEM.PUT(systemBlockAdr + TypeDescOffset, SystemBlockId); (* temporary type descriptor value, fixup and relocation are done later *)
  379. SYSTEM.PUT(systemBlockAdr + HeapBlockOffset, NilVal);
  380. dataBlockAdr := systemBlockAdr + systemBlockSize (* - BlockHeaderSize + BlockHeaderSize *);
  381. SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* system blocks have no type descriptor *)
  382. SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, systemBlockAdr); (* reference to heap block descriptor *)
  383. Relocate(dataBlockAdr + HeapBlockOffset);
  384. systemBlock := SYSTEM.VAL(SystemBlock, systemBlockAdr);
  385. systemBlock.mark := currentMarkValue;
  386. systemBlock.dataAdr := dataBlockAdr;
  387. systemBlock.nextRealtime := NIL; (* no realtime object since SystemBlock during allocation of a module *)
  388. Relocate(ADDRESSOF(systemBlock.dataAdr));
  389. Relocate(ADDRESSOF(systemBlock.nextRealtime));
  390. systemBlock.size := blockSize;
  391. p := SYSTEM.VAL(ANY, dataBlockAdr);
  392. Fill4(dataBlockAdr, (blockSize - systemBlockSize - BlockHeaderSize) DIV 4, 0); (* clear everything from dataBlockAdr until end of block *)
  393. END NewSys;
  394. (* NewRealArr - Implementation of allocation of new real array *)
  395. PROCEDURE NewRealArr*(VAR p: ANY; numElems, elemSize: SIZE; numDims: LONGINT);
  396. VAR arrayBlockAdr, dataBlockAdr, firstElem, elemTag: ADDRESS; arrSize, arrayBlockSize, blockSize, fillSize: SIZE;
  397. arrayBlock: ArrayBlock;
  398. arrayDataOffset: SIZE; (* offset from descriptor origin to first element of array, depends on number of dimensions, must be aligned to 0 MOD 8 *)
  399. BEGIN
  400. elemTag := 0;
  401. arrSize := numElems * elemSize;
  402. ASSERT(arrSize > 0);
  403. ASSERT((BlockHeaderSize MOD ArrayAlignment = 0));
  404. arrayDataOffset := numDims * AddressSize + 3 * AddressSize;
  405. INC(arrayDataOffset, (-arrayDataOffset) MOD ArrayAlignment); (* align here such that first first array element is aligned 0 MOD ArrayAlignment *)
  406. arrayBlockSize := BlockHeaderSize + SIZEOF(ArrayBlockDesc);
  407. INC(arrayBlockSize,(-arrayBlockSize) MOD ArrayAlignment); (* do. *)
  408. blockSize := arrayBlockSize + BlockHeaderSize + (arrayDataOffset + arrSize);
  409. INC(blockSize,(-blockSize) MOD BlockSize);(* round up to multiple of BlockSize *)
  410. arrayBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
  411. SYSTEM.PUT(arrayBlockAdr + TypeDescOffset, ArrayBlockId); (* temporary value, fixup and relocation are done later *)
  412. SYSTEM.PUT(arrayBlockAdr + HeapBlockOffset, NilVal);
  413. dataBlockAdr := arrayBlockAdr + arrayBlockSize (* - BlockHeaderSize + BlockHeaderSize *);
  414. SYSTEM.PUT(dataBlockAdr + TypeDescOffset, elemTag); (* dummy Tag, correct element tag will be filled in later *)
  415. SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, arrayBlockAdr); (* reference to heap block descriptor *)
  416. Relocate(dataBlockAdr + HeapBlockOffset);
  417. arrayBlock := SYSTEM.VAL(ArrayBlock, arrayBlockAdr);
  418. arrayBlock.mark := currentMarkValue;
  419. arrayBlock.dataAdr := dataBlockAdr;
  420. arrayBlock.nextRealtime := NIL; (* no realtime object since this object is used during allocation of a module *)
  421. Relocate(ADDRESSOF(arrayBlock.dataAdr));
  422. Relocate(ADDRESSOF(arrayBlock.nextRealtime));
  423. arrayBlock.size := blockSize;
  424. (* clear data part of array, clear everything from dataBlockAdr until end of block, write GC support info after clearing the block *)
  425. fillSize := blockSize - arrayBlockSize - BlockHeaderSize;
  426. ASSERT(fillSize MOD 4 = 0); (* fillSize implicitly is a multiple of 4 *)
  427. Fill4(dataBlockAdr, fillSize DIV 4, 0);
  428. firstElem := dataBlockAdr + arrayDataOffset;
  429. SYSTEM.PUT(dataBlockAdr, numElems (* firstElem + arrSize - elemSize*) ); (* lastElemToMark *)
  430. (* Relocate(dataBlockAdr); *)
  431. SYSTEM.PUT(dataBlockAdr + AddressSize, NIL); (* reserved for Mark *)
  432. SYSTEM.PUT(dataBlockAdr + 2 * AddressSize, firstElem); (* firstElem *)
  433. Relocate(dataBlockAdr + 2 * AddressSize);
  434. p := SYSTEM.VAL(ANY, dataBlockAdr);
  435. END NewRealArr;
  436. (* NewTypeDesc - Implementation of allocation of dynamic record *)
  437. PROCEDURE NewTypeDesc*(VAR p: ANY; recSize: SIZE);
  438. VAR blockSize: SIZE; recordBlockAdr, dataBlockAdr: ADDRESS;
  439. recordBlock: RecordBlock;
  440. BEGIN
  441. blockSize := BlockHeaderSize + SIZEOF(RecordBlockDesc) + BlockHeaderSize + recSize;
  442. INC(blockSize, (-blockSize) MOD BlockSize); (* align to multiple of BlockSize *)
  443. recordBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
  444. SYSTEM.PUT(recordBlockAdr + TypeDescOffset, RecordBlockId); (* temporary tag value, fixup and relocation are done later *)
  445. SYSTEM.PUT(recordBlockAdr + HeapBlockOffset, NilVal);
  446. dataBlockAdr := recordBlockAdr + SIZEOF(RecordBlockDesc) + BlockHeaderSize;
  447. SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* type descriptor tag will be filled in FixupTypeDescTags *)
  448. SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, recordBlockAdr); (* reference to heap block descriptor *)
  449. Relocate(dataBlockAdr + HeapBlockOffset);
  450. recordBlock := SYSTEM.VAL(RecordBlock, recordBlockAdr);
  451. recordBlock.mark := currentMarkValue;
  452. recordBlock.dataAdr := dataBlockAdr;
  453. recordBlock.nextRealtime := NIL; (* default value NIL since module type descriptors are no realtime objects *)
  454. Relocate(ADDRESSOF(recordBlock.dataAdr));
  455. Relocate(ADDRESSOF(recordBlock.nextRealtime));
  456. recordBlock.size := blockSize;
  457. p := SYSTEM.VAL(ANY, dataBlockAdr);
  458. Fill4(dataBlockAdr, (blockSize - SIZEOF(RecordBlockDesc) - 2 * BlockHeaderSize) DIV 4, 0); (* clear everything from dataBlockAdr to end of blockr *)
  459. END NewTypeDesc;
  460. (* FillStaticType - Implementation of filling static type descriptor *)
  461. PROCEDURE FillStaticType*(VAR staticTypeAddr: ADDRESS; startAddr, typeInfoAdr: ADDRESS; size, recSize: SIZE;
  462. numPtrs, numSlots: LONGINT);
  463. VAR p, offset: ADDRESS; staticTypeBlock {UNTRACED}: StaticTypeBlock;
  464. BEGIN
  465. Fill4(startAddr, size DIV 4, 0); (* clear whole static type, size MOD AddressSize = 0 implicitly, see WriteType in PCOF.Mod *)
  466. SYSTEM.PUT(startAddr, MethodEndMarker); (* sentinel *)
  467. (* methods and tags filled in later *)
  468. offset := AddressSize * (numSlots + 1 + 1); (* #methods, max. no. of tags, method end marker (sentinel), pointer to type information*)
  469. p := startAddr + offset;
  470. SYSTEM.PUT(p + TypeDescOffset, typeInfoAdr); (* pointer to typeInfo *)
  471. Relocate(p + TypeDescOffset);
  472. staticTypeBlock := SYSTEM.VAL(StaticTypeBlock, p);
  473. staticTypeBlock.recSize := recSize;
  474. staticTypeAddr := p;
  475. (* create the pointer for the dynamic array of pointer, the dynamic array of pointer offsets is stored in the static type
  476. descriptor and has no header part *)
  477. INC(p, SIZEOF(StaticTypeDesc));
  478. IF p MOD (2 * AddressSize) # 0 THEN INC(p, AddressSize) END;
  479. ASSERT(p MOD (2 * AddressSize) = 0);
  480. SYSTEM.PUT(p + 3 * AddressSize, numPtrs); (* internal structure of dynamic array without pointers: the first 3 fields are unused *)
  481. staticTypeBlock.pointerOffsets := SYSTEM.VAL(PointerOffsets, p); (* the fourth field contains the dimension of the array *)
  482. Relocate(ADDRESSOF(staticTypeBlock.pointerOffsets));
  483. (* pointer offsets filled in later *)
  484. END FillStaticType;
  485. (** --- MODULE Modules --- *)
  486. (** Append - Append from to to, truncating on overflow. *)
  487. PROCEDURE Append*(CONST from: ARRAY OF CHAR; VAR to: ARRAY OF CHAR);
  488. VAR i, j, m: LONGINT;
  489. BEGIN
  490. j := 0; WHILE to[j] # 0X DO INC(j) END;
  491. m := LEN(to)-1;
  492. i := 0; WHILE (from[i] # 0X) & (j # m) DO to[j] := from[i]; INC(i); INC(j) END;
  493. to[j] := 0X
  494. END Append;
  495. (* Publish - Add a module to the pool of accessible modules, or return named module. *)
  496. PROCEDURE Publish(VAR m: Module; VAR new: BOOLEAN);
  497. VAR n: Module; i: LONGINT;
  498. BEGIN
  499. n := SYSTEM.VAL(Module, root);
  500. WHILE (n # NIL) & (n.name # m.name) DO n := n.next END;
  501. IF n # NIL THEN (* module with same name exists, return it and ignore new m *)
  502. m := n; new := FALSE
  503. ELSE
  504. m.published := TRUE;
  505. m.next := SYSTEM.VAL(Module, root);
  506. root := SYSTEM.VAL(ADDRESS, m);
  507. m.refcnt := 0;
  508. FOR i := 0 TO LEN(m.module)-1 DO INC(m.module[i].refcnt) END;
  509. new := TRUE
  510. END
  511. END Publish;
  512. (* ModuleByName - Return the named module. *)
  513. PROCEDURE ModuleByName(CONST name: ARRAY OF CHAR): Module;
  514. VAR m: Module;
  515. BEGIN
  516. m := SYSTEM.VAL(Module, root);
  517. WHILE (m # NIL) & (m.name # name) DO m := m.next END;
  518. RETURN m
  519. END ModuleByName;
  520. (* GetFileName - Generate a module file name. *)
  521. PROCEDURE GetFileName(CONST name: ARRAY OF CHAR; VAR fileName: ARRAY OF CHAR);
  522. VAR i, j: LONGINT;
  523. BEGIN
  524. i := 0; WHILE prefix[i] # 0X DO fileName[i] := prefix[i]; INC(i) END;
  525. j := 0; WHILE name[j] # 0X DO fileName[i] := name[j]; INC(i); INC(j) END;
  526. j := 0; WHILE suffix[j] # 0X DO fileName[i] := suffix[j]; INC(i); INC(j) END;
  527. fileName[i] := 0X
  528. END GetFileName;
  529. (** ThisModule - Import a module. *) (* Algorithm J. Templ, ETHZ, 1994 *)
  530. PROCEDURE ThisModule*(CONST name: ARRAY OF CHAR; VAR res: LONGINT; VAR msg: ARRAY OF CHAR): Module;
  531. (* TYPE Body = PROCEDURE; *)
  532. VAR m, p: Module; fileName: ARRAY 64 OF CHAR; (*body: Body;*) new: BOOLEAN;
  533. BEGIN
  534. res := 0; msg[0] := 0X; m := ModuleByName(name);
  535. IF m = NIL THEN
  536. GetFileName(name, fileName);
  537. m := loadObj(name, fileName, res, msg);
  538. IF (m # NIL) & ~m.published THEN
  539. p := m; Publish(m, new);
  540. IF new THEN (* m was successfully published *)
  541. (*body := SYSTEM.VAL(Body, ADDRESSOF(m.code[0]));
  542. body; res := 0; msg[0] := 0X;*)
  543. m.init := TRUE (* allow ThisCommand *)
  544. ELSE
  545. (* m was part of cycle, replaced by existing module *)
  546. HALT(99)
  547. END
  548. END
  549. END;
  550. RETURN m
  551. END ThisModule;
  552. (** Return the named type *)
  553. PROCEDURE ThisType*(m: Module; CONST name: ARRAY OF CHAR): TypeDesc;
  554. VAR i: LONGINT; type: TypeDesc;
  555. BEGIN
  556. i := 0;
  557. WHILE (i < LEN(m.typeInfo)) & (m.typeInfo[i].name # name) DO INC(i) END;
  558. IF i = LEN(m.typeInfo) THEN
  559. type := NIL
  560. ELSE
  561. type := m.typeInfo[i]
  562. END;
  563. RETURN type
  564. END ThisType;
  565. (* ug: just for debugging *)
  566. (** WriteType - Write a type name (for tracing only). *)
  567. PROCEDURE WriteType(t: ADDRESS); (* t is static type descriptor *)
  568. VAR typeDesc: TypeDesc;
  569. BEGIN
  570. IF t # NilVal THEN
  571. SYSTEM.GET (t + TypeDescOffset, typeDesc);
  572. IF typeDesc.mod # NIL THEN
  573. String(typeDesc.mod.name)
  574. ELSE
  575. String("NIL");
  576. END;
  577. Char(".");
  578. String(typeDesc.name)
  579. ELSE
  580. String("no type")
  581. END
  582. END WriteType;
  583. PROCEDURE FindInsertionPos(VAR entry: ProcTableEntry; VAR pos: LONGINT): BOOLEAN;
  584. VAR l, r, x: LONGINT; success, isHit: BOOLEAN;
  585. BEGIN
  586. pos := -1;
  587. success := FALSE;
  588. IF numProcs = 0 THEN (* empty table *)
  589. pos := 0; success := TRUE
  590. ELSE
  591. l := 0; r := numProcs - 1;
  592. REPEAT
  593. x := (l + r) DIV 2;
  594. IF entry.pcLimit < procOffsets[x].data.pcFrom THEN r := x - 1 ELSE l := x + 1 END;
  595. isHit := ((x = 0) OR (procOffsets[x - 1].data.pcLimit < entry.pcFrom)) & (entry.pcLimit < procOffsets[x].data.pcFrom);
  596. UNTIL isHit OR (l > r);
  597. IF isHit THEN
  598. pos := x; success := TRUE
  599. ELSE
  600. IF (x = numProcs - 1) & (procOffsets[x].data.pcLimit < entry.pcFrom) THEN
  601. pos := x + 1; success := TRUE
  602. END
  603. END
  604. END;
  605. RETURN success
  606. END FindInsertionPos;
  607. PROCEDURE NumTotalPtrs(procTable: ProcTable): LONGINT;
  608. VAR i, num: LONGINT;
  609. BEGIN
  610. num := 0;
  611. FOR i := 0 TO LEN(procTable) - 1 DO
  612. num := num + procTable[i].noPtr
  613. END;
  614. RETURN num
  615. END NumTotalPtrs;
  616. (* insert the procedure code offsets and pointer offsets of a single module into the global table *)
  617. PROCEDURE InsertProcOffsets*(procTable: ProcTable; ptrTable: PtrTable; maxPtr: LONGINT);
  618. VAR success: BOOLEAN; i, j, pos, poslast, num: LONGINT;
  619. BEGIN
  620. IF LEN(procTable) > 0 THEN
  621. ASSERT(numProcs + LEN(procTable) <= LEN(procOffsets)); (* no reallocation of procOffsets in linker *)
  622. num := NumTotalPtrs(procTable);
  623. ASSERT(numPtrs + num <= LEN(ptrOffsets)); (* no reallocation of ptrOffsets in linker *)
  624. success := FindInsertionPos(procTable[0], pos); success := success & FindInsertionPos(procTable[LEN(procTable) - 1], poslast);
  625. ASSERT(success & (pos = poslast));
  626. FOR i := numProcs - 1 TO pos BY -1 DO procOffsets[i + LEN(procTable)] := procOffsets[i] END;
  627. FOR i := 0 TO LEN(procTable) - 1 DO
  628. procOffsets[pos + i].data := procTable[i];
  629. procOffsets[pos + i].startIndex := numPtrs; (* this field is never accessed in case of procTable[i].noPtr = 0, so we put numPtrs in there *)
  630. FOR j := 0 TO procTable[i].noPtr - 1 DO
  631. ptrOffsets[numPtrs + j] := ptrTable[i * maxPtr + j]
  632. END;
  633. numPtrs := numPtrs + procTable[i].noPtr;
  634. END;
  635. numProcs := numProcs + LEN(procTable)
  636. END
  637. END InsertProcOffsets;
  638. (** --- MODULE Linker0 --- *)
  639. (* GrowTable - Grow an address table. *)
  640. PROCEDURE GrowTable(VAR table: AdrTable);
  641. VAR new: AdrTable; i: LONGINT;
  642. BEGIN
  643. NEW(new, 2*LEN(table));
  644. FOR i := 0 TO LEN(table)-1 DO new[i] := table[i] END;
  645. table := new
  646. END GrowTable;
  647. (** Relocate - Record a relocate location. *)
  648. PROCEDURE Relocate*(adr: ADDRESS);
  649. BEGIN
  650. IF relocates = LEN(relocateAdr) THEN GrowTable(relocateAdr) END;
  651. relocateAdr[relocates] := adr; INC(relocates);
  652. SYSTEM.GET(adr, adr);
  653. ASSERT((adr = 0) OR (adr > beginMemBlockAdr) & (adr <= freeAdr))
  654. END Relocate;
  655. (** Open - Initialize the log file etc. *)
  656. PROCEDURE Open*(CONST namePrefix,nameSuffix: ARRAY OF CHAR; base: ADDRESS; log: Streams.Writer);
  657. VAR i: LONGINT; w: Files.Writer;
  658. BEGIN
  659. (* fof 071201 *)
  660. COPY(namePrefix, prefix);
  661. IF nameSuffix = "" THEN
  662. suffix := DefaultExtension
  663. ELSE
  664. COPY(nameSuffix, suffix)
  665. END;
  666. baseAdr := base;
  667. InitHeap;
  668. root := 0;
  669. freeAdr := memBlock.beginBlockAdr;
  670. heapOfs := baseAdr - beginAdr;
  671. exportTags := 0; relocates := 0; refsMissed := 0;
  672. curRelocate := -1;
  673. IF log # NIL THEN logWriter := log; logFile := NIL ELSE logFile := Files.New(LogName); NEW(w, logFile,0); logWriter := w END;
  674. FOR i := 0 TO LEN(getProcs) - 1 DO getProcs[i] := FALSE END;
  675. (* allocate the global tables procOffsets and ptrOffsets in linker heap *)
  676. NewProcOffsets(procOffsets, InitTableLen);
  677. numProcs := 0;
  678. NewPtrOffsets(ptrOffsets, InitPtrTableLen);
  679. numPtrs := 0;
  680. END Open;
  681. (* RelocateModules - Relocate the module records. *)
  682. PROCEDURE RelocateModules;
  683. VAR adr: ADDRESS; i: LONGINT; type, hdPtrDescType: TypeDesc; m: Module;
  684. BEGIN
  685. type := ThisType(ModuleByName(ModDescModule), ModDescType);
  686. hdPtrDescType := ThisType(ModuleByName(HdPtrDescModule), HdPtrDescType);
  687. ASSERT((type # NIL) & (hdPtrDescType # NIL));
  688. IF ProtectedModule THEN
  689. INCL(type.flags, ProtTypeBit) (* flag for dynamic loader *)
  690. END;
  691. m := SYSTEM.VAL(Module, root);
  692. WHILE m # NIL DO
  693. adr := SYSTEM.VAL(ADDRESS, m);
  694. SYSTEM.PUT(adr + TypeDescOffset, type.tag); Relocate(adr + TypeDescOffset); (* module descriptor tag *)
  695. IF LEN(m.typeInfo) > 0 THEN (* type tag only set in case of no. elements > 0 otherwise a SystemBlock with no type tag is used *)
  696. adr := SYSTEM.VAL(ADDRESS, m.typeInfo);
  697. SYSTEM.PUT(adr + TypeDescOffset, hdPtrDescType.tag);
  698. Relocate(adr + TypeDescOffset)
  699. END;
  700. IF LEN(m.module) > 0 THEN (* do. *)
  701. adr := SYSTEM.VAL(ADDRESS, m.module);
  702. SYSTEM.PUT(adr + TypeDescOffset, hdPtrDescType.tag);
  703. Relocate(adr + TypeDescOffset)
  704. END;
  705. (* relocation of addresses *)
  706. Relocate(ADDRESSOF(m.next));
  707. Relocate(m.sb); (* SELF in const area *)
  708. Relocate(ADDRESSOF(m.sb));
  709. (* m.entry in module block *)
  710. (* m.entry indirect tag already relocated (same as SysBlk) *)
  711. FOR i := 0 TO LEN(m.entry)-1 DO Relocate(ADDRESSOF(m.entry[i])) END;
  712. Relocate(ADDRESSOF(m.entry));
  713. (* m.command in module block *)
  714. FOR i := 0 TO LEN(m.command)-1 DO
  715. Relocate(ADDRESSOF(m.command[i].entryAdr));
  716. IF (m.command[i].argTdAdr > 1) THEN Relocate(ADDRESSOF(m.command[i].argTdAdr)); END;
  717. IF (m.command[i].retTdAdr > 1) THEN Relocate(ADDRESSOF(m.command[i].retTdAdr)); END;
  718. END;
  719. Relocate(ADDRESSOF(m.command));
  720. (* m.ptrAdr in module block *)
  721. FOR i := 0 TO LEN(m.ptrAdr)-1 DO Relocate(ADDRESSOF(m.ptrAdr[i])) END;
  722. Relocate(ADDRESSOF(m.ptrAdr));
  723. (* m.typeInfo in module block *)
  724. FOR i := 0 TO LEN(m.typeInfo) - 1 DO
  725. Relocate(ADDRESSOF(m.typeInfo[i]));
  726. Relocate(ADDRESSOF(m.typeInfo[i].tag));
  727. Relocate(ADDRESSOF(m.typeInfo[i].mod))
  728. END;
  729. Relocate(ADDRESSOF(m.typeInfo));
  730. (* m.module in module block *)
  731. FOR i := 0 TO LEN(m.module)-1 DO Relocate(ADDRESSOF(m.module[i])) END;
  732. Relocate(ADDRESSOF(m.module));
  733. (* m.data in module block *)
  734. Relocate(ADDRESSOF(m.data));
  735. (* m.code in module block *)
  736. Relocate(ADDRESSOF(m.code));
  737. (* m.staticTypeDescs in module block *)
  738. Relocate(ADDRESSOF(m.staticTypeDescs));
  739. (* m.refs in module block *)
  740. Relocate(ADDRESSOF(m.refs));
  741. (* m.exTable in module block *)
  742. FOR i := 0 TO LEN(m.exTable)-1 DO
  743. Relocate(ADDRESSOF(m.exTable[i].pcFrom));
  744. Relocate(ADDRESSOF(m.exTable[i].pcTo));
  745. Relocate(ADDRESSOF(m.exTable[i].pcHandler))
  746. END;
  747. Relocate(ADDRESSOF(m.exTable));
  748. Relocate(ADDRESSOF(m.firstProc));
  749. (*
  750. (* object model support *)
  751. ASSERT((m.publics = 0) & (m.privates = 0)); (* not marked *)
  752. ASSERT(m.import = NIL); (* not marked *)
  753. ASSERT(m.struct = NIL); (* not marked *)
  754. ASSERT(m.reimp = NIL); (* not marked *)
  755. *)
  756. Relocate(ADDRESSOF(m.export.dsc)); (* descendants relocated via RelocateArray *)
  757. m := m.next
  758. END
  759. END RelocateModules;
  760. (* RelocateArrayFields - Fix up a dynamic array. *)
  761. PROCEDURE RelocateArrayFields(tagAdr: ADDRESS);
  762. VAR adr, p, lastElem, size: ADDRESS; staticTypeBlock {UNTRACED}: StaticTypeBlock; i: LONGINT;
  763. BEGIN
  764. SYSTEM.GET(tagAdr + AddressSize, size);
  765. SYSTEM.GET(tagAdr + 3 * AddressSize, p); (* firstElem *)
  766. SYSTEM.GET(tagAdr, adr); (* adr is address of static type descriptor (no alignment) *)
  767. staticTypeBlock := SYSTEM.VAL(StaticTypeBlock, adr);
  768. LOOP
  769. IF size = 0 THEN EXIT END;
  770. DEC(size);
  771. FOR i := 0 TO LEN(staticTypeBlock.pointerOffsets) - 1 DO
  772. Relocate(p + staticTypeBlock.pointerOffsets[i]);
  773. END;
  774. INC(p, staticTypeBlock.recSize) (* step to next array element *)
  775. END
  776. END RelocateArrayFields;
  777. (* RelocateExports - Relocate export arrays. *)
  778. PROCEDURE RelocateExports;
  779. VAR type: TypeDesc; i: LONGINT;
  780. BEGIN
  781. type := ThisType(ModuleByName(ExportDescModule), ExportDescType);
  782. ASSERT(type # NIL);
  783. FOR i := 0 TO exportTags - 1 DO
  784. SYSTEM.PUT(exportTagAdr[i], type.tag);
  785. Relocate(exportTagAdr[i]);
  786. RelocateArrayFields(exportTagAdr[i]);
  787. END
  788. END RelocateExports;
  789. (* RelocateProcOffsets - relocate the contents of the global table procOffsets, see InitTable for relocation of the global pointers *)
  790. PROCEDURE RelocateProcOffsets;
  791. VAR i: LONGINT;
  792. BEGIN
  793. FOR i := 0 TO numProcs - 1 DO (* relocation of code addresses in procOffsets *)
  794. Relocate(ADDRESSOF(procOffsets[i].data.pcFrom));
  795. Relocate(ADDRESSOF(procOffsets[i].data.pcLimit));
  796. Relocate(ADDRESSOF(procOffsets[i].data.pcStatementBegin));
  797. Relocate(ADDRESSOF(procOffsets[i].data.pcStatementEnd));
  798. END;
  799. END RelocateProcOffsets;
  800. PROCEDURE FixupTypeDescTags;
  801. VAR type: TypeDesc; i: LONGINT; m: Module; adr: ADDRESS;
  802. BEGIN
  803. type := ThisType(ModuleByName(TypeDescModule), TypeDescType);
  804. ASSERT(type # NIL);
  805. m := SYSTEM.VAL(Module, root);
  806. WHILE m # NIL DO
  807. FOR i := 0 TO LEN(m.typeInfo) - 1 DO
  808. adr := SYSTEM.VAL(ADDRESS, m.typeInfo[i]);
  809. SYSTEM.PUT(adr + TypeDescOffset, type.tag);
  810. Relocate(adr + TypeDescOffset);
  811. END;
  812. m := m.next
  813. END
  814. END FixupTypeDescTags;
  815. PROCEDURE FixupHeapBlockTags;
  816. VAR type: TypeDesc; m: Module; heapBlock {UNTRACED}: HeapBlock; adr, heapBlockAdr: ADDRESS; val: LONGINT;
  817. BEGIN
  818. m := ModuleByName(HeapModule); ASSERT(m # NIL);
  819. type := ThisType(m, FreeBlockDescType); ASSERT(type # NIL); freeBlockTag := type.tag;
  820. type := ThisType(m, SystemBlockDescType); ASSERT(type # NIL); systemBlockTag := type.tag;
  821. type := ThisType(m, RecordBlockDescType); ASSERT(type # NIL); recordBlockTag := type.tag;
  822. type := ThisType(m, ProtRecBlockDescType); ASSERT(type # NIL); protRecBlockTag := type.tag;
  823. type := ThisType(m, ArrayBlockDescType); ASSERT(type # NIL); arrayBlockTag := type.tag;
  824. adr := beginMemBlockAdr;
  825. WHILE adr < endMemBlockAdr DO
  826. heapBlockAdr := adr + BlockHeaderSize;
  827. SYSTEM.GET(heapBlockAdr + TypeDescOffset, val); (* tag field of heap block p *)
  828. CASE val OF
  829. FreeBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, freeBlockTag);
  830. | SystemBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, systemBlockTag);
  831. | RecordBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, recordBlockTag);
  832. | ProtRecBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, protRecBlockTag);
  833. | ArrayBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, arrayBlockTag);
  834. END;
  835. Relocate(heapBlockAdr + TypeDescOffset);
  836. heapBlock := SYSTEM.VAL(HeapBlock, heapBlockAdr);
  837. adr := adr + heapBlock.size
  838. END;
  839. END FixupHeapBlockTags;
  840. (* SortRelocates - Sort the relocates. *)
  841. PROCEDURE SortRelocates;
  842. VAR h, i, j: LONGINT; p: ADDRESS;
  843. BEGIN
  844. h := 1; REPEAT h := h*3 + 1 UNTIL h > relocates;
  845. REPEAT
  846. h := h DIV 3; i := h;
  847. WHILE i < relocates DO
  848. p := relocateAdr[i]; j := i;
  849. WHILE (j >= h) & (relocateAdr[j-h] > p) DO
  850. relocateAdr[j] := relocateAdr[j-h]; j := j-h;
  851. END;
  852. relocateAdr[j] := p; INC(i)
  853. END
  854. UNTIL h = 1;
  855. IF ~TraceDuplicates THEN
  856. FOR i := 1 TO relocates-1 DO ASSERT(relocateAdr[i-1] < relocateAdr[i]) END (* sorted, without dups *)
  857. END
  858. END SortRelocates;
  859. (* GetNum - Get a compressed refblk number. *)
  860. PROCEDURE GetNum(refs: Bytes; VAR i, num: LONGINT);
  861. VAR n, s: LONGINT; x: CHAR;
  862. BEGIN
  863. s := 0; n := 0;
  864. x := refs[i]; INC(i);
  865. WHILE ORD(x) >= 128 DO
  866. INC(n, ASH(ORD(x) - 128, s));
  867. INC(s, 7);
  868. x := refs[i]; INC(i)
  869. END;
  870. num := n + ASH(ORD(x) MOD 64 - ORD(x) DIV 64 * 64, s)
  871. END GetNum;
  872. (* VarByName - Find a global variable in the reference block. *)
  873. PROCEDURE VarByName(refs: Bytes; i: LONGINT; CONST name: ARRAY OF CHAR): SIZE;
  874. VAR mode: CHAR; j, m, adr, type, t: LONGINT; s: Name; found: BOOLEAN;
  875. BEGIN
  876. m := LEN(refs^); found := FALSE;
  877. mode := refs[i]; INC(i);
  878. WHILE (i < m) & ((mode = 1X) OR (mode = 3X)) & ~found DO (* var *)
  879. type := ORD(refs[i]); INC(i);
  880. IF (type >= 81H) OR (type = 16H) OR (type = 1DH) THEN
  881. GetNum(refs, i, t) (* dim/tdadr *)
  882. END;
  883. GetNum(refs, i, adr);
  884. j := 0; REPEAT s[j] := refs[i]; INC(i); INC(j) UNTIL s[j-1] = 0X;
  885. IF s = name THEN found := TRUE
  886. ELSIF i < m THEN mode := refs[i]; INC(i)
  887. END
  888. END;
  889. IF found THEN
  890. ASSERT((mode = 1X) & ((type = 0DH) OR (type = 1DH) OR (type = 06H))) (* pointer or LInt VAR *)
  891. ELSE
  892. adr := 0
  893. END;
  894. RETURN SYSTEM.VAL(SIZE, adr)
  895. END VarByName;
  896. (* InitTable - Generate init code for module bodies. *)
  897. PROCEDURE InitTable(diff: SIZE; baseAdr, loadAdr: ADDRESS);
  898. VAR i, n: LONGINT; adr: ADDRESS; m: Module;
  899. PROCEDURE InitBody(m: Module);
  900. BEGIN
  901. IF m = NIL THEN
  902. (* allocate block for init calls of n modules - each call requires 5 bytes (1 byte for the opcode and 4 bytes for the call address) - and some
  903. extra code following it, see body of InitTable *)
  904. NewSys(initBlock, 5*n + (5+3)); adr := SYSTEM.VAL(ADDRESS, initBlock)
  905. ELSE
  906. INC(n); InitBody(m.next);
  907. Address(ADDRESSOF(m.code[0])+diff); Char("H"); Char(" ");
  908. Address(ADDRESSOF(m.data[0])+diff); Char("H"); Char(" ");
  909. String(m.name); Ln;
  910. SYSTEM.PUT(adr, 0E8X); (* CALL *)
  911. SYSTEM.PUT(adr+1, ADDRESSOF(m.code[0]) - (adr+5)); (* call address *)
  912. INC(adr, 5)
  913. END
  914. END InitBody;
  915. BEGIN
  916. String("BEGIN"); Ln;
  917. n := 0; InitBody(SYSTEM.VAL(Module, root));
  918. String("END"); Ln;
  919. (* startup command *)
  920. m := ModuleByName(StartModule);
  921. i := 0; WHILE m.command[i].name # StartCommand DO INC(i) END;
  922. Address(SYSTEM.VAL(ADDRESS, m.command[i].entryAdr)+diff); Char(" ");
  923. String(m.name); Char("."); String(StartCommand); Ln;
  924. SYSTEM.PUT(adr, 0E8X); (* CALL *)
  925. SYSTEM.PUT(adr+1, SYSTEM.VAL(LONGINT, m.command[i].entryAdr) - (adr+5));
  926. INC(adr, 5);
  927. (* HALT *)
  928. SYSTEM.PUT(adr, 6AX); (* PUSH imm8 *)
  929. SYSTEM.PUT(adr+1, 0FFX);
  930. SYSTEM.PUT(adr+2, 0CCX); (* INT 3 *)
  931. (* init table *)
  932. FOR adr := beginAdr TO beginAdr+HeaderSize-1 DO
  933. SYSTEM.PUT(adr, 0X)
  934. END;
  935. IF baseAdr = loadAdr THEN
  936. SYSTEM.PUT(beginAdr, 0E8X); (* CALL *)
  937. SYSTEM.PUT(beginAdr+1, SYSTEM.VAL(ADDRESS, initBlock) - (beginAdr+5))
  938. ELSE (* image will relocate itself *)
  939. adr := beginAdr;
  940. SYSTEM.PUT(adr, 60X); (* PUSHAD *)
  941. INC(adr);
  942. SYSTEM.PUT(adr, 0BEX); (* MOV ESI, X *)
  943. SYSTEM.PUT(adr+1, loadAdr);
  944. INC(adr, 5);
  945. SYSTEM.PUT(adr, 0BFX); (* MOV EDI, X *)
  946. SYSTEM.PUT(adr+1, baseAdr);
  947. INC(adr, 5);
  948. SYSTEM.PUT(adr, 0B9X); (* MOV ECX, X *)
  949. SYSTEM.PUT(adr+1, (freeAdr-beginAdr+3) DIV 4); (* length of image in dwords *)
  950. INC(adr, 5);
  951. SYSTEM.PUT(adr, 0FCX); (* CLD *)
  952. SYSTEM.PUT(adr+1, 0F3X); (* REP *)
  953. SYSTEM.PUT(adr+2, 0A5X); (* MOVSD *)
  954. INC(adr, 3);
  955. SYSTEM.PUT(adr, 61X); (* POPAD *)
  956. INC(adr);
  957. SYSTEM.PUT(adr, 0E8X); (* CALL *)
  958. SYSTEM.PUT(adr+1, SYSTEM.VAL(ADDRESS, initBlock) - (adr+5) + (baseAdr-loadAdr));
  959. INC(adr, 5);
  960. ASSERT(adr-beginAdr <= EndBlockOfs) (* not too much code *)
  961. END;
  962. SYSTEM.PUT(beginAdr + EndBlockOfs, freeAdr); Relocate(beginAdr + EndBlockOfs)
  963. END InitTable;
  964. PROCEDURE RootGlobals;
  965. VAR m: Module; i: LONGINT; ofs: SIZE;
  966. BEGIN
  967. (* root init block pointer *)
  968. m := ModuleByName(InitPtrModule);
  969. ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
  970. i := 5; ofs := VarByName(m.refs, i, InitPtrName); ASSERT(ofs # 0);
  971. SYSTEM.PUT(m.sb + ofs, initBlock); Relocate(m.sb + ofs);
  972. (* module root pointer, pointer to global procOffsets and ptrOffsets table, number of valid entries in procOffsets and ptrOffsets*)
  973. m := ModuleByName(ModRootModule);
  974. ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
  975. i := 5;
  976. ofs := VarByName(m.refs, i, ModRootName); ASSERT(ofs # 0);
  977. SYSTEM.PUT(m.sb + ofs, root); Relocate(m.sb + ofs);
  978. ofs := VarByName(m.refs, i, ProcOffsetsName); ASSERT(ofs # 0);
  979. SYSTEM.PUT(m.sb + ofs, SYSTEM.VAL(ADDRESS, procOffsets)); Relocate(m.sb + ofs);
  980. ofs := VarByName(m.refs, i, NumProcsName); ASSERT(ofs # 0);
  981. SYSTEM.PUT(m.sb + ofs, numProcs);
  982. ofs := VarByName(m.refs, i, PtrOffsetsName); ASSERT(ofs # 0);
  983. SYSTEM.PUT(m.sb + ofs, SYSTEM.VAL(ADDRESS, ptrOffsets)); Relocate(m.sb + ofs);
  984. ofs := VarByName(m.refs, i, NumPtrsName); ASSERT(ofs # 0);
  985. SYSTEM.PUT(m.sb + ofs, numPtrs);
  986. (* write tag addresses as pointer values since the reference section does not contain variables of type ADDRESS *)
  987. (* patching of Type Tags not necessary any more -- cf. Module Heaps *)
  988. m := ModuleByName(HeapModule);
  989. ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
  990. i := 5;
  991. ofs := VarByName(m.refs, i, CurrentMarkValueName); ASSERT(ofs # 0);
  992. SYSTEM.PUT(m.sb + ofs, currentMarkValue)
  993. END RootGlobals;
  994. (* ScopeInfo - Write information for debugger. *)
  995. PROCEDURE ScopeInfo(diff: SIZE; baseAdr: ADDRESS; root: Module);
  996. VAR main: ADDRESS; m: Module; i: LONGINT;
  997. BEGIN
  998. m := root; WHILE (m # NIL) & (m.name # MainModule) DO m := m.next END;
  999. IF m = NIL THEN main := -1 ELSE main := ADDRESSOF(m.code[0])+diff END;
  1000. IF main = -1 THEN String(MainModule); String(" not found"); Ln END;
  1001. String("SCOPE.BEGIN 0"); Address(baseAdr); String("H 0"); Address(main); Char("H"); Ln;
  1002. m := root;
  1003. WHILE m # NIL DO
  1004. String(" "); String(m.name); String(" 0");
  1005. Address(ADDRESSOF(m.code[0])+diff); String("H 0");
  1006. Hex(LEN(m.code), 8); String("H 0");
  1007. Address(m.sb); String("H "); Int(LEN(m.typeInfo), 1); Ln;
  1008. FOR i := 0 TO LEN(m.typeInfo)-1 DO
  1009. String(" 0"); Hex(-1, 8); String("H 0");
  1010. Address(SYSTEM.VAL(ADDRESS, m.typeInfo[i].tag)+diff); Char("H"); Ln
  1011. END;
  1012. m := m.next
  1013. END;
  1014. String("SCOPE.END"); Ln
  1015. END ScopeInfo;
  1016. (* ug *)
  1017. PROCEDURE CheckLinkerHeap; (* ug: for debugging *)
  1018. VAR p, tagAdr, typeDescAdr: ADDRESS; heapBlock: HeapBlock;
  1019. BEGIN
  1020. (* find last block in static heap *)
  1021. p := beginMemBlockAdr;
  1022. heapBlock := SYSTEM.VAL(HeapBlock, p + BlockHeaderSize);
  1023. WHILE p < endMemBlockAdr DO
  1024. SYSTEM.GET(SYSTEM.VAL(ADDRESS, heapBlock) + TypeDescOffset, tagAdr);
  1025. IF tagAdr = freeBlockTag THEN
  1026. String("FreeBlock at adr = "); Address(p); Ln
  1027. ELSIF tagAdr = systemBlockTag THEN
  1028. String("SystemBlock at adr = "); Address(p); Ln
  1029. ELSIF tagAdr = recordBlockTag THEN
  1030. SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
  1031. String("RecordBlock at adr = "); Address(p); String(" type = "); WriteType(typeDescAdr); Ln
  1032. ELSIF tagAdr = protRecBlockTag THEN
  1033. SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
  1034. String("ProtRecBlock at adr = "); Address(p); String(" type = "); WriteType(typeDescAdr); Ln
  1035. ELSIF tagAdr = arrayBlockTag THEN
  1036. SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
  1037. String("ArrayBlock at adr = "); Address(p); String(" element type = "); WriteType(typeDescAdr); Ln
  1038. ELSE
  1039. HALT(9999)
  1040. END;
  1041. p := p + heapBlock.size;
  1042. heapBlock := SYSTEM.VAL(HeapBlock, p + BlockHeaderSize)
  1043. END
  1044. END CheckLinkerHeap;
  1045. (** Close - Finalize the log file etc. *)
  1046. PROCEDURE Close*(w: Files.Writer; loadAdr: ADDRESS; res: LONGINT; CONST msg: ARRAY OF CHAR; log: Streams.Writer);
  1047. VAR i: LONGINT; adr: ADDRESS; diff: SIZE; ch: CHAR;
  1048. BEGIN
  1049. IF res = 0 THEN
  1050. IF baseAdr = -1 THEN diff := 0 ELSE diff := baseAdr - beginAdr END;
  1051. FixupTypeDescTags;
  1052. InitTable(diff, baseAdr, loadAdr); (* InitTable call before FixupHeapBlockTags since InitTable creates new heap block, i.e. init block *)
  1053. (* no heap block allocations in linker heap from this point on *)
  1054. memBlock.endBlockAdr := freeAdr; (* set correct end block address of linker heap *)
  1055. memBlock.size := freeAdr - beginMemBlockAdr; (* set correct size of whole memory block *)
  1056. FixupHeapBlockTags; (* FixupHeapBlockTags before RootGlobals since heap block tags will be rooted in boot file *)
  1057. RootGlobals;
  1058. ScopeInfo(diff, baseAdr, SYSTEM.VAL(Module, root));
  1059. RelocateMemoryBlock;
  1060. RelocateModules;
  1061. RelocateProcOffsets;
  1062. RelocateExports;
  1063. (* relocate addresses *)
  1064. FOR i := 0 TO relocates-1 DO
  1065. SYSTEM.GET(relocateAdr[i], adr);
  1066. IF adr # 0 THEN
  1067. IF ~(((adr > beginMemBlockAdr) & (adr <= freeAdr))) THEN
  1068. KernelLog.String("problem with adr in Linker0.Close ");
  1069. KernelLog.Int(beginMemBlockAdr,1);
  1070. KernelLog.String("<=");
  1071. KernelLog.Int(adr,1);
  1072. KernelLog.String("<=");
  1073. KernelLog.Int(freeAdr,1);
  1074. KernelLog.String(" at "); KernelLog.Int(i,1); KernelLog.String(":"); KernelLog.Int(relocates,1);
  1075. KernelLog.String(" Check for fixup duplicates ! ");
  1076. KernelLog.Ln;
  1077. END;
  1078. (*ASSERT((adr > beginMemBlockAdr) & (adr <= freeAdr));*)
  1079. SYSTEM.PUT(relocateAdr[i], adr + diff)
  1080. END
  1081. END;
  1082. (* output *)
  1083. IF TraceDump THEN
  1084. SortRelocates; curRelocate := 0; (* for highlighting of relocations *)
  1085. Memory(beginAdr, freeAdr - beginAdr);
  1086. ASSERT(curRelocate = -1) (* all relocations highlighted *)
  1087. END;
  1088. String(" exports: "); Int(exportTags, 1); String(" relocates: "); Int(relocates, 1);
  1089. IF TraceRefs THEN String(" possible missed references: "); Int(refsMissed, 1) END;
  1090. Ln;
  1091. FOR adr := beginAdr TO freeAdr - 1 DO
  1092. SYSTEM.GET(adr, ch);
  1093. w.Char( ch)
  1094. END;
  1095. FOR adr := 1 TO AddressSize DO
  1096. w.Char(0X)
  1097. END;
  1098. String("Written bytes"); Char(" "); Address(freeAdr - beginAdr+AddressSize); Ln
  1099. END;
  1100. String("Result = "); Int(res, 1); Char(" "); String(msg); Ln; logWriter.Update;
  1101. IF res = 0 THEN
  1102. log.String("Linker0 Ok. #Bytes= "); log.Address(freeAdr - beginAdr);
  1103. IF logFile # NIL THEN
  1104. log.String(" "); log.String(LogName);
  1105. END;
  1106. ELSE
  1107. log.String( "Error report in "); log.String( LogName);
  1108. END;
  1109. log.Ln;
  1110. IF logFile # NIL THEN
  1111. logWriter.Update();
  1112. logFile.Update();
  1113. Files.Register(logFile);
  1114. logFile := NIL; logWriter := NIL
  1115. END;
  1116. END Close;
  1117. (* NewModule - Allocate a module descriptor (protected record) *)
  1118. PROCEDURE NewModule*(VAR m: Module);
  1119. VAR size, blockSize: SIZE; protRecBlockAdr, dataBlockAdr: ADDRESS;
  1120. protRecBlock: ProtRecBlock; i: LONGINT;
  1121. BEGIN
  1122. size := SYSTEM.GET32(SYSTEM.TYPECODE(Module));
  1123. blockSize := BlockHeaderSize + SIZEOF(ProtRecBlockDesc) + BlockHeaderSize + size;
  1124. INC(blockSize, (-blockSize) MOD BlockSize); (* round up to multiple of BlockSize *)
  1125. protRecBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
  1126. SYSTEM.PUT(protRecBlockAdr + TypeDescOffset, ProtRecBlockId);
  1127. SYSTEM.PUT(protRecBlockAdr + HeapBlockOffset, NilVal);
  1128. dataBlockAdr := protRecBlockAdr + SIZEOF(ProtRecBlockDesc) + BlockHeaderSize;
  1129. SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* will be set later *)
  1130. SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, protRecBlockAdr);
  1131. Relocate(dataBlockAdr + HeapBlockOffset);
  1132. protRecBlock := SYSTEM.VAL(ProtRecBlock, protRecBlockAdr);
  1133. protRecBlock.mark := currentMarkValue;
  1134. protRecBlock.dataAdr := dataBlockAdr;
  1135. protRecBlock.nextRealtime := NIL; (* default value NIL since module is never a realtime object *)
  1136. Relocate(ADDRESSOF(protRecBlock.dataAdr));
  1137. Relocate(ADDRESSOF(protRecBlock.nextRealtime));
  1138. protRecBlock.size := blockSize;
  1139. protRecBlock.count := 0;
  1140. protRecBlock.awaitingLock.head := NIL;
  1141. protRecBlock.awaitingLock.tail := NIL;
  1142. protRecBlock.awaitingCond.head := NIL;
  1143. protRecBlock.awaitingCond.tail := NIL;
  1144. protRecBlock.lockedBy := NIL;
  1145. protRecBlock.lock := NIL;
  1146. FOR i := 0 TO NumPriorities - 1 DO
  1147. protRecBlock.waitingPriorities[i] := 0
  1148. END;
  1149. INC(protRecBlock.waitingPriorities[0]); (* set sentinel value: assume that idle process with priority 0 waits on this resource *)
  1150. m := SYSTEM.VAL(Module, dataBlockAdr);
  1151. Fill4(dataBlockAdr, (blockSize - SIZEOF(ProtRecBlockDesc) - 2 * BlockHeaderSize) DIV 4, 0); (* clear everything except tag & header *)
  1152. END NewModule;
  1153. (* NewExportDesc - Allocate an export array. *)
  1154. PROCEDURE NewExportDesc*(VAR p: ExportArray; numElems: LONGINT);
  1155. VAR adr: ADDRESS; block: ANY;
  1156. BEGIN
  1157. NewRealArr(block, numElems, SIZEOF(ExportDesc), 1);
  1158. adr := SYSTEM.VAL(ADDRESS, block);
  1159. SYSTEM.PUT(adr + LenOfs, numElems);
  1160. p := SYSTEM.VAL(ExportArray, block);
  1161. IF exportTags = LEN(exportTagAdr) THEN GrowTable(exportTagAdr) END;
  1162. exportTagAdr[exportTags] := adr + TypeDescOffset; INC(exportTags);
  1163. END NewExportDesc;
  1164. PROCEDURE ArraySize*(numElems, elemSize: SIZE; numDims: LONGINT): SIZE;
  1165. VAR arrSize, arrayDataOffset: SIZE;
  1166. BEGIN
  1167. arrSize := numElems * elemSize;
  1168. arrayDataOffset := numDims * AddressSize + 3 * AddressSize;
  1169. INC(arrayDataOffset,(-arrayDataOffset) MOD ArrayAlignment); (* align to multiple of ArrayAlignment *)
  1170. RETURN arrayDataOffset + arrSize
  1171. END ArraySize;
  1172. (* NewProcOffsets - Allocate a procedure offset table *)
  1173. PROCEDURE NewProcOffsets(VAR p: ProcOffsetTable; numElems: LONGINT);
  1174. VAR adr: ADDRESS; block: ANY;
  1175. BEGIN
  1176. NewSys(block, ArraySize(numElems, SIZEOF(ProcOffsetEntry), 1));
  1177. adr := SYSTEM.VAL(ADDRESS, block);
  1178. SYSTEM.PUT(adr + LenOfs, numElems);
  1179. p := SYSTEM.VAL(ProcOffsetTable, block)
  1180. END NewProcOffsets;
  1181. (* NewPtrOffsets - Allocate a pointer offset table *)
  1182. PROCEDURE NewPtrOffsets(VAR p: PtrTable; numElems: LONGINT);
  1183. VAR adr: ADDRESS; block: ANY;
  1184. BEGIN
  1185. NewSys(block, ArraySize(numElems, SIZEOF(SIZE), 1));
  1186. adr := SYSTEM.VAL(ADDRESS, block);
  1187. SYSTEM.PUT(adr + LenOfs, numElems);
  1188. p := SYSTEM.VAL(PtrTable, block)
  1189. END NewPtrOffsets;
  1190. (* fit memory block at given start address - relocation of addresses is done later, see RelocateMemoryBlock *)
  1191. PROCEDURE FitMemoryBlock(startAdr: ADDRESS; size: SIZE; VAR memBlock: MemoryBlock);
  1192. VAR blockSize: SIZE; recordBlock: RecordBlock; recordBlockAdr, dataBlockAdr: ADDRESS;
  1193. BEGIN
  1194. blockSize := BlockHeaderSize + SIZEOF(RecordBlockDesc) + BlockHeaderSize + SIZEOF(MemoryBlockDesc);
  1195. INC(blockSize,(-blockSize) MOD BlockSize); (* align to multiple of BlockSize *)
  1196. recordBlockAdr := startAdr + BlockHeaderSize;
  1197. SYSTEM.PUT(recordBlockAdr + TypeDescOffset, RecordBlockId); (* temporary tag value, fixup and relocation are done later *)
  1198. SYSTEM.PUT(recordBlockAdr + HeapBlockOffset, NilVal);
  1199. dataBlockAdr := recordBlockAdr + SIZEOF(RecordBlockDesc) + BlockHeaderSize;
  1200. SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* type descriptor tag will be filled in FixupTypeDescTags *)
  1201. SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, recordBlockAdr); (* reference to heap block descriptor *)
  1202. recordBlock := SYSTEM.VAL(RecordBlock, recordBlockAdr);
  1203. recordBlock.mark := currentMarkValue;
  1204. recordBlock.dataAdr := dataBlockAdr;
  1205. recordBlock.size := blockSize;
  1206. recordBlock.nextRealtime := NIL;
  1207. memBlock := SYSTEM.VAL(MemoryBlock, dataBlockAdr);
  1208. memBlock.next := NIL;
  1209. memBlock.startAdr := NilVal; (* will be set by Win32.Machine.Mod, unused for I386.Machine.Mod *)
  1210. memBlock.size := 0; (* do. *)
  1211. memBlock.beginBlockAdr := startAdr + blockSize;
  1212. memBlock.endBlockAdr := startAdr + size;
  1213. ASSERT(memBlock.beginBlockAdr < memBlock.endBlockAdr);
  1214. ASSERT(memBlock.beginBlockAdr MOD BlockSize = 0);
  1215. ASSERT(memBlock.endBlockAdr MOD BlockSize = 0);
  1216. END FitMemoryBlock;
  1217. (* relocate addresses of memory block *)
  1218. PROCEDURE RelocateMemoryBlock;
  1219. VAR type: TypeDesc; memBlockAdr: ADDRESS; recordBlock: RecordBlock;
  1220. BEGIN
  1221. type := ThisType(ModuleByName(MemBlockDescModule), MemBlockDescType);
  1222. ASSERT(type # NIL);
  1223. memBlockAdr := SYSTEM.VAL(ADDRESS, memBlock);
  1224. SYSTEM.PUT(memBlockAdr + TypeDescOffset, type.tag);
  1225. Relocate(memBlockAdr + TypeDescOffset);
  1226. Relocate(memBlockAdr + HeapBlockOffset);
  1227. SYSTEM.GET(memBlockAdr + HeapBlockOffset, recordBlock);
  1228. (* type descriptor field of record block is relocated in FixupHeapBlockTags *)
  1229. Relocate(ADDRESSOF(recordBlock.dataAdr));
  1230. Relocate(ADDRESSOF(recordBlock.nextRealtime));
  1231. Relocate(ADDRESSOF(memBlock.beginBlockAdr));
  1232. Relocate(ADDRESSOF(memBlock.endBlockAdr))
  1233. END RelocateMemoryBlock;
  1234. (* InitHeap - Initialize the virtual heap. *)
  1235. PROCEDURE InitHeap;
  1236. VAR freeBlock: FreeBlock; alignOffset: SIZE;
  1237. BEGIN
  1238. SYSTEM.NEW(heap, HeapSize);
  1239. beginMemBlockAdr := SYSTEM.VAL(ADDRESS, heap) + HeaderSize;
  1240. alignOffset := (-beginMemBlockAdr) MOD BlockSize;
  1241. beginMemBlockAdr := beginMemBlockAdr + alignOffset; (* round up to multiple of BlockSize *)
  1242. beginAdr := beginMemBlockAdr - HeaderSize;
  1243. endMemBlockAdr := beginMemBlockAdr + HeapSize - HeaderSize - alignOffset;
  1244. DEC(endMemBlockAdr, endMemBlockAdr MOD BlockSize);
  1245. ASSERT(beginMemBlockAdr < endMemBlockAdr);
  1246. ASSERT(beginMemBlockAdr MOD BlockSize = 0);
  1247. ASSERT(endMemBlockAdr MOD BlockSize = 0);
  1248. (* represent linker heap as one large memory block that contains a single free heap block *)
  1249. FitMemoryBlock(beginMemBlockAdr, endMemBlockAdr - beginMemBlockAdr, memBlock);
  1250. freeBlock := SYSTEM.VAL(FreeBlock, memBlock.beginBlockAdr + BlockHeaderSize);
  1251. InitFreeBlock(freeBlock, Unmarked, NilVal, memBlock.endBlockAdr - memBlock.beginBlockAdr);
  1252. END InitHeap;
  1253. (*
  1254. Reference = {OldRef | ProcRef} .
  1255. OldRef = 0F8X offset/n name/s {Variable} .
  1256. ProcRef = 0F9X offset/n nofPars/n RetType procLev/1 slFlag/1 name/s {Variable} .
  1257. RetType = 0X | Var | ArrayType | Record .
  1258. ArrayType = 12X | 14X | 15X . (* static array, dynamic array, open array *)
  1259. Record = 16X .
  1260. Variable = VarMode (Var | ArrayVar | RecordVar ) offset/n name/s .
  1261. VarMode = 1X | 3X . (* direct, indirect *)
  1262. Var = 1X .. 0FX . (* byte, boolean, char, shortint, integer, longint, real, longreal, set, ptr, proc, string *)
  1263. ArrayVar = (81X .. 8EX) dim/n . (* byte, boolean, char, shortint, integer, longint, real, longreal, set, ptr, proc *)
  1264. RecordVar = (16X | 1DX) tdadr/n . (* record, recordpointer *)
  1265. *)
  1266. (* ProcByName - Find a procedure in the reference block. Return procedure offset, or -1 if not found. *)
  1267. PROCEDURE ProcByName (refs: Bytes; CONST name: ARRAY OF CHAR): SIZE;
  1268. VAR i, j, m, t, pofs: LONGINT; ch: CHAR; found: BOOLEAN;
  1269. BEGIN
  1270. i := 0; m := LEN(refs^); found := FALSE;
  1271. ch := refs[i]; INC(i);
  1272. WHILE (i < m) & ((ch = 0F8X) OR (ch = 0F9X)) & ~found DO (* proc *)
  1273. GetNum(refs, i, pofs);
  1274. IF ch = 0F9X THEN
  1275. GetNum(refs, i, t); (* nofPars *)
  1276. INC(i, 3) (* RetType, procLev, slFlag *)
  1277. END;
  1278. j := 0; WHILE (name[j] = refs[i]) & (name[j] # 0X) DO INC(i); INC(j) END;
  1279. IF (name[j] = 0X) & (refs[i] = 0X) THEN
  1280. found := TRUE
  1281. ELSE
  1282. WHILE refs[i] # 0X DO INC(i) END;
  1283. INC(i);
  1284. IF i < m THEN
  1285. ch := refs[i]; INC(i); (* 1X | 3X | 0F8X | 0F9X *)
  1286. WHILE (i < m) & ((ch = 1X) OR (ch = 3X)) DO (* var *)
  1287. ch := refs[i]; INC(i); (* type *)
  1288. IF (ch >= 81X) OR (ch = 16X) OR (ch = 1DX) THEN
  1289. GetNum(refs, i, t) (* dim/tdadr *)
  1290. END;
  1291. GetNum(refs, i, t); (* vofs *)
  1292. REPEAT ch := refs[i]; INC(i) UNTIL ch = 0X; (* vname *)
  1293. ch := refs[i]; INC(i) (* 1X | 3X | 0F8X | 0F9X *)
  1294. END
  1295. END
  1296. END
  1297. END;
  1298. IF ~found THEN pofs := -1 END;
  1299. RETURN SYSTEM.VAL(SIZE, pofs)
  1300. END ProcByName;
  1301. (* GetProc - Return procedure address. *)
  1302. PROCEDURE GetProc(m: Module; i: LONGINT; CONST mod, proc: ARRAY OF CHAR): ADDRESS;
  1303. VAR adr: SIZE;
  1304. BEGIN
  1305. IF m.name # mod THEN (* fixup not in current module *)
  1306. m := ModuleByName(mod) (* must have been loaded already *)
  1307. END;
  1308. adr := ProcByName(m.refs, proc);
  1309. IF ~getProcs[i] THEN
  1310. String("GetProc "); String(mod); Char("."); String(proc); Address(adr); Ln;
  1311. getProcs[i] := TRUE
  1312. END;
  1313. ASSERT(adr # -1);
  1314. RETURN ADDRESSOF(m.code[0]) + adr
  1315. END GetProc;
  1316. (* GetKernelProc - Return the specified kernel procedure. *)
  1317. PROCEDURE GetKernelProc*(m: Module; num: LONGINT): ADDRESS;
  1318. VAR adr: ADDRESS;
  1319. BEGIN
  1320. CASE num OF
  1321. |243: adr := GetProc(m, 8, "Modules", "GetProcedure")
  1322. |246: adr := GetProc(m, 1, "Objects", "Unlock")
  1323. |247: adr := GetProc(m, 2, "Objects", "Lock")
  1324. |249: adr := GetProc(m, 3, "Objects", "Await")
  1325. |250: adr := GetProc(m, 4, "Objects", "CreateProcess")
  1326. |251: adr := GetProc(m, 5, "Heaps", "NewArr")
  1327. |252: adr := GetProc(m, 6, "Heaps", "NewSys")
  1328. |253: adr := GetProc(m, 7, "Heaps", "NewRec")
  1329. END;
  1330. RETURN adr
  1331. END GetKernelProc;
  1332. (** Dump the log text . Use in case of trap. *)
  1333. PROCEDURE WriteLog*;
  1334. BEGIN
  1335. logWriter.Update(); logFile.Update(); Files.Register(logFile); logFile := NIL; logWriter := NIL;
  1336. KernelLog.String(LogName); KernelLog.Ln;
  1337. END WriteLog;
  1338. BEGIN
  1339. suffix := DefaultExtension; prefix := "";
  1340. logFile := NIL; logWriter := NIL;
  1341. currentMarkValue := Unmarked + 1; (* one higher than the mark value of the free block *);
  1342. NEW(relocateAdr, 2048); NEW(exportTagAdr, 32)
  1343. END Linker0.
  1344. (*
  1345. 19.05.98 pjm Started
  1346. 23.05.99 pjm Fixed Find for non-sorted tables
  1347. *)
  1348. Linker0.Find 10A3C4H
  1349. Linker0.WriteLog
  1350. SystemTools.Free PELinker Linker1 Linker0 ~