12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559 |
- (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
- MODULE Linker0; (* pjm *)
- (* Aos Bootlinfker auxiliary module *)
- (* fof: modifications for address sizes other than 4, mainly modified New* Procedures and offsets, tried to get some more documentation into the program text *)
- IMPORT SYSTEM, Streams, Files, KernelLog;
- CONST
- DefaultExtension = ".Obx";
- HeapSize = 1024*1024 (*630*1024;*); (* linker heap size *)
- AddressSize = SIZEOF (ADDRESS);
- LenOfs = 3 * AddressSize; (* offset of first array dimension in SysBlk or ArrayBlk *)
- Unmarked = 0; (* mark value of free block *)
- (* fixup identifiers - also see GetKernelProc *)
- MemBlockDescModule = "Machine"; MemBlockDescType = "MemoryBlockDesc";
- ModDescModule = "Modules"; ModDescType = "Module";
- TypeDescModule = "Modules"; TypeDescType = "TypeDesc";
- HdPtrDescModule = "Loader"; HdPtrDescType = "@HdPtrDesc";
- ExportDescModule = "Modules"; ExportDescType = "ExportDesc";
- InitPtrModule = "Modules"; InitPtrName = "initBlock";
- ModRootModule = "Modules"; ModRootName = "root";
- ProcOffsetsName = "procOffsets"; NumProcsName = "numProcs";
- PtrOffsetsName = "ptrOffsets"; NumPtrsName = "numPtrs";
- HeapModule = "Heaps";
- FreeBlockDescType = "FreeBlockDesc"; SystemBlockDescType = "SystemBlockDesc"; RecordBlockDescType = "RecordBlockDesc";
- ProtRecBlockDescType = "ProtRecBlockDesc"; ArrayBlockDescType = "ArrayBlockDesc";
- FreeBlockTagPtrName = "freeBlockTagPtr"; SystemBlockTagPtrName = "systemBlockTagPtr"; RecordBlockTagPtrName = "recordBlockTagPtr";
- ProtRecBlockTagPtrName = "protRecBlockTagPtr"; ArrayBlockTagPtrName = "arrayBlockTagPtr";
- CurrentMarkValueName = "currentMarkValue";
- StartModule = "Objects"; StartCommand = "Terminate";
- MainModule = "BootConsole";
- (* id field temporarily stored in tag field of heap block, fixup in FixupHeapBlockTags *)
- FreeBlockId = 0;
- SystemBlockId = 1;
- RecordBlockId = 2;
- ProtRecBlockId = 3;
- ArrayBlockId = 4;
- ProtectedModule = TRUE; (* is module descriptor protected? *)
- TraceDump = FALSE; (* should full dump be displayed? *)
- TraceRefs = TRUE & TraceDump; (* conservatively look for "missed" internal references? *)
- TraceDuplicates = FALSE & TraceDump; (* should duplicate relocates be allowed and highlighted? *)
- LogName = "Linker.Log";
- HeaderSize = 40H; (* HeaderSize MOD BlockSize = 0 *) (* ug *)
- EndBlockOfs = 38H; (* cf. Machine.GetStaticHeap *)
- NumPriorities* = 6;
- TYPE
- AdrTable = POINTER TO ARRAY OF ADDRESS;
- (** --- MODULE Heaps --- *)
- CONST
- MaxTags* = 16; (* in type descriptor *)
- (** type descriptor field offsets relative to root (middle) *)
- Tag0Ofs* = -2 * AddressSize; (** first tag *)
- Mth0Ofs* = Tag0Ofs - AddressSize * MaxTags; (** first method *)
- Ptr0Ofs* = AddressSize; (** first pointer offset *)
- (** flags in TypeDesc, RoundUp(log2(MaxTags)) low bits reserved for extLevel *)
- ProtTypeBit* = 31;
- BlockSize = 32; (* power of two, <= 32 for RegisterCandidates *)
- ArrayAlignment = 8;
- BlockHeaderSize = 2 * AddressSize;
- HeapBlockOffset = - 2 * AddressSize;
- TypeDescOffset = - AddressSize;
- MinPtrOfs = -40000000H; (* sentinel offset for ptrOfs *)
- MethodEndMarker* = MinPtrOfs; (* marks the end of the method addresses in the static type descriptor *)
- InitTableLen = 2048 + 256;
- InitPtrTableLen = 2048;
- TypeDescRecSize* = 5 * AddressSize + 32; (* needs to be changed in case TypeDesc is adapted *)
- NilVal* = 0;
- TYPE
- RootObject* = OBJECT
- VAR nextRoot: RootObject; (* for linking root objects during GC *)
- PROCEDURE FindRoots*; (** abstract *)
- BEGIN
- HALT(30101)
- END FindRoots;
- END RootObject;
- ProcessLink* = OBJECT (RootObject)
- VAR next*, prev*: ProcessLink
- END ProcessLink;
- ProcessQueue* = RECORD
- head*, tail*: ProcessLink
- END;
- MemoryBlock = POINTER TO MemoryBlockDesc;
- MemoryBlockDesc = RECORD
- next {UNTRACED}: MemoryBlock;
- startAdr: ADDRESS;
- size: SIZE;
- beginBlockAdr, endBlockAdr: ADDRESS
- END;
- HeapBlock = POINTER TO HeapBlockDesc; (* base object of all heap blocks *)
- HeapBlockDesc = RECORD
- mark: LONGINT;
- dataAdr: ADDRESS;
- size: SIZE;
- nextRealtime: HeapBlock;
- END;
- FreeBlock = POINTER TO FreeBlockDesc;
- FreeBlockDesc = RECORD (HeapBlockDesc)
- END;
- SystemBlock = POINTER TO SystemBlockDesc;
- SystemBlockDesc = RECORD (HeapBlockDesc)
- END;
- RecordBlock = POINTER TO RecordBlockDesc;
- RecordBlockDesc = RECORD (HeapBlockDesc)
- END;
- ProtRecBlock* = POINTER TO ProtRecBlockDesc;
- ProtRecBlockDesc* = RECORD (RecordBlockDesc)
- count*: LONGINT;
- locked*: BOOLEAN;
- awaitingLock*: ProcessQueue;
- awaitingCond*: ProcessQueue;
- lockedBy*: ANY;
- lock*: ANY; (* field used for Win32 system, unused for I386 *)
- waitingPriorities*: ARRAY NumPriorities OF LONGINT;
- END;
- ArrayBlock = POINTER TO ArrayBlockDesc;
- ArrayBlockDesc = RECORD (HeapBlockDesc)
- END;
- StaticTypeBlock*= POINTER TO StaticTypeDesc;
- StaticTypeDesc* = RECORD
- recSize: SIZE;
- pointerOffsets* {UNTRACED}: PointerOffsets;
- END;
- PointerOffsets = POINTER TO ARRAY OF SIZE;
- (** --- MODULE Modules --- *)
- TYPE
- (* definitions for object-model loader support *)
- Name* = ARRAY 32 OF CHAR;
- CommandProc* = PROCEDURE;
- CommandParProc* = PROCEDURE(par: ANY): ANY;
- Command* = RECORD
- name*: Name;
- argTdAdr*, retTdAdr* : ADDRESS;
- entryAdr* : ADDRESS;
- END;
- ExportDesc* = RECORD
- fp*: ADDRESS;
- adr*: ADDRESS;
- exports*: LONGINT;
- dsc*: ExportArray
- END;
- ExportArray* = POINTER TO ARRAY OF ExportDesc;
- Bytes* = POINTER TO ARRAY OF CHAR;
- TerminationHandler* = PROCEDURE;
- ExceptionTableEntry* = RECORD
- pcFrom*: ADDRESS;
- pcTo*: ADDRESS;
- pcHandler*: ADDRESS;
- END;
- ExceptionTable* = POINTER TO ARRAY OF ExceptionTableEntry;
- ProcTableEntry* = RECORD
- pcFrom*, pcLimit*, pcStatementBegin*, pcStatementEnd*: ADDRESS;
- noPtr*: LONGINT;
- END;
- ProcTable* = POINTER TO ARRAY OF ProcTableEntry;
- PtrTable* = POINTER TO ARRAY OF SIZE;
- ProcOffsetEntry* = RECORD
- data*: ProcTableEntry; (* code offsets of procedures *)
- startIndex: LONGINT; (* start index into global ptrOffset table *)
- END;
- ProcOffsetTable* = POINTER TO ARRAY OF ProcOffsetEntry;
- Module* = OBJECT (RootObject) (* cf. Linker0 & Heaps.WriteType *)
- VAR
- next*: Module;
- name*: Name;
- init, published: BOOLEAN;
- refcnt*: LONGINT;
- sb*: ADDRESS;
- entry*: POINTER TO ARRAY OF ADDRESS;
- command*: POINTER TO ARRAY OF Command;
- ptrAdr*: POINTER TO ARRAY OF ADDRESS;
- typeInfo*: POINTER TO ARRAY OF TypeDesc; (* traced explicitly in FindRoots *) (* ug *)
- module*: POINTER TO ARRAY OF Module;
- procTable*: ProcTable; (* information inserted by loader, removed after use in Publish, not used by linker *)
- ptrTable*: PtrTable; (* information inserted by loader, removed after use in Publish, not used by linker *)
- data*, code*, staticTypeDescs* (* ug *), refs*: Bytes;
- export*: ExportDesc;
- term*: TerminationHandler;
- exTable*: ExceptionTable;
- noProcs*: LONGINT;
- firstProc*: ADDRESS; (* procedure with lowest PC in module *)
- maxPtrs*: LONGINT;
- crc*: LONGINT;
- END Module;
- TypeDesc* = POINTER TO RECORD (* ug: adapt constant TypeDescRecSize if this type if this type is changed !!! *)
- descSize: LONGINT;
- sentinel: LONGINT; (* = MPO-4 *)
- tag*: ADDRESS; (* pointer to static type descriptor, only used by linker and loader *)
- flags*: SET;
- mod*: Module; (* hint only, because module may have been freed (at Heaps.ModOfs) *)
- name*: Name;
- END;
- VAR
- logWriter: Streams.Writer; logFile: Files.File;
- root-: ADDRESS;
- procOffsets {UNTRACED}: ProcOffsetTable; (* global table containing procedure code offsets and pointer offsets, sorted in ascending order of procedure code offsets *)
- numProcs: LONGINT; (* number of entries in procOffsets *)
- ptrOffsets {UNTRACED}: PtrTable; (* global table containing pointer offsets of procedures *)
- numPtrs: LONGINT; (* number of entries in ptrOffsets *)
- heap-: ANY;
- memBlock {UNTRACED}: MemoryBlock;
- beginMemBlockAdr, endMemBlockAdr: ADDRESS; (* block boundaries of linker heap (including memory block descriptor) *)
- beginAdr, freeAdr, baseAdr (* fof 071201 *) : ADDRESS;
- heapOfs: SIZE;
- exportTags, relocates: LONGINT;
- exportTagAdr: AdrTable;
- relocateAdr: AdrTable;
- curRelocate: LONGINT;
- refsMissed: LONGINT;
- prefix,suffix: Files.FileName; (* fof 071203 could be long filename *)
- loadObj*: PROCEDURE (name, fileName: ARRAY OF CHAR; VAR res: LONGINT;
- VAR msg: ARRAY OF CHAR): Module;
- getProcs: ARRAY 9 OF BOOLEAN;
- freeBlockTag, systemBlockTag, recordBlockTag, protRecBlockTag, arrayBlockTag: ADDRESS;
- initBlock {UNTRACED}: ANY; (* address of init block, i.e. block that contains calls to module bodies *)
- currentMarkValue: LONGINT; (* all objects allocated in the link phase receive this mark value *)
- (** --- MODULE Machine --- *)
- (** Fill4 - Fill "size" dwords at "destAdr" with "filler". *)
- PROCEDURE Fill4 (destAdr: ADDRESS; size: SIZE; filler: LONGINT);
- BEGIN
- WHILE size > 0 DO
- SYSTEM.PUT (destAdr, filler);
- INC (destAdr, SIZEOF(LONGINT));
- DEC (size);
- END;
- END Fill4;
- (** --- MODULE KernelLog --- *)
- (** Char - Write a character to the trace output. *)
- PROCEDURE Char*(c: CHAR);
- BEGIN
- logWriter.Char(c);
- END Char;
- (** String - Write a string. *)
- PROCEDURE String*(CONST s: ARRAY OF CHAR);
- BEGIN
- logWriter.String(s);
- END String;
- (** Ln - Skip to the next line on trace output. *)
- PROCEDURE Ln*;
- BEGIN
- logWriter.Ln();
- END Ln;
- (** Int - Write "x" as a decimal number. "w" is the field width. *)
- PROCEDURE Int*(x, w: LONGINT);
- BEGIN
- logWriter.Int(x,w);
- END Int;
- (** Hex - Write "x" as a hexadecimal number. *)
- PROCEDURE Hex*(x: SIZE; w: LONGINT);
- BEGIN
- logWriter.Hex(x,w);
- END Hex;
- (** Address - Write "x" as an address. *)
- PROCEDURE Address*(x: ADDRESS);
- BEGIN
- logWriter.Address(x);
- END Address;
- (** Memory - Write a block of memory. *)
- PROCEDURE Memory*(adr: ADDRESS; size: SIZE); (* ug: not yet rewritten using ADDRESS and SIZE *)
- VAR i,j: SIZE; t: LONGINT; buf: ARRAY 4 OF CHAR; reset, missed: BOOLEAN;
- BEGIN
- (*
- Texts.SetFont(writer, Fonts.This("Courier10.Scn.Fnt"));
- *)
- buf[1] := 0X; size := adr+size-1;
- reset := FALSE;
- FOR i := adr TO size BY 16 DO
- Hex(i, 9); missed := FALSE;
- FOR j := i TO i+15 DO
- IF j <= size THEN
- IF curRelocate >= 0 THEN (* highlighting enabled *)
- IF (j >= relocateAdr[curRelocate]) & (j <= relocateAdr[curRelocate]+3) THEN
- (* Texts.SetColor(writer, 3); *) reset := TRUE
- ELSIF j = relocateAdr[curRelocate]+4 THEN
- INC(curRelocate);
- IF curRelocate # relocates THEN
- IF j = relocateAdr[curRelocate] THEN
- (* Texts.SetColor(writer, 3); *) reset := TRUE
- ELSIF TraceDuplicates & (j = relocateAdr[curRelocate]+4) THEN (* duplicate! *)
- (* Texts.SetColor(writer, 1); *) reset := TRUE;
- REPEAT
- INC(curRelocate)
- UNTIL (curRelocate = relocates) OR (j # relocateAdr[curRelocate]+4)
- END
- ELSE
- curRelocate := -1
- END
- ELSIF TraceRefs THEN
- IF j <= adr+size-4 THEN (* heuristic to check if all pointers were seen *)
- SYSTEM.GET(j, t);
- IF (t > beginMemBlockAdr) & (t < freeAdr) THEN
- INC(refsMissed); missed := TRUE;
- (* Texts.SetColor(writer, 4); *) reset := TRUE
- END
- END
- END
- END;
- SYSTEM.GET(j, buf[0]);
- Hex(SYSTEM.VAL(SHORTINT, buf[0]), -3);
- (*
- IF reset THEN Texts.SetColor(writer, 15) END
- *)
- ELSE
- buf := " "; String(buf); buf[1] := 0X
- END
- END;
- buf[0] := " "; String(buf);
- FOR j := i TO i+15 DO
- IF j <= size THEN
- SYSTEM.GET(j, buf[0]);
- IF (buf[0] < " ") OR (buf[0] >= CHR(127)) THEN
- buf[0] := "."
- END;
- String(buf)
- END
- END;
- IF missed THEN String(" <--missed?") END;
- Ln
- END;
- (*
- Texts.SetFont(writer, Fonts.Default);
- *)
- END Memory;
- (** Bits - Write bits (ofs..ofs+n-1) of x in binary. *)
- PROCEDURE Bits*(x: SET; ofs, n: LONGINT);
- BEGIN
- REPEAT
- DEC(n);
- IF (ofs+n) IN x THEN Char("1") ELSE Char("0") END
- UNTIL n = 0
- END Bits;
- (** Enter - Enter mutually exclusive region for writing. *)
- PROCEDURE Enter*;
- BEGIN
- Char("{")
- END Enter;
- (** Exit - Exit mutually exclusive region for writing. *)
- PROCEDURE Exit*;
- BEGIN
- Char("}"); Ln
- END Exit;
- (** --- MODULE Heaps --- *)
- (* initialize a free block *)
- PROCEDURE InitFreeBlock(freeBlock: FreeBlock; mark: LONGINT; dataAdr: ADDRESS; size: SIZE);
- VAR freeBlockAdr: ADDRESS;
- BEGIN
- freeBlock.mark := mark;
- freeBlock.dataAdr := dataAdr;
- freeBlock.size := size;
- freeBlock.nextRealtime := NIL;
- (* initialize free block header *)
- freeBlockAdr := SYSTEM.VAL(ADDRESS, freeBlock);
- SYSTEM.PUT(freeBlockAdr + TypeDescOffset, FreeBlockId); (* use temporary constant here, correct tags are filled in by FixupHeapBlockTags *)
- SYSTEM.PUT(freeBlockAdr + HeapBlockOffset, NilVal)
- END InitFreeBlock;
- (* NewBlock - Allocate a heap block. {(size MOD BlockSize = 0)} *)
- PROCEDURE NewBlock(size: SIZE): ADDRESS;
- VAR p, freeBlockAdr: ADDRESS; freeBlock: FreeBlock; blockSize: SIZE;
- BEGIN
- ASSERT(size MOD BlockSize = 0);
- freeBlock := SYSTEM.VAL(FreeBlock, freeAdr + BlockHeaderSize);
- blockSize := freeBlock.size;
- p := freeAdr; INC(freeAdr, size);
- ASSERT(freeAdr + BlockHeaderSize + SIZEOF(FreeBlockDesc) <= memBlock.endBlockAdr); (* there must be space for an empty heap block *)
- freeBlockAdr := freeAdr + BlockHeaderSize; (* address of remaining free block *)
- freeBlock := SYSTEM.VAL(FreeBlock, freeBlockAdr);
- InitFreeBlock(freeBlock, Unmarked, NilVal, blockSize - size);
- RETURN p
- END NewBlock;
- (** NewSys - Implementation of SYSTEM.NEW *)
- PROCEDURE NewSys*(VAR p: ANY; size: SIZE);
- VAR systemBlockSize, blockSize: SIZE; systemBlockAdr, dataBlockAdr: ADDRESS;
- systemBlock: SystemBlock;
- BEGIN
- ASSERT((BlockHeaderSize MOD ArrayAlignment = 0));
- systemBlockSize := BlockHeaderSize + SIZEOF(SystemBlockDesc);
- 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 *)
- blockSize := systemBlockSize + BlockHeaderSize + size;
- INC(blockSize,(-blockSize) MOD BlockSize); (* round up to multiple of BlockSize *)
- systemBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
- SYSTEM.PUT(systemBlockAdr + TypeDescOffset, SystemBlockId); (* temporary type descriptor value, fixup and relocation are done later *)
- SYSTEM.PUT(systemBlockAdr + HeapBlockOffset, NilVal);
- dataBlockAdr := systemBlockAdr + systemBlockSize (* - BlockHeaderSize + BlockHeaderSize *);
- SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* system blocks have no type descriptor *)
- SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, systemBlockAdr); (* reference to heap block descriptor *)
- Relocate(dataBlockAdr + HeapBlockOffset);
- systemBlock := SYSTEM.VAL(SystemBlock, systemBlockAdr);
- systemBlock.mark := currentMarkValue;
- systemBlock.dataAdr := dataBlockAdr;
- systemBlock.nextRealtime := NIL; (* no realtime object since SystemBlock during allocation of a module *)
- Relocate(ADDRESSOF(systemBlock.dataAdr));
- Relocate(ADDRESSOF(systemBlock.nextRealtime));
- systemBlock.size := blockSize;
- p := SYSTEM.VAL(ANY, dataBlockAdr);
- Fill4(dataBlockAdr, (blockSize - systemBlockSize - BlockHeaderSize) DIV 4, 0); (* clear everything from dataBlockAdr until end of block *)
- END NewSys;
- (* NewRealArr - Implementation of allocation of new real array *)
- PROCEDURE NewRealArr*(VAR p: ANY; numElems, elemSize: SIZE; numDims: LONGINT);
- VAR arrayBlockAdr, dataBlockAdr, firstElem, elemTag: ADDRESS; arrSize, arrayBlockSize, blockSize, fillSize: SIZE;
- arrayBlock: ArrayBlock;
- arrayDataOffset: SIZE; (* offset from descriptor origin to first element of array, depends on number of dimensions, must be aligned to 0 MOD 8 *)
- BEGIN
- elemTag := 0;
- arrSize := numElems * elemSize;
- ASSERT(arrSize > 0);
- ASSERT((BlockHeaderSize MOD ArrayAlignment = 0));
- arrayDataOffset := numDims * AddressSize + 3 * AddressSize;
- INC(arrayDataOffset, (-arrayDataOffset) MOD ArrayAlignment); (* align here such that first first array element is aligned 0 MOD ArrayAlignment *)
- arrayBlockSize := BlockHeaderSize + SIZEOF(ArrayBlockDesc);
- INC(arrayBlockSize,(-arrayBlockSize) MOD ArrayAlignment); (* do. *)
- blockSize := arrayBlockSize + BlockHeaderSize + (arrayDataOffset + arrSize);
- INC(blockSize,(-blockSize) MOD BlockSize);(* round up to multiple of BlockSize *)
- arrayBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
- SYSTEM.PUT(arrayBlockAdr + TypeDescOffset, ArrayBlockId); (* temporary value, fixup and relocation are done later *)
- SYSTEM.PUT(arrayBlockAdr + HeapBlockOffset, NilVal);
- dataBlockAdr := arrayBlockAdr + arrayBlockSize (* - BlockHeaderSize + BlockHeaderSize *);
- SYSTEM.PUT(dataBlockAdr + TypeDescOffset, elemTag); (* dummy Tag, correct element tag will be filled in later *)
- SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, arrayBlockAdr); (* reference to heap block descriptor *)
- Relocate(dataBlockAdr + HeapBlockOffset);
- arrayBlock := SYSTEM.VAL(ArrayBlock, arrayBlockAdr);
- arrayBlock.mark := currentMarkValue;
- arrayBlock.dataAdr := dataBlockAdr;
- arrayBlock.nextRealtime := NIL; (* no realtime object since this object is used during allocation of a module *)
- Relocate(ADDRESSOF(arrayBlock.dataAdr));
- Relocate(ADDRESSOF(arrayBlock.nextRealtime));
- arrayBlock.size := blockSize;
- (* clear data part of array, clear everything from dataBlockAdr until end of block, write GC support info after clearing the block *)
- fillSize := blockSize - arrayBlockSize - BlockHeaderSize;
- ASSERT(fillSize MOD 4 = 0); (* fillSize implicitly is a multiple of 4 *)
- Fill4(dataBlockAdr, fillSize DIV 4, 0);
- firstElem := dataBlockAdr + arrayDataOffset;
- SYSTEM.PUT(dataBlockAdr, numElems (* firstElem + arrSize - elemSize*) ); (* lastElemToMark *)
- (* Relocate(dataBlockAdr); *)
- SYSTEM.PUT(dataBlockAdr + AddressSize, NIL); (* reserved for Mark *)
- SYSTEM.PUT(dataBlockAdr + 2 * AddressSize, firstElem); (* firstElem *)
- Relocate(dataBlockAdr + 2 * AddressSize);
- p := SYSTEM.VAL(ANY, dataBlockAdr);
- END NewRealArr;
- (* NewTypeDesc - Implementation of allocation of dynamic record *)
- PROCEDURE NewTypeDesc*(VAR p: ANY; recSize: SIZE);
- VAR blockSize: SIZE; recordBlockAdr, dataBlockAdr: ADDRESS;
- recordBlock: RecordBlock;
- BEGIN
- blockSize := BlockHeaderSize + SIZEOF(RecordBlockDesc) + BlockHeaderSize + recSize;
- INC(blockSize, (-blockSize) MOD BlockSize); (* align to multiple of BlockSize *)
- recordBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
- SYSTEM.PUT(recordBlockAdr + TypeDescOffset, RecordBlockId); (* temporary tag value, fixup and relocation are done later *)
- SYSTEM.PUT(recordBlockAdr + HeapBlockOffset, NilVal);
- dataBlockAdr := recordBlockAdr + SIZEOF(RecordBlockDesc) + BlockHeaderSize;
- SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* type descriptor tag will be filled in FixupTypeDescTags *)
- SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, recordBlockAdr); (* reference to heap block descriptor *)
- Relocate(dataBlockAdr + HeapBlockOffset);
- recordBlock := SYSTEM.VAL(RecordBlock, recordBlockAdr);
- recordBlock.mark := currentMarkValue;
- recordBlock.dataAdr := dataBlockAdr;
- recordBlock.nextRealtime := NIL; (* default value NIL since module type descriptors are no realtime objects *)
- Relocate(ADDRESSOF(recordBlock.dataAdr));
- Relocate(ADDRESSOF(recordBlock.nextRealtime));
- recordBlock.size := blockSize;
- p := SYSTEM.VAL(ANY, dataBlockAdr);
- Fill4(dataBlockAdr, (blockSize - SIZEOF(RecordBlockDesc) - 2 * BlockHeaderSize) DIV 4, 0); (* clear everything from dataBlockAdr to end of blockr *)
- END NewTypeDesc;
- (* FillStaticType - Implementation of filling static type descriptor *)
- PROCEDURE FillStaticType*(VAR staticTypeAddr: ADDRESS; startAddr, typeInfoAdr: ADDRESS; size, recSize: SIZE;
- numPtrs, numSlots: LONGINT);
- VAR p, offset: ADDRESS; staticTypeBlock {UNTRACED}: StaticTypeBlock;
- BEGIN
- Fill4(startAddr, size DIV 4, 0); (* clear whole static type, size MOD AddressSize = 0 implicitly, see WriteType in PCOF.Mod *)
- SYSTEM.PUT(startAddr, MethodEndMarker); (* sentinel *)
- (* methods and tags filled in later *)
- offset := AddressSize * (numSlots + 1 + 1); (* #methods, max. no. of tags, method end marker (sentinel), pointer to type information*)
- p := startAddr + offset;
- SYSTEM.PUT(p + TypeDescOffset, typeInfoAdr); (* pointer to typeInfo *)
- Relocate(p + TypeDescOffset);
- staticTypeBlock := SYSTEM.VAL(StaticTypeBlock, p);
- staticTypeBlock.recSize := recSize;
- staticTypeAddr := p;
- (* create the pointer for the dynamic array of pointer, the dynamic array of pointer offsets is stored in the static type
- descriptor and has no header part *)
- INC(p, SIZEOF(StaticTypeDesc));
- IF p MOD (2 * AddressSize) # 0 THEN INC(p, AddressSize) END;
- ASSERT(p MOD (2 * AddressSize) = 0);
- SYSTEM.PUT(p + 3 * AddressSize, numPtrs); (* internal structure of dynamic array without pointers: the first 3 fields are unused *)
- staticTypeBlock.pointerOffsets := SYSTEM.VAL(PointerOffsets, p); (* the fourth field contains the dimension of the array *)
- Relocate(ADDRESSOF(staticTypeBlock.pointerOffsets));
- (* pointer offsets filled in later *)
- END FillStaticType;
- (** --- MODULE Modules --- *)
- (** Append - Append from to to, truncating on overflow. *)
- PROCEDURE Append*(CONST from: ARRAY OF CHAR; VAR to: ARRAY OF CHAR);
- VAR i, j, m: LONGINT;
- BEGIN
- j := 0; WHILE to[j] # 0X DO INC(j) END;
- m := LEN(to)-1;
- i := 0; WHILE (from[i] # 0X) & (j # m) DO to[j] := from[i]; INC(i); INC(j) END;
- to[j] := 0X
- END Append;
- (* Publish - Add a module to the pool of accessible modules, or return named module. *)
- PROCEDURE Publish(VAR m: Module; VAR new: BOOLEAN);
- VAR n: Module; i: LONGINT;
- BEGIN
- n := SYSTEM.VAL(Module, root);
- WHILE (n # NIL) & (n.name # m.name) DO n := n.next END;
- IF n # NIL THEN (* module with same name exists, return it and ignore new m *)
- m := n; new := FALSE
- ELSE
- m.published := TRUE;
- m.next := SYSTEM.VAL(Module, root);
- root := SYSTEM.VAL(ADDRESS, m);
- m.refcnt := 0;
- FOR i := 0 TO LEN(m.module)-1 DO INC(m.module[i].refcnt) END;
- new := TRUE
- END
- END Publish;
- (* ModuleByName - Return the named module. *)
- PROCEDURE ModuleByName(CONST name: ARRAY OF CHAR): Module;
- VAR m: Module;
- BEGIN
- m := SYSTEM.VAL(Module, root);
- WHILE (m # NIL) & (m.name # name) DO m := m.next END;
- RETURN m
- END ModuleByName;
- (* GetFileName - Generate a module file name. *)
- PROCEDURE GetFileName(CONST name: ARRAY OF CHAR; VAR fileName: ARRAY OF CHAR);
- VAR i, j: LONGINT;
- BEGIN
- i := 0; WHILE prefix[i] # 0X DO fileName[i] := prefix[i]; INC(i) END;
- j := 0; WHILE name[j] # 0X DO fileName[i] := name[j]; INC(i); INC(j) END;
- j := 0; WHILE suffix[j] # 0X DO fileName[i] := suffix[j]; INC(i); INC(j) END;
- fileName[i] := 0X
- END GetFileName;
- (** ThisModule - Import a module. *) (* Algorithm J. Templ, ETHZ, 1994 *)
- PROCEDURE ThisModule*(CONST name: ARRAY OF CHAR; VAR res: LONGINT; VAR msg: ARRAY OF CHAR): Module;
- (* TYPE Body = PROCEDURE; *)
- VAR m, p: Module; fileName: ARRAY 64 OF CHAR; (*body: Body;*) new: BOOLEAN;
- BEGIN
- res := 0; msg[0] := 0X; m := ModuleByName(name);
- IF m = NIL THEN
- GetFileName(name, fileName);
- m := loadObj(name, fileName, res, msg);
- IF (m # NIL) & ~m.published THEN
- p := m; Publish(m, new);
- IF new THEN (* m was successfully published *)
- (*body := SYSTEM.VAL(Body, ADDRESSOF(m.code[0]));
- body; res := 0; msg[0] := 0X;*)
- m.init := TRUE (* allow ThisCommand *)
- ELSE
- (* m was part of cycle, replaced by existing module *)
- HALT(99)
- END
- END
- END;
- RETURN m
- END ThisModule;
- (** Return the named type *)
- PROCEDURE ThisType*(m: Module; CONST name: ARRAY OF CHAR): TypeDesc;
- VAR i: LONGINT; type: TypeDesc;
- BEGIN
- i := 0;
- WHILE (i < LEN(m.typeInfo)) & (m.typeInfo[i].name # name) DO INC(i) END;
- IF i = LEN(m.typeInfo) THEN
- type := NIL
- ELSE
- type := m.typeInfo[i]
- END;
- RETURN type
- END ThisType;
- (* ug: just for debugging *)
- (** WriteType - Write a type name (for tracing only). *)
- PROCEDURE WriteType(t: ADDRESS); (* t is static type descriptor *)
- VAR typeDesc: TypeDesc;
- BEGIN
- IF t # NilVal THEN
- SYSTEM.GET (t + TypeDescOffset, typeDesc);
- IF typeDesc.mod # NIL THEN
- String(typeDesc.mod.name)
- ELSE
- String("NIL");
- END;
- Char(".");
- String(typeDesc.name)
- ELSE
- String("no type")
- END
- END WriteType;
- PROCEDURE FindInsertionPos(VAR entry: ProcTableEntry; VAR pos: LONGINT): BOOLEAN;
- VAR l, r, x: LONGINT; success, isHit: BOOLEAN;
- BEGIN
- pos := -1;
- success := FALSE;
- IF numProcs = 0 THEN (* empty table *)
- pos := 0; success := TRUE
- ELSE
- l := 0; r := numProcs - 1;
- REPEAT
- x := (l + r) DIV 2;
- IF entry.pcLimit < procOffsets[x].data.pcFrom THEN r := x - 1 ELSE l := x + 1 END;
- isHit := ((x = 0) OR (procOffsets[x - 1].data.pcLimit < entry.pcFrom)) & (entry.pcLimit < procOffsets[x].data.pcFrom);
- UNTIL isHit OR (l > r);
- IF isHit THEN
- pos := x; success := TRUE
- ELSE
- IF (x = numProcs - 1) & (procOffsets[x].data.pcLimit < entry.pcFrom) THEN
- pos := x + 1; success := TRUE
- END
- END
- END;
- RETURN success
- END FindInsertionPos;
- PROCEDURE NumTotalPtrs(procTable: ProcTable): LONGINT;
- VAR i, num: LONGINT;
- BEGIN
- num := 0;
- FOR i := 0 TO LEN(procTable) - 1 DO
- num := num + procTable[i].noPtr
- END;
- RETURN num
- END NumTotalPtrs;
- (* insert the procedure code offsets and pointer offsets of a single module into the global table *)
- PROCEDURE InsertProcOffsets*(procTable: ProcTable; ptrTable: PtrTable; maxPtr: LONGINT);
- VAR success: BOOLEAN; i, j, pos, poslast, num: LONGINT;
- BEGIN
- IF LEN(procTable) > 0 THEN
- ASSERT(numProcs + LEN(procTable) <= LEN(procOffsets)); (* no reallocation of procOffsets in linker *)
- num := NumTotalPtrs(procTable);
- ASSERT(numPtrs + num <= LEN(ptrOffsets)); (* no reallocation of ptrOffsets in linker *)
- success := FindInsertionPos(procTable[0], pos); success := success & FindInsertionPos(procTable[LEN(procTable) - 1], poslast);
- ASSERT(success & (pos = poslast));
- FOR i := numProcs - 1 TO pos BY -1 DO procOffsets[i + LEN(procTable)] := procOffsets[i] END;
- FOR i := 0 TO LEN(procTable) - 1 DO
- procOffsets[pos + i].data := procTable[i];
- procOffsets[pos + i].startIndex := numPtrs; (* this field is never accessed in case of procTable[i].noPtr = 0, so we put numPtrs in there *)
- FOR j := 0 TO procTable[i].noPtr - 1 DO
- ptrOffsets[numPtrs + j] := ptrTable[i * maxPtr + j]
- END;
- numPtrs := numPtrs + procTable[i].noPtr;
- END;
- numProcs := numProcs + LEN(procTable)
- END
- END InsertProcOffsets;
- (** --- MODULE Linker0 --- *)
- (* GrowTable - Grow an address table. *)
- PROCEDURE GrowTable(VAR table: AdrTable);
- VAR new: AdrTable; i: LONGINT;
- BEGIN
- NEW(new, 2*LEN(table));
- FOR i := 0 TO LEN(table)-1 DO new[i] := table[i] END;
- table := new
- END GrowTable;
- (** Relocate - Record a relocate location. *)
- PROCEDURE Relocate*(adr: ADDRESS);
- BEGIN
- IF relocates = LEN(relocateAdr) THEN GrowTable(relocateAdr) END;
- relocateAdr[relocates] := adr; INC(relocates);
- SYSTEM.GET(adr, adr);
- ASSERT((adr = 0) OR (adr > beginMemBlockAdr) & (adr <= freeAdr))
- END Relocate;
- (** Open - Initialize the log file etc. *)
- PROCEDURE Open*(CONST namePrefix,nameSuffix: ARRAY OF CHAR; base: ADDRESS; log: Streams.Writer);
- VAR i: LONGINT; w: Files.Writer;
- BEGIN
- (* fof 071201 *)
- COPY(namePrefix, prefix);
- IF nameSuffix = "" THEN
- suffix := DefaultExtension
- ELSE
- COPY(nameSuffix, suffix)
- END;
- baseAdr := base;
- InitHeap;
- root := 0;
- freeAdr := memBlock.beginBlockAdr;
- heapOfs := baseAdr - beginAdr;
- exportTags := 0; relocates := 0; refsMissed := 0;
- curRelocate := -1;
- IF log # NIL THEN logWriter := log; logFile := NIL ELSE logFile := Files.New(LogName); NEW(w, logFile,0); logWriter := w END;
- FOR i := 0 TO LEN(getProcs) - 1 DO getProcs[i] := FALSE END;
- (* allocate the global tables procOffsets and ptrOffsets in linker heap *)
- NewProcOffsets(procOffsets, InitTableLen);
- numProcs := 0;
- NewPtrOffsets(ptrOffsets, InitPtrTableLen);
- numPtrs := 0;
- END Open;
- (* RelocateModules - Relocate the module records. *)
- PROCEDURE RelocateModules;
- VAR adr: ADDRESS; i: LONGINT; type, hdPtrDescType: TypeDesc; m: Module;
- BEGIN
- type := ThisType(ModuleByName(ModDescModule), ModDescType);
- hdPtrDescType := ThisType(ModuleByName(HdPtrDescModule), HdPtrDescType);
- ASSERT((type # NIL) & (hdPtrDescType # NIL));
- IF ProtectedModule THEN
- INCL(type.flags, ProtTypeBit) (* flag for dynamic loader *)
- END;
- m := SYSTEM.VAL(Module, root);
- WHILE m # NIL DO
- adr := SYSTEM.VAL(ADDRESS, m);
- SYSTEM.PUT(adr + TypeDescOffset, type.tag); Relocate(adr + TypeDescOffset); (* module descriptor tag *)
- 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 *)
- adr := SYSTEM.VAL(ADDRESS, m.typeInfo);
- SYSTEM.PUT(adr + TypeDescOffset, hdPtrDescType.tag);
- Relocate(adr + TypeDescOffset)
- END;
- IF LEN(m.module) > 0 THEN (* do. *)
- adr := SYSTEM.VAL(ADDRESS, m.module);
- SYSTEM.PUT(adr + TypeDescOffset, hdPtrDescType.tag);
- Relocate(adr + TypeDescOffset)
- END;
- (* relocation of addresses *)
- Relocate(ADDRESSOF(m.next));
- Relocate(m.sb); (* SELF in const area *)
- Relocate(ADDRESSOF(m.sb));
- (* m.entry in module block *)
- (* m.entry indirect tag already relocated (same as SysBlk) *)
- FOR i := 0 TO LEN(m.entry)-1 DO Relocate(ADDRESSOF(m.entry[i])) END;
- Relocate(ADDRESSOF(m.entry));
- (* m.command in module block *)
- FOR i := 0 TO LEN(m.command)-1 DO
- Relocate(ADDRESSOF(m.command[i].entryAdr));
- IF (m.command[i].argTdAdr > 1) THEN Relocate(ADDRESSOF(m.command[i].argTdAdr)); END;
- IF (m.command[i].retTdAdr > 1) THEN Relocate(ADDRESSOF(m.command[i].retTdAdr)); END;
- END;
- Relocate(ADDRESSOF(m.command));
- (* m.ptrAdr in module block *)
- FOR i := 0 TO LEN(m.ptrAdr)-1 DO Relocate(ADDRESSOF(m.ptrAdr[i])) END;
- Relocate(ADDRESSOF(m.ptrAdr));
- (* m.typeInfo in module block *)
- FOR i := 0 TO LEN(m.typeInfo) - 1 DO
- Relocate(ADDRESSOF(m.typeInfo[i]));
- Relocate(ADDRESSOF(m.typeInfo[i].tag));
- Relocate(ADDRESSOF(m.typeInfo[i].mod))
- END;
- Relocate(ADDRESSOF(m.typeInfo));
- (* m.module in module block *)
- FOR i := 0 TO LEN(m.module)-1 DO Relocate(ADDRESSOF(m.module[i])) END;
- Relocate(ADDRESSOF(m.module));
- (* m.data in module block *)
- Relocate(ADDRESSOF(m.data));
- (* m.code in module block *)
- Relocate(ADDRESSOF(m.code));
- (* m.staticTypeDescs in module block *)
- Relocate(ADDRESSOF(m.staticTypeDescs));
- (* m.refs in module block *)
- Relocate(ADDRESSOF(m.refs));
- (* m.exTable in module block *)
- FOR i := 0 TO LEN(m.exTable)-1 DO
- Relocate(ADDRESSOF(m.exTable[i].pcFrom));
- Relocate(ADDRESSOF(m.exTable[i].pcTo));
- Relocate(ADDRESSOF(m.exTable[i].pcHandler))
- END;
- Relocate(ADDRESSOF(m.exTable));
- Relocate(ADDRESSOF(m.firstProc));
- (*
- (* object model support *)
- ASSERT((m.publics = 0) & (m.privates = 0)); (* not marked *)
- ASSERT(m.import = NIL); (* not marked *)
- ASSERT(m.struct = NIL); (* not marked *)
- ASSERT(m.reimp = NIL); (* not marked *)
- *)
- Relocate(ADDRESSOF(m.export.dsc)); (* descendants relocated via RelocateArray *)
- m := m.next
- END
- END RelocateModules;
- (* RelocateArrayFields - Fix up a dynamic array. *)
- PROCEDURE RelocateArrayFields(tagAdr: ADDRESS);
- VAR adr, p, lastElem, size: ADDRESS; staticTypeBlock {UNTRACED}: StaticTypeBlock; i: LONGINT;
- BEGIN
- SYSTEM.GET(tagAdr + AddressSize, size);
- SYSTEM.GET(tagAdr + 3 * AddressSize, p); (* firstElem *)
- SYSTEM.GET(tagAdr, adr); (* adr is address of static type descriptor (no alignment) *)
- staticTypeBlock := SYSTEM.VAL(StaticTypeBlock, adr);
- LOOP
- IF size = 0 THEN EXIT END;
- DEC(size);
- FOR i := 0 TO LEN(staticTypeBlock.pointerOffsets) - 1 DO
- Relocate(p + staticTypeBlock.pointerOffsets[i]);
- END;
- INC(p, staticTypeBlock.recSize) (* step to next array element *)
- END
- END RelocateArrayFields;
- (* RelocateExports - Relocate export arrays. *)
- PROCEDURE RelocateExports;
- VAR type: TypeDesc; i: LONGINT;
- BEGIN
- type := ThisType(ModuleByName(ExportDescModule), ExportDescType);
- ASSERT(type # NIL);
- FOR i := 0 TO exportTags - 1 DO
- SYSTEM.PUT(exportTagAdr[i], type.tag);
- Relocate(exportTagAdr[i]);
- RelocateArrayFields(exportTagAdr[i]);
- END
- END RelocateExports;
- (* RelocateProcOffsets - relocate the contents of the global table procOffsets, see InitTable for relocation of the global pointers *)
- PROCEDURE RelocateProcOffsets;
- VAR i: LONGINT;
- BEGIN
- FOR i := 0 TO numProcs - 1 DO (* relocation of code addresses in procOffsets *)
- Relocate(ADDRESSOF(procOffsets[i].data.pcFrom));
- Relocate(ADDRESSOF(procOffsets[i].data.pcLimit));
- Relocate(ADDRESSOF(procOffsets[i].data.pcStatementBegin));
- Relocate(ADDRESSOF(procOffsets[i].data.pcStatementEnd));
- END;
- END RelocateProcOffsets;
- PROCEDURE FixupTypeDescTags;
- VAR type: TypeDesc; i: LONGINT; m: Module; adr: ADDRESS;
- BEGIN
- type := ThisType(ModuleByName(TypeDescModule), TypeDescType);
- ASSERT(type # NIL);
- m := SYSTEM.VAL(Module, root);
- WHILE m # NIL DO
- FOR i := 0 TO LEN(m.typeInfo) - 1 DO
- adr := SYSTEM.VAL(ADDRESS, m.typeInfo[i]);
- SYSTEM.PUT(adr + TypeDescOffset, type.tag);
- Relocate(adr + TypeDescOffset);
- END;
- m := m.next
- END
- END FixupTypeDescTags;
- PROCEDURE FixupHeapBlockTags;
- VAR type: TypeDesc; m: Module; heapBlock {UNTRACED}: HeapBlock; adr, heapBlockAdr: ADDRESS; val: LONGINT;
- BEGIN
- m := ModuleByName(HeapModule); ASSERT(m # NIL);
- type := ThisType(m, FreeBlockDescType); ASSERT(type # NIL); freeBlockTag := type.tag;
- type := ThisType(m, SystemBlockDescType); ASSERT(type # NIL); systemBlockTag := type.tag;
- type := ThisType(m, RecordBlockDescType); ASSERT(type # NIL); recordBlockTag := type.tag;
- type := ThisType(m, ProtRecBlockDescType); ASSERT(type # NIL); protRecBlockTag := type.tag;
- type := ThisType(m, ArrayBlockDescType); ASSERT(type # NIL); arrayBlockTag := type.tag;
- adr := beginMemBlockAdr;
- WHILE adr < endMemBlockAdr DO
- heapBlockAdr := adr + BlockHeaderSize;
- SYSTEM.GET(heapBlockAdr + TypeDescOffset, val); (* tag field of heap block p *)
- CASE val OF
- FreeBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, freeBlockTag);
- | SystemBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, systemBlockTag);
- | RecordBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, recordBlockTag);
- | ProtRecBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, protRecBlockTag);
- | ArrayBlockId: SYSTEM.PUT(heapBlockAdr + TypeDescOffset, arrayBlockTag);
- END;
- Relocate(heapBlockAdr + TypeDescOffset);
- heapBlock := SYSTEM.VAL(HeapBlock, heapBlockAdr);
- adr := adr + heapBlock.size
- END;
- END FixupHeapBlockTags;
- (* SortRelocates - Sort the relocates. *)
- PROCEDURE SortRelocates;
- VAR h, i, j: LONGINT; p: ADDRESS;
- BEGIN
- h := 1; REPEAT h := h*3 + 1 UNTIL h > relocates;
- REPEAT
- h := h DIV 3; i := h;
- WHILE i < relocates DO
- p := relocateAdr[i]; j := i;
- WHILE (j >= h) & (relocateAdr[j-h] > p) DO
- relocateAdr[j] := relocateAdr[j-h]; j := j-h;
- END;
- relocateAdr[j] := p; INC(i)
- END
- UNTIL h = 1;
- IF ~TraceDuplicates THEN
- FOR i := 1 TO relocates-1 DO ASSERT(relocateAdr[i-1] < relocateAdr[i]) END (* sorted, without dups *)
- END
- END SortRelocates;
- (* GetNum - Get a compressed refblk number. *)
- PROCEDURE GetNum(refs: Bytes; VAR i, num: LONGINT);
- VAR n, s: LONGINT; x: CHAR;
- BEGIN
- s := 0; n := 0;
- x := refs[i]; INC(i);
- WHILE ORD(x) >= 128 DO
- INC(n, ASH(ORD(x) - 128, s));
- INC(s, 7);
- x := refs[i]; INC(i)
- END;
- num := n + ASH(ORD(x) MOD 64 - ORD(x) DIV 64 * 64, s)
- END GetNum;
- (* VarByName - Find a global variable in the reference block. *)
- PROCEDURE VarByName(refs: Bytes; i: LONGINT; CONST name: ARRAY OF CHAR): SIZE;
- VAR mode: CHAR; j, m, adr, type, t: LONGINT; s: Name; found: BOOLEAN;
- BEGIN
- m := LEN(refs^); found := FALSE;
- mode := refs[i]; INC(i);
- WHILE (i < m) & ((mode = 1X) OR (mode = 3X)) & ~found DO (* var *)
- type := ORD(refs[i]); INC(i);
- IF (type >= 81H) OR (type = 16H) OR (type = 1DH) THEN
- GetNum(refs, i, t) (* dim/tdadr *)
- END;
- GetNum(refs, i, adr);
- j := 0; REPEAT s[j] := refs[i]; INC(i); INC(j) UNTIL s[j-1] = 0X;
- IF s = name THEN found := TRUE
- ELSIF i < m THEN mode := refs[i]; INC(i)
- END
- END;
- IF found THEN
- ASSERT((mode = 1X) & ((type = 0DH) OR (type = 1DH) OR (type = 06H))) (* pointer or LInt VAR *)
- ELSE
- adr := 0
- END;
- RETURN SYSTEM.VAL(SIZE, adr)
- END VarByName;
- (* InitTable - Generate init code for module bodies. *)
- PROCEDURE InitTable(diff: SIZE; baseAdr, loadAdr: ADDRESS);
- VAR i, n: LONGINT; adr: ADDRESS; m: Module;
- PROCEDURE InitBody(m: Module);
- BEGIN
- IF m = NIL THEN
- (* 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
- extra code following it, see body of InitTable *)
- NewSys(initBlock, 5*n + (5+3)); adr := SYSTEM.VAL(ADDRESS, initBlock)
- ELSE
- INC(n); InitBody(m.next);
- Address(ADDRESSOF(m.code[0])+diff); Char("H"); Char(" ");
- Address(ADDRESSOF(m.data[0])+diff); Char("H"); Char(" ");
- String(m.name); Ln;
- SYSTEM.PUT(adr, 0E8X); (* CALL *)
- SYSTEM.PUT(adr+1, ADDRESSOF(m.code[0]) - (adr+5)); (* call address *)
- INC(adr, 5)
- END
- END InitBody;
- BEGIN
- String("BEGIN"); Ln;
- n := 0; InitBody(SYSTEM.VAL(Module, root));
- String("END"); Ln;
- (* startup command *)
- m := ModuleByName(StartModule);
- i := 0; WHILE m.command[i].name # StartCommand DO INC(i) END;
- Address(SYSTEM.VAL(ADDRESS, m.command[i].entryAdr)+diff); Char(" ");
- String(m.name); Char("."); String(StartCommand); Ln;
- SYSTEM.PUT(adr, 0E8X); (* CALL *)
- SYSTEM.PUT(adr+1, SYSTEM.VAL(LONGINT, m.command[i].entryAdr) - (adr+5));
- INC(adr, 5);
- (* HALT *)
- SYSTEM.PUT(adr, 6AX); (* PUSH imm8 *)
- SYSTEM.PUT(adr+1, 0FFX);
- SYSTEM.PUT(adr+2, 0CCX); (* INT 3 *)
- (* init table *)
- FOR adr := beginAdr TO beginAdr+HeaderSize-1 DO
- SYSTEM.PUT(adr, 0X)
- END;
- IF baseAdr = loadAdr THEN
- SYSTEM.PUT(beginAdr, 0E8X); (* CALL *)
- SYSTEM.PUT(beginAdr+1, SYSTEM.VAL(ADDRESS, initBlock) - (beginAdr+5))
- ELSE (* image will relocate itself *)
- adr := beginAdr;
- SYSTEM.PUT(adr, 60X); (* PUSHAD *)
- INC(adr);
- SYSTEM.PUT(adr, 0BEX); (* MOV ESI, X *)
- SYSTEM.PUT(adr+1, loadAdr);
- INC(adr, 5);
- SYSTEM.PUT(adr, 0BFX); (* MOV EDI, X *)
- SYSTEM.PUT(adr+1, baseAdr);
- INC(adr, 5);
- SYSTEM.PUT(adr, 0B9X); (* MOV ECX, X *)
- SYSTEM.PUT(adr+1, (freeAdr-beginAdr+3) DIV 4); (* length of image in dwords *)
- INC(adr, 5);
- SYSTEM.PUT(adr, 0FCX); (* CLD *)
- SYSTEM.PUT(adr+1, 0F3X); (* REP *)
- SYSTEM.PUT(adr+2, 0A5X); (* MOVSD *)
- INC(adr, 3);
- SYSTEM.PUT(adr, 61X); (* POPAD *)
- INC(adr);
- SYSTEM.PUT(adr, 0E8X); (* CALL *)
- SYSTEM.PUT(adr+1, SYSTEM.VAL(ADDRESS, initBlock) - (adr+5) + (baseAdr-loadAdr));
- INC(adr, 5);
- ASSERT(adr-beginAdr <= EndBlockOfs) (* not too much code *)
- END;
- SYSTEM.PUT(beginAdr + EndBlockOfs, freeAdr); Relocate(beginAdr + EndBlockOfs)
- END InitTable;
- PROCEDURE RootGlobals;
- VAR m: Module; i: LONGINT; ofs: SIZE;
- BEGIN
- (* root init block pointer *)
- m := ModuleByName(InitPtrModule);
- ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
- i := 5; ofs := VarByName(m.refs, i, InitPtrName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, initBlock); Relocate(m.sb + ofs);
- (* module root pointer, pointer to global procOffsets and ptrOffsets table, number of valid entries in procOffsets and ptrOffsets*)
- m := ModuleByName(ModRootModule);
- ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
- i := 5;
- ofs := VarByName(m.refs, i, ModRootName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, root); Relocate(m.sb + ofs);
- ofs := VarByName(m.refs, i, ProcOffsetsName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, SYSTEM.VAL(ADDRESS, procOffsets)); Relocate(m.sb + ofs);
- ofs := VarByName(m.refs, i, NumProcsName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, numProcs);
- ofs := VarByName(m.refs, i, PtrOffsetsName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, SYSTEM.VAL(ADDRESS, ptrOffsets)); Relocate(m.sb + ofs);
- ofs := VarByName(m.refs, i, NumPtrsName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, numPtrs);
- (* write tag addresses as pointer values since the reference section does not contain variables of type ADDRESS *)
- (* patching of Type Tags not necessary any more -- cf. Module Heaps *)
- m := ModuleByName(HeapModule);
- ASSERT((m.refs[0] = 0F8X) & (m.refs[1] = 0X) & (m.refs[2] = "$") & (m.refs[3] = "$") & (m.refs[4] = 0X));
- i := 5;
- ofs := VarByName(m.refs, i, CurrentMarkValueName); ASSERT(ofs # 0);
- SYSTEM.PUT(m.sb + ofs, currentMarkValue)
- END RootGlobals;
- (* ScopeInfo - Write information for debugger. *)
- PROCEDURE ScopeInfo(diff: SIZE; baseAdr: ADDRESS; root: Module);
- VAR main: ADDRESS; m: Module; i: LONGINT;
- BEGIN
- m := root; WHILE (m # NIL) & (m.name # MainModule) DO m := m.next END;
- IF m = NIL THEN main := -1 ELSE main := ADDRESSOF(m.code[0])+diff END;
- IF main = -1 THEN String(MainModule); String(" not found"); Ln END;
- String("SCOPE.BEGIN 0"); Address(baseAdr); String("H 0"); Address(main); Char("H"); Ln;
- m := root;
- WHILE m # NIL DO
- String(" "); String(m.name); String(" 0");
- Address(ADDRESSOF(m.code[0])+diff); String("H 0");
- Hex(LEN(m.code), 8); String("H 0");
- Address(m.sb); String("H "); Int(LEN(m.typeInfo), 1); Ln;
- FOR i := 0 TO LEN(m.typeInfo)-1 DO
- String(" 0"); Hex(-1, 8); String("H 0");
- Address(SYSTEM.VAL(ADDRESS, m.typeInfo[i].tag)+diff); Char("H"); Ln
- END;
- m := m.next
- END;
- String("SCOPE.END"); Ln
- END ScopeInfo;
- (* ug *)
- PROCEDURE CheckLinkerHeap; (* ug: for debugging *)
- VAR p, tagAdr, typeDescAdr: ADDRESS; heapBlock: HeapBlock;
- BEGIN
- (* find last block in static heap *)
- p := beginMemBlockAdr;
- heapBlock := SYSTEM.VAL(HeapBlock, p + BlockHeaderSize);
- WHILE p < endMemBlockAdr DO
- SYSTEM.GET(SYSTEM.VAL(ADDRESS, heapBlock) + TypeDescOffset, tagAdr);
- IF tagAdr = freeBlockTag THEN
- String("FreeBlock at adr = "); Address(p); Ln
- ELSIF tagAdr = systemBlockTag THEN
- String("SystemBlock at adr = "); Address(p); Ln
- ELSIF tagAdr = recordBlockTag THEN
- SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
- String("RecordBlock at adr = "); Address(p); String(" type = "); WriteType(typeDescAdr); Ln
- ELSIF tagAdr = protRecBlockTag THEN
- SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
- String("ProtRecBlock at adr = "); Address(p); String(" type = "); WriteType(typeDescAdr); Ln
- ELSIF tagAdr = arrayBlockTag THEN
- SYSTEM.GET(heapBlock.dataAdr + TypeDescOffset, typeDescAdr);
- String("ArrayBlock at adr = "); Address(p); String(" element type = "); WriteType(typeDescAdr); Ln
- ELSE
- HALT(9999)
- END;
- p := p + heapBlock.size;
- heapBlock := SYSTEM.VAL(HeapBlock, p + BlockHeaderSize)
- END
- END CheckLinkerHeap;
- (** Close - Finalize the log file etc. *)
- PROCEDURE Close*(w: Files.Writer; loadAdr: ADDRESS; res: LONGINT; CONST msg: ARRAY OF CHAR; log: Streams.Writer);
- VAR i: LONGINT; adr: ADDRESS; diff: SIZE; ch: CHAR;
- BEGIN
- IF res = 0 THEN
- IF baseAdr = -1 THEN diff := 0 ELSE diff := baseAdr - beginAdr END;
- FixupTypeDescTags;
- InitTable(diff, baseAdr, loadAdr); (* InitTable call before FixupHeapBlockTags since InitTable creates new heap block, i.e. init block *)
- (* no heap block allocations in linker heap from this point on *)
- memBlock.endBlockAdr := freeAdr; (* set correct end block address of linker heap *)
- memBlock.size := freeAdr - beginMemBlockAdr; (* set correct size of whole memory block *)
- FixupHeapBlockTags; (* FixupHeapBlockTags before RootGlobals since heap block tags will be rooted in boot file *)
- RootGlobals;
- ScopeInfo(diff, baseAdr, SYSTEM.VAL(Module, root));
- RelocateMemoryBlock;
- RelocateModules;
- RelocateProcOffsets;
- RelocateExports;
- (* relocate addresses *)
- FOR i := 0 TO relocates-1 DO
- SYSTEM.GET(relocateAdr[i], adr);
- IF adr # 0 THEN
- IF ~(((adr > beginMemBlockAdr) & (adr <= freeAdr))) THEN
- KernelLog.String("problem with adr in Linker0.Close ");
- KernelLog.Int(beginMemBlockAdr,1);
- KernelLog.String("<=");
- KernelLog.Int(adr,1);
- KernelLog.String("<=");
- KernelLog.Int(freeAdr,1);
- KernelLog.String(" at "); KernelLog.Int(i,1); KernelLog.String(":"); KernelLog.Int(relocates,1);
- KernelLog.String(" Check for fixup duplicates ! ");
- KernelLog.Ln;
- END;
- (*ASSERT((adr > beginMemBlockAdr) & (adr <= freeAdr));*)
- SYSTEM.PUT(relocateAdr[i], adr + diff)
- END
- END;
- (* output *)
- IF TraceDump THEN
- SortRelocates; curRelocate := 0; (* for highlighting of relocations *)
- Memory(beginAdr, freeAdr - beginAdr);
- ASSERT(curRelocate = -1) (* all relocations highlighted *)
- END;
- String(" exports: "); Int(exportTags, 1); String(" relocates: "); Int(relocates, 1);
- IF TraceRefs THEN String(" possible missed references: "); Int(refsMissed, 1) END;
- Ln;
- FOR adr := beginAdr TO freeAdr - 1 DO
- SYSTEM.GET(adr, ch);
- w.Char( ch)
- END;
- FOR adr := 1 TO AddressSize DO
- w.Char(0X)
- END;
- String("Written bytes"); Char(" "); Address(freeAdr - beginAdr+AddressSize); Ln
- END;
- String("Result = "); Int(res, 1); Char(" "); String(msg); Ln; logWriter.Update;
- IF res = 0 THEN
- log.String("Linker0 Ok. #Bytes= "); log.Address(freeAdr - beginAdr);
- IF logFile # NIL THEN
- log.String(" "); log.String(LogName);
- END;
- ELSE
- log.String( "Error report in "); log.String( LogName);
- END;
- log.Ln;
- IF logFile # NIL THEN
- logWriter.Update();
- logFile.Update();
- Files.Register(logFile);
- logFile := NIL; logWriter := NIL
- END;
- END Close;
- (* NewModule - Allocate a module descriptor (protected record) *)
- PROCEDURE NewModule*(VAR m: Module);
- VAR size, blockSize: SIZE; protRecBlockAdr, dataBlockAdr: ADDRESS;
- protRecBlock: ProtRecBlock; i: LONGINT;
- BEGIN
- size := SYSTEM.GET32(SYSTEM.TYPECODE(Module));
- blockSize := BlockHeaderSize + SIZEOF(ProtRecBlockDesc) + BlockHeaderSize + size;
- INC(blockSize, (-blockSize) MOD BlockSize); (* round up to multiple of BlockSize *)
- protRecBlockAdr := NewBlock(blockSize) + BlockHeaderSize;
- SYSTEM.PUT(protRecBlockAdr + TypeDescOffset, ProtRecBlockId);
- SYSTEM.PUT(protRecBlockAdr + HeapBlockOffset, NilVal);
- dataBlockAdr := protRecBlockAdr + SIZEOF(ProtRecBlockDesc) + BlockHeaderSize;
- SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* will be set later *)
- SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, protRecBlockAdr);
- Relocate(dataBlockAdr + HeapBlockOffset);
- protRecBlock := SYSTEM.VAL(ProtRecBlock, protRecBlockAdr);
- protRecBlock.mark := currentMarkValue;
- protRecBlock.dataAdr := dataBlockAdr;
- protRecBlock.nextRealtime := NIL; (* default value NIL since module is never a realtime object *)
- Relocate(ADDRESSOF(protRecBlock.dataAdr));
- Relocate(ADDRESSOF(protRecBlock.nextRealtime));
- protRecBlock.size := blockSize;
- protRecBlock.count := 0;
- protRecBlock.awaitingLock.head := NIL;
- protRecBlock.awaitingLock.tail := NIL;
- protRecBlock.awaitingCond.head := NIL;
- protRecBlock.awaitingCond.tail := NIL;
- protRecBlock.lockedBy := NIL;
- protRecBlock.lock := NIL;
- FOR i := 0 TO NumPriorities - 1 DO
- protRecBlock.waitingPriorities[i] := 0
- END;
- INC(protRecBlock.waitingPriorities[0]); (* set sentinel value: assume that idle process with priority 0 waits on this resource *)
- m := SYSTEM.VAL(Module, dataBlockAdr);
- Fill4(dataBlockAdr, (blockSize - SIZEOF(ProtRecBlockDesc) - 2 * BlockHeaderSize) DIV 4, 0); (* clear everything except tag & header *)
- END NewModule;
- (* NewExportDesc - Allocate an export array. *)
- PROCEDURE NewExportDesc*(VAR p: ExportArray; numElems: LONGINT);
- VAR adr: ADDRESS; block: ANY;
- BEGIN
- NewRealArr(block, numElems, SIZEOF(ExportDesc), 1);
- adr := SYSTEM.VAL(ADDRESS, block);
- SYSTEM.PUT(adr + LenOfs, numElems);
- p := SYSTEM.VAL(ExportArray, block);
- IF exportTags = LEN(exportTagAdr) THEN GrowTable(exportTagAdr) END;
- exportTagAdr[exportTags] := adr + TypeDescOffset; INC(exportTags);
- END NewExportDesc;
- PROCEDURE ArraySize*(numElems, elemSize: SIZE; numDims: LONGINT): SIZE;
- VAR arrSize, arrayDataOffset: SIZE;
- BEGIN
- arrSize := numElems * elemSize;
- arrayDataOffset := numDims * AddressSize + 3 * AddressSize;
- INC(arrayDataOffset,(-arrayDataOffset) MOD ArrayAlignment); (* align to multiple of ArrayAlignment *)
- RETURN arrayDataOffset + arrSize
- END ArraySize;
- (* NewProcOffsets - Allocate a procedure offset table *)
- PROCEDURE NewProcOffsets(VAR p: ProcOffsetTable; numElems: LONGINT);
- VAR adr: ADDRESS; block: ANY;
- BEGIN
- NewSys(block, ArraySize(numElems, SIZEOF(ProcOffsetEntry), 1));
- adr := SYSTEM.VAL(ADDRESS, block);
- SYSTEM.PUT(adr + LenOfs, numElems);
- p := SYSTEM.VAL(ProcOffsetTable, block)
- END NewProcOffsets;
- (* NewPtrOffsets - Allocate a pointer offset table *)
- PROCEDURE NewPtrOffsets(VAR p: PtrTable; numElems: LONGINT);
- VAR adr: ADDRESS; block: ANY;
- BEGIN
- NewSys(block, ArraySize(numElems, SIZEOF(SIZE), 1));
- adr := SYSTEM.VAL(ADDRESS, block);
- SYSTEM.PUT(adr + LenOfs, numElems);
- p := SYSTEM.VAL(PtrTable, block)
- END NewPtrOffsets;
- (* fit memory block at given start address - relocation of addresses is done later, see RelocateMemoryBlock *)
- PROCEDURE FitMemoryBlock(startAdr: ADDRESS; size: SIZE; VAR memBlock: MemoryBlock);
- VAR blockSize: SIZE; recordBlock: RecordBlock; recordBlockAdr, dataBlockAdr: ADDRESS;
- BEGIN
- blockSize := BlockHeaderSize + SIZEOF(RecordBlockDesc) + BlockHeaderSize + SIZEOF(MemoryBlockDesc);
- INC(blockSize,(-blockSize) MOD BlockSize); (* align to multiple of BlockSize *)
- recordBlockAdr := startAdr + BlockHeaderSize;
- SYSTEM.PUT(recordBlockAdr + TypeDescOffset, RecordBlockId); (* temporary tag value, fixup and relocation are done later *)
- SYSTEM.PUT(recordBlockAdr + HeapBlockOffset, NilVal);
- dataBlockAdr := recordBlockAdr + SIZEOF(RecordBlockDesc) + BlockHeaderSize;
- SYSTEM.PUT(dataBlockAdr + TypeDescOffset, NilVal); (* type descriptor tag will be filled in FixupTypeDescTags *)
- SYSTEM.PUT(dataBlockAdr + HeapBlockOffset, recordBlockAdr); (* reference to heap block descriptor *)
- recordBlock := SYSTEM.VAL(RecordBlock, recordBlockAdr);
- recordBlock.mark := currentMarkValue;
- recordBlock.dataAdr := dataBlockAdr;
- recordBlock.size := blockSize;
- recordBlock.nextRealtime := NIL;
- memBlock := SYSTEM.VAL(MemoryBlock, dataBlockAdr);
- memBlock.next := NIL;
- memBlock.startAdr := NilVal; (* will be set by Win32.Machine.Mod, unused for I386.Machine.Mod *)
- memBlock.size := 0; (* do. *)
- memBlock.beginBlockAdr := startAdr + blockSize;
- memBlock.endBlockAdr := startAdr + size;
- ASSERT(memBlock.beginBlockAdr < memBlock.endBlockAdr);
- ASSERT(memBlock.beginBlockAdr MOD BlockSize = 0);
- ASSERT(memBlock.endBlockAdr MOD BlockSize = 0);
- END FitMemoryBlock;
- (* relocate addresses of memory block *)
- PROCEDURE RelocateMemoryBlock;
- VAR type: TypeDesc; memBlockAdr: ADDRESS; recordBlock: RecordBlock;
- BEGIN
- type := ThisType(ModuleByName(MemBlockDescModule), MemBlockDescType);
- ASSERT(type # NIL);
- memBlockAdr := SYSTEM.VAL(ADDRESS, memBlock);
- SYSTEM.PUT(memBlockAdr + TypeDescOffset, type.tag);
- Relocate(memBlockAdr + TypeDescOffset);
- Relocate(memBlockAdr + HeapBlockOffset);
- SYSTEM.GET(memBlockAdr + HeapBlockOffset, recordBlock);
- (* type descriptor field of record block is relocated in FixupHeapBlockTags *)
- Relocate(ADDRESSOF(recordBlock.dataAdr));
- Relocate(ADDRESSOF(recordBlock.nextRealtime));
- Relocate(ADDRESSOF(memBlock.beginBlockAdr));
- Relocate(ADDRESSOF(memBlock.endBlockAdr))
- END RelocateMemoryBlock;
- (* InitHeap - Initialize the virtual heap. *)
- PROCEDURE InitHeap;
- VAR freeBlock: FreeBlock; alignOffset: SIZE;
- BEGIN
- SYSTEM.NEW(heap, HeapSize);
- beginMemBlockAdr := SYSTEM.VAL(ADDRESS, heap) + HeaderSize;
- alignOffset := (-beginMemBlockAdr) MOD BlockSize;
- beginMemBlockAdr := beginMemBlockAdr + alignOffset; (* round up to multiple of BlockSize *)
- beginAdr := beginMemBlockAdr - HeaderSize;
- endMemBlockAdr := beginMemBlockAdr + HeapSize - HeaderSize - alignOffset;
- DEC(endMemBlockAdr, endMemBlockAdr MOD BlockSize);
- ASSERT(beginMemBlockAdr < endMemBlockAdr);
- ASSERT(beginMemBlockAdr MOD BlockSize = 0);
- ASSERT(endMemBlockAdr MOD BlockSize = 0);
- (* represent linker heap as one large memory block that contains a single free heap block *)
- FitMemoryBlock(beginMemBlockAdr, endMemBlockAdr - beginMemBlockAdr, memBlock);
- freeBlock := SYSTEM.VAL(FreeBlock, memBlock.beginBlockAdr + BlockHeaderSize);
- InitFreeBlock(freeBlock, Unmarked, NilVal, memBlock.endBlockAdr - memBlock.beginBlockAdr);
- END InitHeap;
- (*
- Reference = {OldRef | ProcRef} .
- OldRef = 0F8X offset/n name/s {Variable} .
- ProcRef = 0F9X offset/n nofPars/n RetType procLev/1 slFlag/1 name/s {Variable} .
- RetType = 0X | Var | ArrayType | Record .
- ArrayType = 12X | 14X | 15X . (* static array, dynamic array, open array *)
- Record = 16X .
- Variable = VarMode (Var | ArrayVar | RecordVar ) offset/n name/s .
- VarMode = 1X | 3X . (* direct, indirect *)
- Var = 1X .. 0FX . (* byte, boolean, char, shortint, integer, longint, real, longreal, set, ptr, proc, string *)
- ArrayVar = (81X .. 8EX) dim/n . (* byte, boolean, char, shortint, integer, longint, real, longreal, set, ptr, proc *)
- RecordVar = (16X | 1DX) tdadr/n . (* record, recordpointer *)
- *)
- (* ProcByName - Find a procedure in the reference block. Return procedure offset, or -1 if not found. *)
- PROCEDURE ProcByName (refs: Bytes; CONST name: ARRAY OF CHAR): SIZE;
- VAR i, j, m, t, pofs: LONGINT; ch: CHAR; found: BOOLEAN;
- BEGIN
- i := 0; m := LEN(refs^); found := FALSE;
- ch := refs[i]; INC(i);
- WHILE (i < m) & ((ch = 0F8X) OR (ch = 0F9X)) & ~found DO (* proc *)
- GetNum(refs, i, pofs);
- IF ch = 0F9X THEN
- GetNum(refs, i, t); (* nofPars *)
- INC(i, 3) (* RetType, procLev, slFlag *)
- END;
- j := 0; WHILE (name[j] = refs[i]) & (name[j] # 0X) DO INC(i); INC(j) END;
- IF (name[j] = 0X) & (refs[i] = 0X) THEN
- found := TRUE
- ELSE
- WHILE refs[i] # 0X DO INC(i) END;
- INC(i);
- IF i < m THEN
- ch := refs[i]; INC(i); (* 1X | 3X | 0F8X | 0F9X *)
- WHILE (i < m) & ((ch = 1X) OR (ch = 3X)) DO (* var *)
- ch := refs[i]; INC(i); (* type *)
- IF (ch >= 81X) OR (ch = 16X) OR (ch = 1DX) THEN
- GetNum(refs, i, t) (* dim/tdadr *)
- END;
- GetNum(refs, i, t); (* vofs *)
- REPEAT ch := refs[i]; INC(i) UNTIL ch = 0X; (* vname *)
- ch := refs[i]; INC(i) (* 1X | 3X | 0F8X | 0F9X *)
- END
- END
- END
- END;
- IF ~found THEN pofs := -1 END;
- RETURN SYSTEM.VAL(SIZE, pofs)
- END ProcByName;
- (* GetProc - Return procedure address. *)
- PROCEDURE GetProc(m: Module; i: LONGINT; CONST mod, proc: ARRAY OF CHAR): ADDRESS;
- VAR adr: SIZE;
- BEGIN
- IF m.name # mod THEN (* fixup not in current module *)
- m := ModuleByName(mod) (* must have been loaded already *)
- END;
- adr := ProcByName(m.refs, proc);
- IF ~getProcs[i] THEN
- String("GetProc "); String(mod); Char("."); String(proc); Address(adr); Ln;
- getProcs[i] := TRUE
- END;
- ASSERT(adr # -1);
- RETURN ADDRESSOF(m.code[0]) + adr
- END GetProc;
- (* GetKernelProc - Return the specified kernel procedure. *)
- PROCEDURE GetKernelProc*(m: Module; num: LONGINT): ADDRESS;
- VAR adr: ADDRESS;
- BEGIN
- CASE num OF
- |243: adr := GetProc(m, 8, "Modules", "GetProcedure")
- |246: adr := GetProc(m, 1, "Objects", "Unlock")
- |247: adr := GetProc(m, 2, "Objects", "Lock")
- |249: adr := GetProc(m, 3, "Objects", "Await")
- |250: adr := GetProc(m, 4, "Objects", "CreateProcess")
- |251: adr := GetProc(m, 5, "Heaps", "NewArr")
- |252: adr := GetProc(m, 6, "Heaps", "NewSys")
- |253: adr := GetProc(m, 7, "Heaps", "NewRec")
- END;
- RETURN adr
- END GetKernelProc;
- (** Dump the log text . Use in case of trap. *)
- PROCEDURE WriteLog*;
- BEGIN
- logWriter.Update(); logFile.Update(); Files.Register(logFile); logFile := NIL; logWriter := NIL;
- KernelLog.String(LogName); KernelLog.Ln;
- END WriteLog;
- BEGIN
- suffix := DefaultExtension; prefix := "";
- logFile := NIL; logWriter := NIL;
- currentMarkValue := Unmarked + 1; (* one higher than the mark value of the free block *);
- NEW(relocateAdr, 2048); NEW(exportTagAdr, 32)
- END Linker0.
- (*
- 19.05.98 pjm Started
- 23.05.99 pjm Fixed Find for non-sorted tables
- *)
- Linker0.Find 10A3C4H
- Linker0.WriteLog
- SystemTools.Free PELinker Linker1 Linker0 ~
|