<<>> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [BITAND, BITOR, Card16FromH, Card32FromF, Comparison, FWORD, HWORD], BasicTime USING [GMT, Now], CCTypes USING[CCError, CCErrorCase], CirioTypes USING [zeroBA], Commander USING [Register, CommandProc], CommanderOps USING [ArgumentVector, Parse], Convert USING[IntFromRope, RopeFromChar], IO USING[card, EndOf, GetChar, GetFWord, GetHWord, PeekChar, PutF, PutFR, SetIndex, STREAM, time, UnsafeGetBlock], List USING[LORA, CompareProc, Sort], ObjectFiles USING [BracketNest, BracketPairKind, CNameOfStab, CreateParsed, FileSegmentPC, GlobalVarLoc, MakeUnknownVarLoc, RopeForStabType, SimpleSeg, Stab, StabBody, StabType, unspecdBitSize, VarLoc, VarLocBody, VersionStampInfo], ObjectFilesPrivate USING [AlterFunStabType, BracketPair, BracketPairBody, CheckStaticVar, FunStabInfo, FunStabSet, GetSPOffsetType, GetTypeRefProcType, HeaderBody, InstallStaticVarsType, LineNumToPCMapBody, MemorySegmentInfo, Module, ModuleBody, ModuleFromParsedAndPCProcType, ObjectFileFlavorBody, Parsed, ParsedBody, PCtoLineNumMapBody, RaiseUnreadableObjectFileForFun, ReadHeaderProcType, ReadInitialDataAsRope, ReadStab, ReadStabRope, RegisterObjectFileFlavor, ScanSymbolStabs, SLineData, StabList, StabRange, StabSet, TranslationTable, TranslationTableBody, VarLocFromStabProcType], PFS USING [PathFromRope, RopeFromPath, StreamFromOpenFile, OpenFileFromStream], PFSNames USING [PATH], Random USING [ChooseInt, Create, RandomStream], RCTW USING [GetTokenRope, RCTWData, RCTWDataBody], Rope USING[Concat, Equal, Fetch, FromChar, Index, IsEmpty, Length, Match, ROPE], SystemInterface USING[CirioFile, CloseFileSet, CreateFileSet, FileSet, GetCirioFile, GetStreamForFile, ReleaseStreamForFile]; XCOFFFiles: CEDAR MONITOR IMPORTS Basics, BasicTime, CCTypes, Commander, CommanderOps, Convert, IO, List, ObjectFiles, ObjectFilesPrivate, PFS, Random, RCTW, Rope, SystemInterface EXPORTS ObjectFiles = BEGIN CCError: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; <> ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; <> Stab: TYPE = ObjectFiles.Stab; StabBody: TYPE = ObjectFiles.StabBody; StabType: TYPE = ObjectFiles.StabType; FileSegmentPC: TYPE = ObjectFiles.FileSegmentPC; VersionStampInfo: TYPE = ObjectFiles.VersionStampInfo; <> Block: BYTE = 64H; Brac: BYTE = 65H; <> <> Fun: BYTE = 8eH; <> STSym: BYTE = 85H; <> <> GSym: BYTE = 80H; PSym: BYTE = 82H; LSym: BYTE = 81H; RSym: BYTE = 83H; SO: BYTE = 67H; HidEnt: BYTE = 6bH; <> XTYSD: BYTE = 1; -- CSECT Section Definition -- <> XMCRW: BYTE = 5; -- Read Write Data -- <> <<>> Parsed: TYPE = REF ParsedBody; ParsedBody: PUBLIC TYPE = ObjectFilesPrivate.ParsedBody; Header: TYPE = REF HeaderBody; HeaderBody: PUBLIC TYPE = ObjectFilesPrivate.HeaderBody; Module: TYPE = REF ModuleBody; ModuleBody: PUBLIC TYPE = ObjectFilesPrivate.ModuleBody; StabList: TYPE = ObjectFilesPrivate.StabList; StabSet: TYPE = ObjectFilesPrivate.StabSet; StabRange: TYPE = ObjectFilesPrivate.StabRange; MemorySegmentInfo: TYPE ~ ObjectFilesPrivate.MemorySegmentInfo; <> <<>> unspecdBitSize: CARD ~ ObjectFiles.unspecdBitSize; <> <> <> <> <> MOldsun2: CARD = 0; M68010: CARD = 1; M68020: CARD = 2; MSparc: CARD = 3; OMagic: CARD16 = 0407B; NMagic: CARD16 = 0410B; ZMagic: CARD16 = 0413B; <> <> PageSize: CARD32 = 02000H; OldPageSize: CARD32 = 00800H; <> FRelFlg: CARD16 = 0001H; FExec: CARD16 = 0002H; FLnNo: CARD16 = 0004H; FLSyms: CARD16 = 0008H; FAr16WR: CARD16 = 0080H; FAr32WR: CARD16 = 0100H; FAr32W: CARD16 = 0200H; FDynLoad: CARD16 = 1000H; FShrObj: CARD16 = 2000H; FLdMinusR: CARD16 = 8000H; <<>> <> WireHeader: TYPE = REF WireHeaderBody; WireHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ magic: Basics.HWORD, numSections: Basics.HWORD, timeDate: Basics.FWORD, symPtr: Basics.FWORD, numSyms: Basics.FWORD, sizeOptHdr: Basics.HWORD, flags: Basics.HWORD]; SectionList: TYPE = REF SectionListBody; SectionListBody: TYPE = RECORD[ list: SEQUENCE length: CARD OF SectionHeader]; SectionHeader: TYPE = REF SectionHeaderBody; SectionHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ name: Rope.ROPE _ NIL, pAddr: CARD32, vAddr: CARD32, size: CARD32, dataPtr: CARD32, relocPtr: CARD32, lnnoPtr: CARD32, numRelocEntries: CARD16, numLnnoEntries: CARD16, flags: CARD32]; WireSectionHeader: TYPE = REF WireSectionHeaderBody; WireSectionHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ name: PACKED ARRAY [0..7] OF BYTE, pAddr: Basics.FWORD, vAddr: Basics.FWORD, size: Basics.FWORD, dataPtr: Basics.FWORD, relocPtr: Basics.FWORD, lnnoPtr: Basics.FWORD, numRelocEntries: Basics.HWORD, numLnnoEntries: Basics.HWORD, flags: Basics.FWORD]; WireAuxHeader: TYPE = REF WireAuxHeaderBody; WireAuxHeaderBody: TYPE = MACHINE DEPENDENT RECORD[ magic: Basics.HWORD, vStamp: Basics.HWORD, textSize: Basics.FWORD, dataSize: Basics.FWORD, bssSize: Basics.FWORD, entryPtr: Basics.FWORD, textBase: Basics.FWORD, dataBase: Basics.FWORD, tocAddress: Basics.FWORD, entryPtSectionNum: Basics.HWORD, textSectionNum: Basics.HWORD, dataSectionNum: Basics.HWORD, tocSectionNum: Basics.HWORD, loaderSectionNum: Basics.HWORD, bssSectionNum: Basics.HWORD, maxAlignmentForText: Basics.HWORD, maxAlignmentForData: Basics.HWORD, moduleTypeField: ARRAY [0..1] OF BYTE, reservedField: ARRAY [0..1] OF BYTE, maxStackSize: Basics.FWORD, reservedFields: ARRAY [0..3] OF Basics.FWORD ]; ByteEntry: TYPE = REF ByteEntryBody; ByteEntryBody: TYPE = MACHINE DEPENDENT RECORD[ val(0:0..7): BYTE]; TwoByteEntry: TYPE = REF TwoByteEntryBody; TwoByteEntryBody: TYPE = MACHINE DEPENDENT RECORD[ val(0:0..15): Basics.HWORD]; StabSize: CARD _ 18; WireSTEntry: TYPE = REF WireSTEntryBody; WireSTEntryBody: TYPE = MACHINE DEPENDENT RECORD[ name(0: 0..63): PACKED ARRAY [0..7] OF BYTE, value(0: 64..95): Basics.FWORD, sectionNumber(0: 96..111): Basics.HWORD, derivedType(0: 112..119): BYTE, type(0: 120..127): BYTE, storageClass(0: 128..135): BYTE, numAuxEntries(0: 136..143): BYTE, pad(0: 144..159): Basics.HWORD ]; AuxType: TYPE = {symbol, file, csect}; WireSTAuxEntry: TYPE = REF WireSTAuxEntryBody; WireSTAuxEntryBody: TYPE = MACHINE DEPENDENT RECORD[ aux(0: 0..159): SELECT OVERLAID AuxType FROM symbol => [ name(0: 0..63): PACKED ARRAY [0..7] OF BYTE, pad(0: 64..159): Basics.HWORD], file => [ fileName(0: 0..111): PACKED ARRAY [0..13] OF BYTE, pad(0: 112..159): Basics.HWORD], csect => [ csectLength(0: 0..31): Basics.FWORD, parameterType(0: 32..63): Basics.FWORD, snParameterType(0: 64..79): Basics.HWORD, alignment(0: 80..84): [0..31], symbolType(0: 85..87): [0..7], storageMappingClass(0: 88..95): BYTE, stab(0: 96..127): Basics.FWORD, snStab(0: 128..143): Basics.HWORD, pad(0: 144..159): Basics.HWORD] ENDCASE]; ReadHeader: ObjectFilesPrivate.ReadHeaderProcType ~ TRUSTED { <> wHeader: WireHeader _ NEW[WireHeaderBody]; wAuxHeader: WireAuxHeader _ NEW[WireAuxHeaderBody]; nBytes: INT _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wHeader^], 0, BYTES[WireHeaderBody]]]; nBytes2: INT _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wAuxHeader^], 0, Basics.Card16FromH[wHeader.sizeOptHdr]]]; magic: CARD _ Basics.Card16FromH[wHeader.magic]; nBadMagic: BOOLEAN _ (magic # OMagic) AND (magic # NMagic)AND (magic # ZMagic); flags: CARD _ Basics.Card16FromH[wHeader.flags]; <> <> nPageSize: CARD _ 01000H; <> SymbolSize: CARD _ 18; RelocEntrySize: CARD _ 10; LnnoEntrySize: CARD _ 6; textOffset: CARD _ Basics.Card32FromF[wAuxHeader.textBase]; <> <<(IF magic = ZMagic THEN nPageSize ELSE BYTES[WireHeaderBody])>> <> <<(IF magic = ZMagic THEN 0 ELSE BYTES[WireHeaderBody]);>> textSize: CARD _ Basics.Card32FromF[wAuxHeader.textSize]; iDataSeg: MemorySegmentInfo _ [Basics.Card32FromF[wAuxHeader.dataBase], Basics.Card32FromF[wAuxHeader.dataSize]]; <> symsSeg: MemorySegmentInfo _ [Basics.Card32FromF[wHeader.symPtr], Basics.Card32FromF[wHeader.numSyms] * SymbolSize]; <> <> textLoadOffset: CARD32 _ 0; <> <> <> linnoSeg, debugSeg, textRelocSeg, dataRelocSeg: MemorySegmentInfo _ [0, 0]; <> <> numSects: CARD _ Basics.Card16FromH[wHeader.numSections]; sectionList: SectionList _ NEW[SectionListBody[numSects]]; debugIndex, textIndex, dataIndex: CARD _ LAST[CARD]; header: Header; FOR i: CARD IN [0..numSects) DO wSectionHeader: WireSectionHeader _ NEW[WireSectionHeaderBody]; nBytes: INT _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wSectionHeader^], 0, BYTES[WireSectionHeaderBody]]]; sectionList[i] _ NEW[SectionHeaderBody]; FOR j: CARD IN [0..8) DO c: CARD _ wSectionHeader.name[j]; ch: CHAR _ VAL[c]; IF c = 0 THEN EXIT; sectionList[i].name _ sectionList[i].name.Concat[Convert.RopeFromChar[from: ch, quote: FALSE]]; ENDLOOP; sectionList[i].pAddr _ Basics.Card32FromF[wSectionHeader.pAddr]; sectionList[i].vAddr _ Basics.Card32FromF[wSectionHeader.vAddr]; sectionList[i].size _ Basics.Card32FromF[wSectionHeader.size]; sectionList[i].dataPtr _ Basics.Card32FromF[wSectionHeader.dataPtr]; sectionList[i].relocPtr _ Basics.Card32FromF[wSectionHeader.relocPtr]; sectionList[i].lnnoPtr _ Basics.Card32FromF[wSectionHeader.lnnoPtr]; sectionList[i].numRelocEntries _ Basics.Card16FromH[wSectionHeader.numRelocEntries]; sectionList[i].numLnnoEntries _ Basics.Card16FromH[wSectionHeader.numLnnoEntries]; sectionList[i].flags _ Basics.Card32FromF[wSectionHeader.flags]; ENDLOOP; FOR i: CARD IN [0..numSects) DO IF Rope.Equal[sectionList[i].name, ".debug", TRUE] THEN debugIndex _ i; IF Rope.Equal[sectionList[i].name, ".text", TRUE] THEN textIndex _ i; IF Rope.Equal[sectionList[i].name, ".data", TRUE] THEN dataIndex _ i; IF Rope.Equal[sectionList[i].name, ".loader", TRUE] THEN flags _ Basics.BITOR[flags, FLdMinusR]; ENDLOOP; IF debugIndex # LAST[CARD] THEN { debugSeg _ [sectionList[debugIndex].dataPtr, sectionList[debugIndex].size]; }; IF textIndex # LAST[CARD] THEN { linnoSeg _ [sectionList[textIndex].lnnoPtr, sectionList[textIndex].numLnnoEntries * LnnoEntrySize]; textOffset _ sectionList[textIndex].dataPtr; textRelocSeg _ [sectionList[textIndex].relocPtr, sectionList[textIndex].numRelocEntries * RelocEntrySize]; }; IF dataIndex # LAST[CARD] THEN { iDataSeg.byteOffset _ sectionList[dataIndex].dataPtr; dataRelocSeg _ [sectionList[dataIndex].relocPtr, sectionList[dataIndex].numRelocEntries * RelocEntrySize]; }; header _ NEW[HeaderBody _ [ dynamic: FALSE, toolversion: BYTE[0], machtype: BYTE[0], magic: magic, flags: flags, text: [textOffset, textSize], iData: iDataSeg, textReloc: textRelocSeg, dataReloc: dataRelocSeg, syms: symsSeg, debug: debugSeg, linno: linnoSeg, textLoadOffset: textLoadOffset, bssSize: Basics.Card32FromF[wAuxHeader.bssSize], entryPoint: Basics.Card32FromF[wAuxHeader.entryPtr], nPageSize: nPageSize, nEntries: Basics.Card32FromF[wHeader.numSyms], stringOffset: symsSeg.byteOffset+symsSeg.byteLength ]]; RETURN[header]; }; <> <<>> <> <> <> <> XCOFFModuleFromParsedAndPC: ObjectFilesPrivate.ModuleFromParsedAndPCProcType ~ { <> IF whole = NIL THEN RETURN[NIL] ELSE { stabRange, pcRange: StabRange; firstX, limitX: CARD; stream: IO.STREAM; [stabRange, pcRange] _ AlternativeFindModuleStabRange[whole, spc.relPC, moduleRope]; IF stabRange.count = 0 THEN RETURN[NIL]; firstX _ stabRange.first; limitX _ stabRange.first+stabRange.count; stream _ SystemInterface.GetStreamForFile[whole.file]; <> { ENABLE UNWIND => { SystemInterface.ReleaseStreamForFile[whole.file, stream]; }; firstSO: Stab; firstPC: CARD32 _ pcRange.first; lag: LIST OF Module _ NIL; [firstSO, ] _ BasicReadStab[whole, stream, firstX]; <> FOR modules: LIST OF Module _ whole.modules, modules.rest WHILE modules # NIL DO IF modules.first.firstPC = firstPC THEN -- we already have it { SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[modules.first] }; IF firstPC < modules.first.firstPC THEN -- we should have found it by now { newModule: Module _ CreateModule[whole, stream, stabRange, pcRange]; cell: LIST OF Module _ LIST[newModule]; cell.rest _ modules; IF lag # NIL THEN lag.rest _ cell ELSE whole.modules _ cell; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[newModule]; }; lag _ modules; ENDLOOP; { newModule: Module _ CreateModule[whole, stream, stabRange, pcRange]; cell: LIST OF Module _ LIST[newModule]; IF lag # NIL THEN lag.rest _ cell ELSE whole.modules _ cell; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[newModule]; }; }; }; }; CreateModule: PROC[parsed: Parsed, stream: IO.STREAM, stabRange, pcRange: StabRange _ [0, 0]] RETURNS[Module] = { module: Module _ NEW[ModuleBody]; rctw: RCTW.RCTWData _ NEW[RCTW.RCTWDataBody]; sizes: REF KnownSizeList _ NEW[KnownSizeList _ CopyList[KnownSizes]]; firstSO: Stab; nStabs: CARD; [firstSO, ] _ BasicReadStab[parsed, stream, stabRange.first, sizes]; nStabs _ stabRange.count; <> module.whole _ parsed; module.firstStabX _ 0; module.limitStabX _ stabRange.count; module.firstPC _ pcRange.first; -- firstSO.value; module.limitPC _ parsed.header.text.byteLength; -- (bogus, but it will suffice for reasons given earlier) <> <<(I did some timing tests on a Dorado for RopeImpl. It took about 6 seconds to perform this loop, including the allocates. On the other hand, it takes about 4 seconds to spin through the entries without allocating the stab records. So, since at some point I have to traverse all the entries to find the Fun stabs, I might as well allocate them.)>> <<(we also relocate the pc value of bracket stabs.)>> module.stabs _ NEW[StabSet[nStabs]]; rctw.module _ module; {I: CARD _ 0; current: CARD _ 0; tmp: REF StabSet _ NIL; auxCount: CARD _ 0; funFlag: BOOLEAN _ FALSE; WHILE I> <> <> <> module.fileName _ PFS.PathFromRope[ObjectFilesPrivate.ReadStabRope[module.stabs[0]]]; module.staticVarsInstalled _ FALSE; module.versionStampInfo _ NIL; module.outerBracket _ NEW[BracketPairBody_[ module: module, kind: syntheticOuter, firstX: 0, limitX: module.whole.header.nEntries, firstPC: module.firstPC, pcLimit: module.limitPC, funStab: NIL, funIndex: 0, symbols: NIL, innerBrackets: NIL]]; InstallPCLineNumMaps[module, stabRange]; RETURN[module]; }; <> <<>> StabIndexTypeAndValue: TYPE = RECORD[stabX, stabXTo: CARD, stabType: StabType, value: CARD32]; NullStabIndexTypeAndValue: StabIndexTypeAndValue = [0, 0, Invalid, 0]; <> AlternativeFindModuleStabRange: PROC[whole: ObjectFilesPrivate.Parsed, relativePC: CARD, moduleRope: Rope.ROPE _ NIL] RETURNS[sr: StabRange, pcRange: StabRange _ [0, 0]] = { stream: IO.STREAM _ NIL; IF whole = NIL THEN RETURN[[0, 0]] ELSE { ENABLE UNWIND => SystemInterface.ReleaseStreamForFile[whole.file, stream]; stream _ SystemInterface.GetStreamForFile[whole.file]; [sr, pcRange] _ AlternativeFindModuleStabRangeInner[whole, relativePC, moduleRope, stream]; SystemInterface.ReleaseStreamForFile[whole.file, stream]; }; }; LastStabX: CARD = 0ffffffffH; AlternativeFindModuleStabRangeInner: PROC[whole: ObjectFilesPrivate.Parsed, relativePC: CARD, moduleRope: Rope.ROPE, stream: IO.STREAM] RETURNS[sr: StabRange, pcRange: StabRange _ [0, 0]] = { firstStabX: CARD _ 0; checkWholeFile: BOOL _ moduleRope.IsEmpty; pattern: Rope.ROPE _ Rope.Concat[moduleRope, ".*"]; baseSO: Stab _ BasicReadStab[whole, stream, firstStabX].stab; <> nextStabX: CARD _ IF baseSO.value = 0 OR baseSO.value = LastStabX THEN whole.stabLimit ELSE baseSO.value; name: Rope.ROPE _ baseSO.rope; IF baseSO.stabType # SO THEN RETURN[[0, 0]]; WHILE firstStabX < whole.stabLimit DO maxPC: CARD _ 0; minPC: CARD _ LAST[CARD]; highDbx: CARD _ baseSO.stabX; IF checkWholeFile OR (~name.IsEmpty AND Rope.Match[pattern, name]) THEN { FOR x: CARD _ baseSO.stabX, highDbx WHILE x < nextStabX DO info: StabIndexTypeAndValue _ CheckStab[whole, stream, x]; IF info.stabType = Fun OR info.stabType = SLine OR info.stabType = LBrac OR info.stabType = RBrac -- OR info.stabType = SO -- THEN { maxPC _ MAX[maxPC, info.value]; minPC _ MIN[minPC, info.value]; }; highDbx _ info.stabXTo + 1; ENDLOOP; IF minPC <= relativePC AND relativePC <= maxPC THEN RETURN[[baseSO.stabX, nextStabX-baseSO.stabX], [minPC, maxPC]]; }; firstStabX _ nextStabX; baseSO _ BasicReadStab[whole, stream, firstStabX].stab; <> nextStabX _ IF baseSO.value = 0 OR baseSO.value = LastStabX THEN whole.stabLimit ELSE baseSO.value; name _ baseSO.rope; ENDLOOP; SystemInterface.ReleaseStreamForFile[whole.file, stream]; RETURN[[0, 0]]; }; CheckStab: ENTRY PROC[whole: Parsed, stream: IO.STREAM, stabX: CARD] RETURNS[StabIndexTypeAndValue] = { ENABLE UNWIND => NULL; rope: Rope.ROPE _ NIL; GetRope: PROC [] RETURNS [rope: Rope.ROPE] ~ { IF stream#previousStream THEN { cloneStream_PFS.StreamFromOpenFile[openFile~PFS.OpenFileFromStream[stream]]; previousStream _ stream; }; rope _ RopeFromData[whole, stream, wireStabBuffer.name, wireStabBuffer.sectionNumber, wireStabBuffer.storageClass, IF wireStabBuffer.numAuxEntries = 0 THEN wireStabBuffer.name ELSE wsAux.name]; }; GetSymTypeAndClass: PROC [] RETURNS [symType, class: CARD] ~ { RETURN[wsAux.symbolType, wsAux.storageMappingClass] }; IO.SetIndex[stream, whole.header.syms.byteOffset+stabX*StabSize]; TRUSTED{[] _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer^], 0, StabSize]]}; IF wireStabBuffer.numAuxEntries # 0 THEN { TRUSTED{[] _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wsAux^], 0, StabSize]]}; }; RETURN[[stabX, stabX + wireStabBuffer.numAuxEntries, TypeFromData[wireStabBuffer.storageClass, GetRope, GetSymTypeAndClass, wireStabBuffer.type], Basics.Card32FromF[wireStabBuffer.value]]]; }; <<>> XCOFFVarLocFromStab: ObjectFilesPrivate.VarLocFromStabProcType ~ { <> header: Header ~ stab.module.whole.header; MkSegment: PROC [kind: ObjectFiles.SimpleSeg] RETURNS [ObjectFiles.VarLoc] ~ { segRope:Rope.ROPE; segBase: CARD ~ SELECT kind FROM text => 0, data => header.iData.byteOffset, --header.text.byteLength,-- bss => header.textReloc.byteOffset, --header.text.byteLength + header.iData.byteLength,-- ENDCASE => ERROR; <> <> SELECT kind FROM text => segRope _ "text"; data => segRope _ "data"; bss => segRope _ "bss"; ENDCASE => ERROR; RETURN [NEW [ObjectFiles.VarLocBody _ [ bitSize: IF stab.size#LAST[CARD] AND stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: fSegment[ [0, segRope], (stab.value-- - segBase--)*8, stab.value + segBase] ]]]}; SELECT stab.stabType FROM Fun => RETURN MkSegment[text]; STSym => RETURN MkSegment[data]; LCSym => RETURN MkSegment[bss]; LSym, PSym => { byteOffset: INT ~ LOOPHOLE[stab.value]; vLB: ObjectFiles.VarLoc; IF stab.stabType=PSym AND stab.size>4 AND stab.size#LAST[CARD] THEN vLB _ NEW[ObjectFiles.VarLocBody _ [ bitSize: stab.size*8, where: indirect[ base: NEW[ObjectFiles.VarLocBody _ [ bitSize: 32, where: frame[bitOffset: 8*byteOffset]]], offset: CirioTypes.zeroBA]]] ELSE vLB _ NEW[ObjectFiles.VarLocBody _ [ bitSize: IF stab.size#LAST[CARD] AND stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: frame[bitOffset: 8*byteOffset]]]; RETURN[vLB]}; RSym => { vLB: ObjectFiles.VarLoc; IF stab.size>4 AND stab.size#LAST[CARD] THEN vLB _ NEW[ObjectFiles.VarLocBody _ [ bitSize: stab.size*8, where: indirect[ base: NEW[ObjectFiles.VarLocBody _ [ bitSize: 32, where: register[regNum: stab.value]]], offset: CirioTypes.zeroBA]]] ELSE vLB _ NEW[ObjectFiles.VarLocBody _ [ bitSize: IF stab.size#LAST[CARD] AND stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: register[regNum: stab.value]]]; RETURN[vLB] }; GSym => RETURN [NEW [ObjectFiles.VarLocBody _ [ bitSize: IF stab.size#LAST[CARD] AND stab.size#0 THEN stab.size*8 ELSE unspecdBitSize, where: namedCommon[Rope.Concat["_", ObjectFiles.CNameOfStab[stab]], 0, 0, FALSE, FALSE] ]]]; ENDCASE => RETURN ObjectFiles.MakeUnknownVarLoc[IO.PutFR["unrecognized stabType (%02xH) for %g", [cardinal[stab.size]], [rope[ObjectFiles.CNameOfStab[stab]]] ]]; }; <> PCtoLineNumMap: TYPE = REF PCtoLineNumMapBody; PCtoLineNumMapBody: TYPE = ObjectFilesPrivate.PCtoLineNumMapBody; <> LineNumToPCMap: TYPE = REF LineNumToPCMapBody; LineNumToPCMapBody: TYPE = ObjectFilesPrivate.LineNumToPCMapBody; <> SLineData: TYPE = ObjectFilesPrivate.SLineData; FMap: TYPE ~ LIST OF FMapData; FMapBody: TYPE ~ RECORD [ seq: SEQUENCE len: CARD OF FMapData]; FMapData: TYPE ~ REF FMapDataBody; FMapDataBody: TYPE ~ RECORD[ fName: Rope.ROPE, stabOffset: CARD]; InstallPCLineNumMaps: PROC[module: Module, stabRange: StabRange] = { fMap, fMapTmp: FMap _ NIL; firstStabX: CARD _ stabRange.first; limitStabX: CARD _ stabRange.first + stabRange.count; CompareByCLineNum: PROC[ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = BEGIN info1: REF SLineData _ NARROW[ref1]; info2: REF SLineData _ NARROW[ref2]; IF info1.cLineNum < info2.cLineNum THEN RETURN[less]; IF info1.cLineNum > info2.cLineNum THEN RETURN[greater]; IF info1.parsedRelPC.relPC < info2.parsedRelPC.relPC THEN RETURN[less]; IF info1.parsedRelPC.relPC > info2.parsedRelPC.relPC THEN RETURN[greater]; RETURN[equal]; END; CompareByPC: PROC[ref1: REF ANY, ref2: REF ANY] RETURNS [Basics.Comparison] = BEGIN info1: REF SLineData _ NARROW[ref1]; info2: REF SLineData _ NARROW[ref2]; IF info1.parsedRelPC.relPC < info2.parsedRelPC.relPC THEN RETURN[less]; IF info1.parsedRelPC.relPC > info2.parsedRelPC.relPC THEN RETURN[greater]; IF info1.cLineNum < info2.cLineNum THEN RETURN[less]; IF info1.cLineNum > info2.cLineNum THEN RETURN[greater]; RETURN[equal]; END; <> <> <> <> <> < info2.stabOffset THEN RETURN[greater];>> <> <> <<>> IF module.pcToLineNum # NIL OR module.lineNumToPC # NIL THEN { IF module.pcToLineNum = NIL OR module.lineNumToPC = NIL THEN ERROR; RETURN; }; <> { nItems: INTEGER _ 0; list1: LIST OF REF ANY _ NIL; -- LIST OF REF SLineData list2: LIST OF REF ANY _ NIL; -- LIST OF REF SLineData sortedList: LIST OF REF ANY _ NIL; linno, relPC, pOffset: CARD _ 0; inCurrentModule: BOOLEAN _ FALSE; stream: IO.STREAM _ SystemInterface.GetStreamForFile[module.whole.file]; IO.SetIndex[stream, module.whole.header.linno.byteOffset]; FOR I: CARD IN [0..module.whole.header.linno.byteLength / 6) DO IO.SetIndex[stream, module.whole.header.linno.byteOffset + I*6]; relPC _ Basics.Card32FromF[IO.GetFWord[stream]]; linno _ Basics.Card16FromH[IO.GetHWord[stream]]; IF linno = 0 THEN IF relPC <= limitStabX AND relPC >= firstStabX THEN { inCurrentModule _ TRUE; IO.SetIndex[stream, module.whole.header.syms.byteOffset + 18 * relPC + 18 * 5 + 4]; pOffset _ Basics.Card16FromH[IO.GetHWord[stream]]; } ELSE inCurrentModule _ FALSE ELSE IF inCurrentModule THEN { info: REF SLineData _ NEW[SLineData _ [cLineNum: linno + pOffset - 1, parsedRelPC: [[0 --??--, PFS.RopeFromPath[module.fileName]], relPC]]]; list1 _ CONS[info, list1]; list2 _ CONS[info, list2]; nItems_nItems + 1; }; ENDLOOP; SystemInterface.ReleaseStreamForFile[module.whole.file, stream]; <> <> <> <> <> <> <> <> <<>> sortedList _ List.Sort[list1, CompareByCLineNum]; module.lineNumToPC _ NEW[LineNumToPCMapBody[nItems]]; FOR I: INTEGER IN [0..nItems) DO info: REF SLineData _ NARROW[sortedList.first]; module.lineNumToPC[I] _ info^; sortedList _ sortedList.rest; ENDLOOP; sortedList _ List.Sort[list2, CompareByPC]; module.pcToLineNum _ NEW[PCtoLineNumMapBody[nItems]]; FOR I: INTEGER IN [0..nItems) DO info: REF SLineData _ NARROW[sortedList.first]; module.pcToLineNum[I] _ info^; sortedList _ sortedList.rest; ENDLOOP; }; }; <<>> <> <<>> <> <> <> <> BasicReadStab: ENTRY PROC[parsed: Parsed, stream: IO.STREAM, stabX: CARD, sizes: REF KnownSizeList _ NIL] RETURNS[stab: Stab, nAux: CARD _ 0] ~ { ENABLE UNWIND => NULL; stab _ NEW[StabBody]; [stab^, nAux] _ ReadStabBody[parsed, stream, stabX, sizes]; RETURN }; TypeFromData: PROC [data: BYTE, getName: PROC RETURNS [Rope.ROPE], getSymTypeAndClass: PROC RETURNS [symType, class: CARD], typ: BYTE _ 0] RETURNS [stabType: StabType] ~ { dataVal: CARD _ data; typeVal: CARD _ typ; IF typeVal = 20H THEN stabType _ Fun ELSE SELECT dataVal FROM Block => { name: Rope.ROPE _ getName[]; SELECT TRUE FROM Rope.Equal[".bb", name] => stabType _ LBrac; Rope.Equal[".eb", name] => stabType _ RBrac; ENDCASE => ERROR; }; Brac => { name: Rope.ROPE _ getName[]; SELECT TRUE FROM Rope.Equal[".bf", name] => stabType _ LBrac; Rope.Equal[".ef", name] => stabType _ RBrac; ENDCASE => ERROR; }; <<00000H => SLine; -- no SLine s in XCOFF>> < stabType _ Fun; -- gets in the way.>> PSym => stabType _ PSym; LSym => stabType _ LSym; RSym => stabType _ RSym; STSym => stabType _ STSym; <<00000H => LCSym; -- ?>> GSym => stabType _ GSym; HidEnt => { symType, class: CARD; [symType, class] _ getSymTypeAndClass[]; IF symType = XTYSD AND class = XMCRW THEN stabType _ Invalid ELSE stabType _ Unspecified; }; <<00000H => Main; -- not used?>> SO => stabType _ SO; <<00000H => BIncl;>> <<00000H => EIncl;>> <<00000H => SOL;>> ENDCASE => stabType _ Unspecified }; DebugStab: CARD = 0fffeH; previousStream: IO.STREAM _ NIL; cloneStream: IO.STREAM _ NIL; ReadStabBody: PROC [parsed: Parsed, stream: IO.STREAM, stabX: CARD, sizes: REF KnownSizeList] RETURNS [stab: StabBody, nAux: CARD _ 0] ~ { size: CARD; rope: Rope.ROPE _ NIL; GetRope: PROC [] RETURNS [Rope.ROPE] ~ { RETURN[rope] }; GetSymTypeAndClass: PROC [] RETURNS [symType, class: CARD] ~ { RETURN[wsAux.symbolType, wsAux.storageMappingClass] }; IO.SetIndex[stream, parsed.header.syms.byteOffset+stabX*StabSize]; TRUSTED{[] _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wireStabBuffer^], 0, StabSize]]}; IF wireStabBuffer.numAuxEntries # 0 THEN { TRUSTED{[] _ IO.UnsafeGetBlock[stream, [LOOPHOLE[@wsAux^], 0, StabSize]]}; }; nAux _ wireStabBuffer.numAuxEntries; IF stream#previousStream THEN { cloneStream_PFS.StreamFromOpenFile[openFile~PFS.OpenFileFromStream[stream]]; previousStream _ stream; }; rope _ RopeFromData[parsed, cloneStream, wireStabBuffer.name, wireStabBuffer.sectionNumber, wireStabBuffer.storageClass, IF wireStabBuffer.numAuxEntries = 0 THEN wireStabBuffer.name ELSE wsAux.name]; IF sizes # NIL THEN [size, sizes^] _ SizeFromName[rope, sizes^] ELSE size _ 0; stab _ [ module: NIL, stabX: stabX, stabType: TypeFromData[wireStabBuffer.storageClass, GetRope, GetSymTypeAndClass, wireStabBuffer.type], --wireStabBuffer.type, value: Basics.Card32FromF[wireStabBuffer.value], size: size, rope: rope ]; RETURN}; dataChar: ByteEntry _ NEW[ByteEntryBody]; RopeFromData: PROC [parsed: Parsed, stream: IO.STREAM, data: PACKED ARRAY [0..7] OF BYTE, sn: Basics.HWORD, storeClass: BYTE, auxData: PACKED ARRAY [0..7] OF BYTE] RETURNS [name: Rope.ROPE _ NIL] ~ TRUSTED { len: TwoByteEntry _ NEW[TwoByteEntryBody]; dbg: BOOL _ IF Basics.Card16FromH[sn] = DebugStab THEN TRUE ELSE FALSE; sum, offset: CARD _ 0; IF dbg AND storeClass = 67H THEN { data _ auxData; dbg _ FALSE; }; offset _ IF dbg THEN parsed.header.debug.byteOffset ELSE parsed.header.stringOffset; FOR i: CARD IN [0..4) DO n: CARD _ data[i]; sum _ sum + n; ENDLOOP; IF sum = 0 THEN { FOR i: CARD IN [4..8) DO n: CARD _ data[i]; sum _ sum * 256 + n; ENDLOOP; IO.SetIndex[stream, offset + sum]; IF IO.EndOf[stream] THEN RETURN[""]; DO c: CHAR _ ' ; c _ IO.GetChar[stream]; <> <> IF c = VAL[0] THEN EXIT; name _ name.Concat[Convert.RopeFromChar[from: c, quote: FALSE]]; ENDLOOP; } ELSE FOR i: CARD IN [0..8) DO num: CARD _ data[i]; IF num = 0 THEN EXIT; name _ name.Concat[Convert.RopeFromChar[from: VAL[num], quote: FALSE]]; ENDLOOP; RETURN }; wireStabBuffer: WireSTEntry _ NEW[WireSTEntryBody]; wsAux: WireSTAuxEntry _ NEW[WireSTAuxEntryBody]; <> RandomTestFindStabRange: Commander.CommandProc = { args: CommanderOps.ArgumentVector _ CommanderOps.Parse[cmd]; path: PATH _ PFS.PathFromRope[args[1]]; fileSet: SystemInterface.FileSet _ SystemInterface.CreateFileSet[]; { ENABLE UNWIND => SystemInterface.CloseFileSet[fileSet]; file: SystemInterface.CirioFile _ SystemInterface.GetCirioFile[fileSet, path]; nextSeed: INT _ IF args.argc < 3 THEN 4466 ELSE Convert.IntFromRope[args[2]]; start: BasicTime.GMT _ BasicTime.Now[]; WHILE TRUE DO rs: Random.RandomStream _ Random.Create[seed: nextSeed]; whole: Parsed _ ObjectFiles.CreateParsed[file, "XCOFF"]; IO.PutF[cmd.out, "beginning seed = %g at %g\N", IO.card[nextSeed], IO.time[start]]; FOR I: INT IN [0..100) DO range: StabRange; pc: CARD _ Random.ChooseInt[rs, 0, whole.header.text.byteLength]; [range, ] _ AlternativeFindModuleStabRange[whole, pc]; IO.PutF[cmd.out, "\Tpc = %g gives firstX: %g count: %g\N", IO.card[pc], IO.card[range.first], IO.card[range.count]]; ENDLOOP; ENDLOOP; }; SystemInterface.CloseFileSet[fileSet]; }; SizeFromName: PROC[name:ROPE, sizes: KnownSizeList _ NIL] RETURNS [size: CARD _ 0, newSizes: KnownSizeList] ~ { c: CHAR; newID: CARD; where: CARD _ 0; IF sizes = NIL THEN RETURN; newSizes _ sizes; where _ Rope.Index[name, 0, ":"] + 1; IF where = ABS[name.Length[]]+ 1 THEN RETURN; IF (c _ name.Fetch[where]) # 't AND c # 'T THEN { typeID: INT; IF IsDigit[c] OR c = '- THEN [typeID, ] _ GetNum[name, where] ELSE [typeID, ] _ GetNum[name, where+1]; <> <> <> <> <> RETURN[FindInList[typeID, sizes], newSizes]; }; [newID, where] _ GetNum[name, where+ 1]; IF name.Fetch[where] # '= THEN ERROR; where _ where + 1; SELECT name.Fetch[where] FROM 'f => { type: INT; [type, where] _ GetNum[name, where+ 1]; size _ FindInList[type, sizes]; }; '*, 'e => size _ 4; 'u, 's => { [size, where] _ GetNum[name, where +1]}; 'a => { garb, start, end, type: INT; baseSize: CARD; c: CHAR _ name.Fetch[where + 1]; IF c# 'r THEN ERROR; [garb, where] _ GetNum[name, where+2]; IF name.Fetch[where] # '; THEN ERROR; [start, where] _ GetNum[name, where+1]; IF name.Fetch[where] # '; THEN ERROR; [end, where] _ GetNum[name, where+1]; IF name.Fetch[where] # '; THEN ERROR; [type, where] _ GetNum[name, where+1]; baseSize _ FindInList[type, sizes]; size _ (end - start + 1) * baseSize; }; ENDCASE => size _ 0; newSizes _ CONS[[newID, size], newSizes]; size _ 0; }; GetNum: PROC [rope: ROPE, index: CARD] RETURNS [num: INT _ 0, newIndex: CARD _ 0] ~ { len: CARD _ rope.Length[]; i: CARD; negFlag: BOOL _ FALSE; FOR i _ index, i + 1 UNTIL i = len DO c: CHAR _ rope.Fetch[i]; IF ~IsDigit[c] AND c # '- THEN { newIndex _ i; EXIT; }; IF c = '- THEN negFlag _ TRUE ELSE num _ num * 10 + (c - '0); ENDLOOP; IF i = len THEN newIndex _ i; IF negFlag THEN num _ -num; }; KnownSize: TYPE ~ RECORD[typeID: INT, size: CARD]; KnownSizeList: TYPE ~ LIST OF KnownSize; <> KnownSizes: KnownSizeList _ LIST[[-1, 4], [-2, 1], [-3, 2], [-4, 4], [-5, 1], [-6, 1], [-7, 2], [-8, 4], [-9, 4], [-10, 4], [-11, 0], [-12, 4], [-13, 8], [-14, 10], [-15, 4], [-16, 1], [-17, 4], [-18, 8], [-19, 1], [-20, 1], [-21, 1], [-22, 2], [-23, 1], [-24, 1], [-25, 8], [-26, 16], [-27, 1], [-28, 2], [-29, 4], [-30, 2]]; CopyList: PROC [l: KnownSizeList] RETURNS [n: KnownSizeList _ NIL] ~ { n _ NIL; FOR i: KnownSizeList _ l, i.rest WHILE i # NIL DO n _ CONS[i.first, n]; ENDLOOP; }; FindInList: PROC [i: INT, l: KnownSizeList] RETURNS [s: CARD _ LAST[CARD]] ~ { FOR loop: KnownSizeList _ l, loop.rest WHILE loop # NIL DO IF loop.first.typeID = i THEN RETURN[loop.first.size]; ENDLOOP; ERROR; }; IsDigit: PROC [c: CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9]] }; XCOFFGetTypeRef: ObjectFilesPrivate.GetTypeRefProcType ~ { <> typeRef: Rope.ROPE; lastChar: CHAR; IF IsDigit[lastChar _ IO.PeekChar[sourceStream]] OR lastChar = '- THEN { typeRef _ RCTW.GetTokenRope[sourceStream]; RETURN[typeRef]} ELSE DO lastChar _ IO.GetChar[sourceStream]; typeRef _ Rope.Concat[typeRef, Rope.FromChar[lastChar]]; IF lastChar = ') THEN RETURN[typeRef] ENDLOOP }; <> XCOFFInstallBracketPairsForOneFunStab: PROC[module: Module, funStabIndex: CARD] = { funStab: Stab _ module.funStabs[funStabIndex].stab; paramNames, lastParamName: LIST OF Rope.ROPE _ NIL; paramStabs, lastParamStab: LIST OF Stab _ NIL; -- includes param mod stabs x: CARD _ funStab.stabX+1; good: BOOL _ TRUE; <<>> module.funStabs[funStabIndex].brackets _ NEW[BracketPairBody_[ module: module, kind: syntheticFun, firstX: funStab.stabX, limitX: 0, firstPC: funStab.value, pcLimit: 0, funStab: funStab, funIndex: funStabIndex, symbols: NIL, innerBrackets: NIL]]; <> <> <> <> <> <<>> <> <<>> WHILE x < module.limitStabX DO stab: Stab _ ObjectFilesPrivate.ReadStab[module, x]; TakeBP: PROC ~ { finalRBracX: CARD; [finalRBracX, module.funStabs[funStabIndex].brackets.innerBrackets, paramStabs] _ ScanOneBracketPairSequence[module, funStab, funStabIndex, x, paramStabs, lastParamStab]; IF good THEN module.funStabs[funStabIndex].brackets.limitX _ finalRBracX+1; module.funStabs[funStabIndex].brackets.pcLimit _ IF finalRBracX { stabCell: LIST OF Stab _ LIST[stab]; name: Rope.ROPE _ ObjectFiles.CNameOfStab[stab]; nameCell: LIST OF Rope.ROPE _ LIST[name]; IF paramStabs#NIL AND stab=paramStabs.first THEN ERROR; IF paramNames = NIL THEN paramNames _ nameCell ELSE lastParamName.rest _ nameCell; lastParamName _ nameCell; IF paramStabs = NIL THEN paramStabs _ stabCell ELSE lastParamStab.rest _ stabCell; lastParamStab _ stabCell}; RSym, LSym => { stabCell: LIST OF Stab _ LIST[stab]; name: Rope.ROPE _ ObjectFiles.CNameOfStab[stab]; isAParam: BOOLEAN _ FALSE; -- initial value FOR pNames: LIST OF Rope.ROPE _ paramNames, pNames.rest WHILE pNames # NIL DO IF Rope.Equal[name, pNames.first] THEN {isAParam _ TRUE; EXIT}; ENDLOOP; IF isAParam THEN { IF paramStabs = NIL THEN paramStabs _ stabCell ELSE lastParamStab.rest _ stabCell; lastParamStab _ stabCell} ELSE -- we are facing the first symbol of a nested block {TakeBP[]; EXIT}; }; GSym, LCSym, STSym => IF good THEN { module.funStabs[funStabIndex].brackets.limitX _ stab.stabX; good _ FALSE}; SLine, Unspecified => NULL; LBrac => {TakeBP[]; EXIT}; Fun => { IF good THEN module.funStabs[funStabIndex].brackets.limitX _ stab.stabX; module.funStabs[funStabIndex].brackets.pcLimit _ stab.value; EXIT}; ENDCASE => ObjectFilesPrivate.RaiseUnreadableObjectFileForFun[ IO.PutFR["Unexpected stab (of stabType %02xH) in intro to %g", [rope[ObjectFiles.RopeForStabType[stab.stabType]]], [rope[ObjectFiles.CNameOfStab[funStab]]] ], module, funStab]; x _ x + 1; REPEAT FINISHED => { IF good THEN module.funStabs[funStabIndex].brackets.limitX _ module.limitStabX; module.funStabs[funStabIndex].brackets.pcLimit _ module.limitPC; }; ENDLOOP; module.funStabs[funStabIndex].brackets.symbols _ paramStabs; RETURN}; <> <> <> <> <> BracketPair: TYPE ~ ObjectFilesPrivate.BracketPair; BracketPairBody: TYPE ~ ObjectFilesPrivate.BracketPairBody; ScanOneBracketPairSequence: PROC[module: Module, fun: Stab, funIndex: CARD, firstX: CARD, symHead, symTail: StabList] RETURNS[--finalRBracX-- CARD, --innerBrackets-- LIST OF BracketPair, --symbols-- StabList] = { innerBrackets: LIST OF BracketPair _ NIL; lastInnerBracket: LIST OF BracketPair _ NIL; x: CARD _ firstX; DO xAfterSymbs: CARD; stabAfterSymbs: Stab; [xAfterSymbs, symHead, symTail] _ ObjectFilesPrivate.ScanSymbolStabs[module, x, symHead, symTail]; IF xAfterSymbs >= module.limitStabX THEN RETURN[xAfterSymbs, innerBrackets, symHead]; stabAfterSymbs _ ObjectFilesPrivate.ReadStab[module, xAfterSymbs]; SELECT stabAfterSymbs.stabType FROM LBrac => { finalRBracX: CARD; nestedInnerBrackets: LIST OF BracketPair; bracket: BracketPair; bracketCell: LIST OF BracketPair; [finalRBracX, nestedInnerBrackets, symHead] _ ScanOneBracketPairSequence[module, fun, funIndex, xAfterSymbs+1, symHead, symTail]; bracket _ NEW[BracketPairBody_[ module: module, kind: actual, firstX: stabAfterSymbs.stabX, limitX: finalRBracX+1, firstPC: stabAfterSymbs.value, pcLimit: IF finalRBracX RETURN[xAfterSymbs, innerBrackets, symHead]; ENDCASE => ERROR; -- can't happen ENDLOOP}; GlobalPreDefinedTypes: REF PDTType _ NIL; GPTDs: LIST OF Rope.ROPE _ LIST [ "int:t-1=r-1;-2147483648;2147483647", "char:t-2=@s8;r-2;0;255", "short:t-3=@s16;r-3;-32768;32767", "long:t-4=-1", "unsigned char:t-5=@s8;r-5;0;255", "signed char:t-6=@s8;r-6;-128;127", "unsigned short:t-7=@s16;r-7;0;65535", "unsigned int:t-8=r-8;0;4294967295", "unsigned:t-9=-8", "unsigned long:t-10=-8", "void:t-11=r-11;0;0", "float:t-12=g-12;4", "double:t-13=g-12;8", "long double:t-14=g-12;10", "integer:t-15=-1", "boolean:t-16=efalse:0,true:1,", "shortreal:t-17=g-12;4", "real:t-18=g-12;8", "stringptr:t-19=N-19", "character:t-20=@s8;r-20;0;255", "logical*1:t-21=@s8;r-21;0;255", "logical*2:t-22=@s16;r-22;0;65535", "logical*4:t-23=r-23;0;4294967295", "logical:t-24=-23", "complex:t-25=c-25;8", "double complex:t-26=c-25;16", "integer*1:t-27=-6", "integer*2:t-28=-3", "integer*4:t-29=-1", "wchar:t-30=@s16;r-30;0;65535"]; PDTType: TYPE ~ RECORD [body: SEQUENCE length: CARD OF Rope.ROPE]; IntallPreDefinedTypes: PROC ~ { count: CARD _ 0; l: LIST OF Rope.ROPE _ NIL; FOR l _ GPTDs, l.rest UNTIL l = NIL DO count _ count + 1; ENDLOOP; GlobalPreDefinedTypes _ NEW[PDTType[count]]; l _ GPTDs; FOR index: CARD IN [0..count) DO GlobalPreDefinedTypes[index] _ l.first; l _ l.rest; ENDLOOP; }; <> GetDataSectionOffset: PROC[module: Module] RETURNS[CARD] ~ { IsDotO: PROC RETURNS[BOOL] ~ { RETURN[Basics.BITAND[module.whole.header.flags, (FLdMinusR+FShrObj+FDynLoad+FExec)] = 0]; }; <> IF IsDotO[] THEN RETURN [0]; FOR x: CARD DECREASING IN [module.firstStabX..module.limitStabX) DO stab: Stab _ ObjectFilesPrivate.ReadStab[module, x]; IF stab.stabType = Invalid THEN RETURN [stab.value]; ENDLOOP; RETURN [0]; }; XCOFFInstallStaticVars: ObjectFilesPrivate.InstallStaticVarsType ~ <> <> { numFuns: INT _ 1; dataStabOffset: CARD _ 0; -- globalFrame stab seems to be offset from versionStringStab, which has to be searched for at times... IF NOT module.staticVarsInstalled THEN FOR y: CARD IN [module.firstStabX..module.limitStabX) DO x: CARD _ module.firstStabX + module.limitStabX - 1 - y; stab: Stab _ ObjectFilesPrivate.ReadStab[module, x]; IF stab = NIL THEN LOOP; IF stab.stabType = Fun THEN { IF numFuns = 0 THEN EXIT; numFuns _ numFuns - 1; }; IF stab.stabType = STSym OR stab.stabType = LCSym THEN { IF module.versionStampStab = NIL THEN { gvi: ObjectFiles.GlobalVarLoc _ NIL; gvi _ NARROW[ObjectFilesPrivate.CheckStaticVar[stab, "versionStamp", TRUE]]; IF gvi # NIL THEN { stream: IO.STREAM _ NIL; dataRope: Rope.ROPE; module.versionStampStab _ stab; dataStabOffset _ GetDataSectionOffset[module]; dataRope _ ObjectFilesPrivate.ReadInitialDataAsRope[module, gvi.fileByteOffset + dataStabOffset]; IF dataRope.IsEmpty[] THEN { ENABLE UNWIND => SystemInterface.ReleaseStreamForFile [module.whole.file, stream]; <> <> <<.data section than usual, and the stab entry shows>> <> <> searchFor: Rope.ROPE _ "@(#)"; c: CHAR; searchForIndex: INT _ 0; found: BOOL _ FALSE; stream _ SystemInterface.GetStreamForFile[module.whole.file]; IO.SetIndex[stream, gvi.fileByteOffset + dataStabOffset]; dataRope _ ""; WHILE ~found DO tmpOffset: CARD _ 0; WHILE ((c _ IO.GetChar[stream]) # searchFor.Fetch[searchForIndex]) DO dataStabOffset _ dataStabOffset + 1; ENDLOOP; tmpOffset _ tmpOffset + 1; searchForIndex _ searchForIndex + 1; WHILE (searchForIndex < searchFor.Length[] AND (c _ IO.GetChar[stream]) = searchFor.Fetch[searchForIndex]) DO tmpOffset _ tmpOffset + 1; searchForIndex _ searchForIndex + 1; ENDLOOP; tmpOffset _ tmpOffset + 1; IF searchForIndex = searchFor.Length[] THEN found _ TRUE ELSE dataStabOffset _ dataStabOffset + tmpOffset; ENDLOOP; dataRope _ searchFor; WHILE ((c _ IO.GetChar[stream]) # '\000) DO dataRope _ dataRope.Concat[Rope.FromChar[c]]; ENDLOOP; SystemInterface.ReleaseStreamForFile [module.whole.file, stream]; }; stab.value _ stab.value+dataStabOffset; IF module.globalFrameStab # NIL THEN module.globalFrameStab.value _ module.globalFrameStab.value + dataStabOffset; IF module.globalFrameStab # NIL THEN { module.globalFrameGvl.bitOffset _ module.globalFrameGvl.bitOffset + dataStabOffset * 8; module.globalFrameGvl.fileByteOffset _ module.globalFrameGvl.fileByteOffset + dataStabOffset; }; module.versionStampInfo _ NEW[ObjectFiles.VersionStampInfo_[gvi, dataRope]]; LOOP; }; }; IF module.globalFrameStab = NIL THEN { gvi: ObjectFiles.GlobalVarLoc _ NIL; gvi _ NARROW[ObjectFilesPrivate.CheckStaticVar[stab, "globalframe", TRUE]]; IF gvi # NIL THEN { module.globalFrameStab _ stab; module.globalFrameGvl _ gvi; LOOP; }; }; }; ENDLOOP; module.staticVarsInstalled _ TRUE; }; XCOFFAlterFunStab: ObjectFilesPrivate.AlterFunStabType ~ { <> <> RETURN [module.funStabs[funStabX].stab]; }; XCOFFGetSPOffset: ObjectFilesPrivate.GetSPOffsetType ~ { <> RETURN [0]; }; <
> <<>> transTable: ObjectFilesPrivate.TranslationTable; IntallPreDefinedTypes[]; transTable _NEW[ObjectFilesPrivate.TranslationTableBody[1]]; Commander.Register["xcoffRandomTestFindStabRange", RandomTestFindStabRange]; transTable[0] _ [0, 2, 479, "XCOFF"]; ObjectFilesPrivate.RegisterObjectFileFlavor[NEW [ObjectFilesPrivate.ObjectFileFlavorBody _ [ "XCOFF", XCOFF, ReadHeader, XCOFFModuleFromParsedAndPC, XCOFFVarLocFromStab, XCOFFGetTypeRef, XCOFFInstallBracketPairsForOneFunStab, NIL, NIL, NIL, FALSE, XCOFFInstallStaticVars, XCOFFAlterFunStab, XCOFFGetSPOffset ]], transTable]; END.