<<>> <> <> <> <> <> <> <> <> 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.