<<>> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Basics USING[CompareCard, Comparison], Breakpoint USING[Break, BreakpointProc, ClearBreakpoint, EnumerateBreakpoints, SetBreakpoint, Cant, CantClear, CantSet], BreakWorldArchitecture USING[Address, AddressRep, WorldAccess, WorldAccessFromBreakWorld, BreakWorld, BreakWorldFromBreakWorldAddress, CreateBreakWorld, NewAddress, nullAddress, PatchAreaRep, Cant, WouldBlock], CCTypes USING[CCError, CCErrorCase], CirioBreakAccess USING[], CirioNubAccess USING[FileEntry, GetFileEntry, GetInstructionSetAndOperatingSystem, Handle, LookupFileEntryByStemName, LookupMatchingSymEntryByName, LookupMatchingSymEntryByValue, LookupSymEntryByName, LookupSymEntryByValue, ModuleType, MonitoredCall, RaFromCi, Read32BitsAsCard, Read4Bytes, RemoteAddress, SymEntry, TextType, Write4Bytes], CirioTargets, IO USING[card, PutFR, PutFR1], MIPSArchitecture USING [MIPSAddress, MIPSContents, MIPSAddressFromTargetAddress, MIPSContentsFromTargetContents, TargetContentsFromMIPSContents, NullMIPSAddress], RedBlackTree, Rope USING[Concat, Equal, Length, ROPE, Substr], SourceFileOpsExtras USING [FullFormatPosition, Position], SPARCArchitecture USING[SPARCAddress, SPARCAddressFromTargetAddress, SPARCContents, SPARCContentsFromTargetContents, TargetContentsFromSPARCContents, NullSPARCAddress], SystemInterface USING[ShowReport], TargetArchitecture USING[Contents]; CirioBreakAccessImpl: CEDAR MONITOR LOCKS breaks USING breaks: CirioBreakSet IMPORTS Basics, Breakpoint, BreakWorldArchitecture, CCTypes, CirioNubAccess, IO, MIPSArchitecture, RedBlackTree, Rope, SourceFileOpsExtras, SPARCArchitecture, SystemInterface EXPORTS CirioBreakAccess = BEGIN <<>> <> maxJump: CARD ~ 2**23; CirioBreakSet: TYPE = REF CirioBreakSetBody; CirioBreakSetBody: PUBLIC TYPE = MONITORED RECORD[ nub: CirioNubAccess.Handle, recentBreakIndex: CARD, breakProc: BreakWorldArchitecture.Address, breakProcDataSegment: BreakWorldArchitecture.Address, debuggeeBreakWorld: BreakWorldArchitecture.BreakWorld, afterLastSpacer: CARD, spacers: RedBlackTree.Table--of Spacer-- ]; <<>> <> <peter>CirioBreaks>FakeCirioImpl.mesa for a sample implementation>> Spacer: TYPE ~ REF SpacerPrivate; SpacerPrivate: TYPE ~ RECORD [start, size: CARD]; CirioBreakClientData: TYPE = REF CirioBreakClientDataBody; CirioBreakClientDataBody: TYPE = RECORD[ index: CARD, cardAddress: CARD32, stopAll: BOOLEAN, -- added for two kinds of breaks. break: Breakpoint.Break, breakSet: CirioBreakSet, mesaPosition: SourceFileOpsExtras.Position]; QuaBreakSet: PUBLIC PROC [ra: REF ANY] RETURNS [is: BOOL, it: CirioBreakSet] ~ { WITH ra SELECT FROM x: CirioBreakSet => RETURN [TRUE, x]; ENDCASE => RETURN [FALSE, NIL]; }; <> CreateCirioBreakSet: PUBLIC PROC[nub: CirioNubAccess.Handle, fileNameStem: Rope.ROPE, breakProcName: Rope.ROPE] RETURNS[CirioBreakSet] = BEGIN breakProcAddr, breakProcDataSegment: CARD; breaks: CirioBreakSet; breakWorld: BreakWorldArchitecture.BreakWorld; target: CirioTargets.Target _ NARROW[nub.target]; <> SPARC: Rope.ROPE _ "SPARC"; RS6000: Rope.ROPE _ "RS6000"; MIPSEL: Rope.ROPE _ "MIPSEL"; -- MIPS little endian MIPSEB: Rope.ROPE _ "MIPSEB"; -- MIPS big endian instrSet, opSys: Rope.ROPE; [instrSet, opSys] _ CirioNubAccess.GetInstructionSetAndOperatingSystem[nub]; [breakProcAddr, breakProcDataSegment] _ FindNamedProcInNamedFile[nub, fileNameStem, breakProcName]; breaks _ NEW[CirioBreakSetBody_ [nub: nub, recentBreakIndex: 0, breakProc: NIL, breakProcDataSegment: NIL, debuggeeBreakWorld: NIL, afterLastSpacer: 0, spacers: RedBlackTree.Create[SpacerGetKey, SpacerCompare] ]]; SELECT TRUE FROM Rope.Equal[instrSet, SPARC], Rope.Equal[instrSet, RS6000] => { breakWorld _ BreakWorldArchitecture.CreateBreakWorld[ name: target.instrSet, peekContents: CirioDebuggeePeekContentsProc, pokeContents: CirioDebuggeePokeContentsProc, getProcAddress: CirioDebuggeeGetProcAddressProc, getProcDataSegment: CirioDebuggeeGetDataSegmentProc, getPatchArea: CirioDebuggeeGetPatchAreaProc, monitoredCall: CirioDebuggeeMonitoredCallProc, worldAccessData: breaks]; <> }; Rope.Equal[instrSet, MIPSEL], Rope.Equal[instrSet, MIPSEB] => { breakWorld _ BreakWorldArchitecture.CreateBreakWorld[ name: target.instrSet, peekContents: MIPSCirioDebuggeePeekContentsProc, pokeContents: MIPSCirioDebuggeePokeContentsProc, getProcAddress: MIPSCirioDebuggeeGetProcAddressProc, getProcDataSegment: MIPSCirioDebuggeeGetDataSegmentProc, getPatchArea: MIPSCirioDebuggeeGetPatchAreaProc, monitoredCall: MIPSCirioDebuggeeMonitoredCallProc, worldAccessData: breaks]; }; ENDCASE => CCTypes.CCError[cirioError, "Unsupported instrSet for CirioBreakSet"]; breaks.breakProc _ IF breakProcAddr # 0 THEN BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[breakProcAddr]] ELSE BreakWorldArchitecture.nullAddress; breaks.debuggeeBreakWorld _ breakWorld; RETURN[breaks]; END; BreakWorldFromBreakSet: PUBLIC PROC[breaks: CirioBreakSet] RETURNS [BreakWorldArchitecture.BreakWorld] ~ { breakWorld: BreakWorldArchitecture.BreakWorld ~ breaks.debuggeeBreakWorld; RETURN [breakWorld]; }; ReportBreakInfo: PROC[breaks: CirioBreakSet, clientBreak: CirioBreakClientData, clientMessage: Rope.ROPE] = { symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByValue[breaks.nub, clientBreak.cardAddress, 0]; procName: Rope.ROPE _ IF symEntry = NIL THEN CCTypes.CCError[cirioError, "Bad args to LookupAddr"] ELSE symEntry.name; SystemInterface.ShowReport[IO.PutFR[ "%g%g at %g = 0x%08x (abs), stopAll=%g.\n", [rope[clientMessage]], [cardinal[clientBreak.index]], [rope[SourceFileOpsExtras.FullFormatPosition[clientBreak.mesaPosition]]], [cardinal[clientBreak.cardAddress]], [boolean[clientBreak.stopAll]] ], $urgent]; }; ClearBreakAtAbsAddr: PUBLIC ENTRY PROC[breaks: CirioBreakSet, cardAddress: CARD32] = BEGIN ENABLE { UNWIND => NULL; Breakpoint.Cant => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.Cant[%g, %g] when trying to clear break at address %g", [atom[code]], [rope[message]], [cardinal[cardAddress]] ]]; Breakpoint.CantClear => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.CantClear[%g, %g] when trying to clear break at address %g", [atom[code]], [rope[message]], [cardinal[cardAddress]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ breaks.debuggeeBreakWorld; clientBreak: CirioBreakClientData _ NIL; examineBreaks: Breakpoint.BreakpointProc = <> BEGIN tentative: CirioBreakClientData _ NARROW[clientData]; IF tentative.cardAddress = cardAddress THEN {clientBreak _ tentative; Breakpoint.ClearBreakpoint[clientBreak.break]; ReportBreakInfo[breaks, clientBreak, "Cleared break #"]; RETURN[TRUE]}; RETURN[FALSE]; END; [] _ Breakpoint.EnumerateBreakpoints[breakWorld, examineBreaks]; IF clientBreak = NIL THEN SystemInterface.ShowReport[IO.PutFR1["sorry, there is no break to clear at %g", IO.card[cardAddress]], $urgent]; <> <> <> <> <> << ELSE>> <> END; ClearBreakAtIndex: PUBLIC ENTRY PROC[breaks: CirioBreakSet, index: CARD] = BEGIN ENABLE { UNWIND => NULL; Breakpoint.Cant => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.Cant[%g, %g] when trying to clear break at index %g", [atom[code]], [rope[message]], [cardinal[index]] ]]; Breakpoint.CantClear => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.CantClear[%g, %g] when trying to clear break at index %g", [atom[code]], [rope[message]], [cardinal[index]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ breaks.debuggeeBreakWorld; clientBreak: CirioBreakClientData _ NIL; examineBreaks: Breakpoint.BreakpointProc = <> BEGIN tentative: CirioBreakClientData _ NARROW[clientData]; IF tentative.index = index THEN {clientBreak _ tentative; Breakpoint.ClearBreakpoint[clientBreak.break]; ReportBreakInfo[breaks, clientBreak, "Cleared break #"]; RETURN[TRUE]}; RETURN[FALSE]; END; [] _ Breakpoint.EnumerateBreakpoints[breakWorld, examineBreaks]; IF clientBreak = NIL THEN SystemInterface.ShowReport[IO.PutFR1["sorry, there is no break with index %g", IO.card[index]], $urgent]; <> <> <> <> <> << ELSE>> <> END; ClearAllBreaks: PUBLIC ENTRY PROC[breaks: CirioBreakSet] = BEGIN ENABLE UNWIND => NULL; breakWorld: BreakWorldArchitecture.BreakWorld _ breaks.debuggeeBreakWorld; examineBreaks: Breakpoint.BreakpointProc = <> BEGIN clientBreak: CirioBreakClientData _ NARROW[clientData]; Breakpoint.ClearBreakpoint[clientBreak.break ! Breakpoint.CantClear => { SystemInterface.ShowReport[IO.PutFR["Breakpoint.CantClear[%g, %g] when trying to clear break with index %g at %g", [atom[code]], [rope[message]], [cardinal[clientBreak.index]], [cardinal[clientBreak.cardAddress]] ], $normal]; GOTO Givup}; Breakpoint.Cant => { SystemInterface.ShowReport[IO.PutFR["Breakpoint.Cant[%g, %g] when trying to clear break with index %g at %g", [atom[code]], [rope[message]], [cardinal[clientBreak.index]], [cardinal[clientBreak.cardAddress]] ], $normal]; GOTO Givup} ]; <> ReportBreakInfo[breaks, clientBreak, "Cleared break #"]; RETURN[FALSE]; EXITS Givup => quit _ FALSE END; [] _ Breakpoint.EnumerateBreakpoints[breakWorld, examineBreaks !Breakpoint.Cant => CCTypes.CCError[cirioError, "Can't enumerate breakpoints"]]; END; BreakSetBroken: PUBLIC PROC [breaks: CirioBreakSet] RETURNS [BOOL] ~ { RETURN [breaks.breakProc = BreakWorldArchitecture.nullAddress]}; ListBreaks: PUBLIC ENTRY PROC[breaks: CirioBreakSet] = BEGIN ENABLE UNWIND => NULL; breakWorld: BreakWorldArchitecture.BreakWorld _ breaks.debuggeeBreakWorld; examineBreaks: Breakpoint.BreakpointProc = <> BEGIN clientBreak: CirioBreakClientData _ NARROW[clientData]; ReportBreakInfo[breaks, clientBreak, "Break #"]; RETURN[FALSE]; END; [] _ Breakpoint.EnumerateBreakpoints[breakWorld, examineBreaks !Breakpoint.Cant => CCTypes.CCError[cirioError, "Can't enumerate breakpoints"]]; END; SetBreakAtAbsAddr: PUBLIC ENTRY PROC[breaks: CirioBreakSet, cardAddress: CARD32, mesaPos: SourceFileOpsExtras.Position, stopAll: BOOLEAN] = BEGIN ENABLE UNWIND => NULL; stopAllDummy: CARD32 _ IF stopAll THEN 1 ELSE 0; breakWorld: BreakWorldArchitecture.BreakWorld _ breaks.debuggeeBreakWorld; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; clientData: CirioBreakClientData _ NEW[CirioBreakClientDataBody_[ breaks.recentBreakIndex _ breaks.recentBreakIndex+1, cardAddress, stopAll, NIL, breaks, mesaPos]]; address: BreakWorldArchitecture.Address _ BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[cardAddress]]; clientData.break _ Breakpoint.SetBreakpoint[address, clientData, breaks.breakProc, stopAllDummy ! Breakpoint.CantSet => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.CantSet[%g, %g] at %g", [atom[code]], [rope[message]], [cardinal[cardAddress]] ]]; Breakpoint.Cant => CCTypes.CCError[cirioError, IO.PutFR["Breakpoint.Cant[%g, %g] when trying to set break at %g", [atom[code]], [rope[message]], [cardinal[cardAddress]] ]] ]; ReportBreakInfo[breaks, clientData, "Set break #"]; END; <<>> CirioDebuggeePeekContentsProc: PROC[address: BreakWorldArchitecture.Address] RETURNS [TargetArchitecture.Contents] = BEGIN ENABLE { SPARCArchitecture.NullSPARCAddress => CCTypes.CCError[cirioError, "SPARCArchitecture.NullSPARCAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; }; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; sparcAddress: SPARCArchitecture.SPARCAddress _ SPARCArchitecture.SPARCAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[sparcAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; remoteContents: PACKED ARRAY [0..3] OF BYTE _ CirioNubAccess.Read4Bytes[remoteAddress]; sparcContents: SPARCArchitecture.SPARCContents _ LOOPHOLE[remoteContents]; RETURN[SPARCArchitecture.TargetContentsFromSPARCContents[sparcContents]]; END; MIPSCirioDebuggeePeekContentsProc: PROC[address: BreakWorldArchitecture.Address] RETURNS [TargetArchitecture.Contents] = BEGIN ENABLE { MIPSArchitecture.NullMIPSAddress => CCTypes.CCError[cirioError, "MIPSArchitecture.NullMIPSAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; }; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; mipsAddress: MIPSArchitecture.MIPSAddress _ MIPSArchitecture.MIPSAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[mipsAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; remoteContents: PACKED ARRAY [0..3] OF BYTE _ LOOPHOLE[CirioNubAccess.Read4Bytes[remoteAddress]]; mipsContents: MIPSArchitecture.MIPSContents _ LOOPHOLE[remoteContents]; RETURN[MIPSArchitecture.TargetContentsFromMIPSContents[mipsContents]]; END; CirioDebuggeePokeContentsProc: PROC[address: BreakWorldArchitecture.Address, contents: TargetArchitecture.Contents] = BEGIN ENABLE { SPARCArchitecture.NullSPARCAddress => CCTypes.CCError[cirioError, "SPARCArchitecture.NullSPARCAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; sparcAddress: SPARCArchitecture.SPARCAddress _ SPARCArchitecture.SPARCAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[sparcAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; sparcContents: SPARCArchitecture.SPARCContents _ SPARCArchitecture.SPARCContentsFromTargetContents[contents]; remoteContents: PACKED ARRAY [0..3] OF BYTE _ LOOPHOLE[sparcContents]; CirioNubAccess.Write4Bytes[remoteAddress, remoteContents]; END; MIPSCirioDebuggeePokeContentsProc: PROC[address: BreakWorldArchitecture.Address, contents: TargetArchitecture.Contents] = BEGIN ENABLE { MIPSArchitecture.NullMIPSAddress => CCTypes.CCError[cirioError, "MIPSArchitecture.NullMIPSAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; mipsAddress: MIPSArchitecture.MIPSAddress _ MIPSArchitecture.MIPSAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[mipsAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; mipsContents: MIPSArchitecture.MIPSContents _ MIPSArchitecture.MIPSContentsFromTargetContents[contents]; remoteContents: PACKED ARRAY [0..3] OF BYTE _ LOOPHOLE[mipsContents]; CirioNubAccess.Write4Bytes[remoteAddress, remoteContents]; END; CirioDebuggeeGetProcAddressProc: PROC[breakWorld: BreakWorldArchitecture.BreakWorld, procName: Rope.ROPE] RETURNS [BreakWorldArchitecture.Address] = BEGIN ENABLE BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByName[breaks.nub, procName, FALSE, FALSE, 0]; IF symEntry = NIL THEN CCTypes.CCError[cirioError, ""] ELSE RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[symEntry.value]]]; END; MIPSCirioDebuggeeGetProcAddressProc: PROC[breakWorld: BreakWorldArchitecture.BreakWorld, procName: Rope.ROPE] RETURNS [BreakWorldArchitecture.Address] = BEGIN ENABLE BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByName[breaks.nub, procName, FALSE, FALSE, 0]; IF symEntry = NIL THEN CCTypes.CCError[cirioError, ""] ELSE RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[symEntry.value]]]; END; CirioDebuggeeGetDataSegmentProc: PROC[breakWorld: BreakWorldArchitecture.BreakWorld, address: BreakWorldArchitecture.Address] RETURNS [BreakWorldArchitecture.Address] = BEGIN ENABLE BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; sparcAddress: SPARCArchitecture.SPARCAddress _ SPARCArchitecture.SPARCAddressFromTargetAddress[address.address]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByValue[breaks.nub, LOOPHOLE[sparcAddress], 0]; fileEntry: CirioNubAccess.FileEntry; tocName: Rope.ROPE; tocEntry: CirioNubAccess.SymEntry; tocAddress: CARD; IF symEntry = NIL THEN CCTypes.CCError[cirioError, ""]; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, symEntry.fileSeqNum]; IF fileEntry = NIL THEN CCTypes.CCError[cirioError, ""]; tocName _ Rope.Substr[symEntry.name, 1, Rope.Length[symEntry.name] - 1]; tocEntry _ CirioNubAccess.LookupSymEntryByName[breaks.nub, tocName, FALSE, FALSE, 0]; IF tocEntry = NIL THEN RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[fileEntry.dataReloc]]]; tocAddress _ CirioNubAccess.RaFromCi[breaks.nub, tocEntry.value, 32].Read32BitsAsCard; RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[tocAddress]]]; END; MIPSCirioDebuggeeGetDataSegmentProc: PROC[breakWorld: BreakWorldArchitecture.BreakWorld, address: BreakWorldArchitecture.Address] RETURNS [BreakWorldArchitecture.Address] = BEGIN ENABLE BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; mipsAddress: MIPSArchitecture.MIPSAddress _ MIPSArchitecture.MIPSAddressFromTargetAddress[address.address]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByValue[breaks.nub, LOOPHOLE[mipsAddress], 0]; fileEntry: CirioNubAccess.FileEntry; tocName: Rope.ROPE; tocEntry: CirioNubAccess.SymEntry; tocAddress: CARD; IF symEntry = NIL THEN CCTypes.CCError[cirioError, ""]; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, symEntry.fileSeqNum]; IF fileEntry = NIL THEN CCTypes.CCError[cirioError, ""]; tocName _ Rope.Substr[symEntry.name, 1, Rope.Length[symEntry.name] - 1]; tocEntry _ CirioNubAccess.LookupSymEntryByName[breaks.nub, tocName, FALSE, FALSE, 0]; IF tocEntry = NIL THEN RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[fileEntry.dataReloc]]]; tocAddress _ CirioNubAccess.RaFromCi[breaks.nub, tocEntry.value, 32].Read32BitsAsCard; RETURN[BreakWorldArchitecture.NewAddress[breakWorld, LOOPHOLE[tocAddress]]]; END; CirioDebuggeeGetPatchAreaProc: PROC[address: BreakWorldArchitecture.Address] RETURNS [BreakWorldArchitecture.PatchAreaRep] = { ENABLE { SPARCArchitecture.NullSPARCAddress => CCTypes.CCError[cirioError, "SPARCArchitecture.NullSPARCAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; BreakWorldArchitecture.WouldBlock => CCTypes.CCError[cirioError, IO.PutFR1["BreakWorldArchitecture.WouldBlock[%g]", [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; sparcAddress: SPARCArchitecture.SPARCAddress _ SPARCArchitecture.SPARCAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[sparcAddress]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByValue[breaks.nub, byteAddress, 0]; patchAddress: BreakWorldArchitecture.Address _ NIL; patchAreaRep: BreakWorldArchitecture.PatchAreaRep _ [NIL, 0]; key: Spacer; TrySpacers: PROC RETURNS [{no, maybe, yes}] ~ { raLeft, raAt, raRight: REF ANY; spLeft, spAt, spRight: Spacer; leftDist, rightDist: CARD _ CARD.LAST; [raLeft, raAt, raRight] _ breaks.spacers.Lookup3[key]; spLeft _ NARROW[raLeft]; spAt _ NARROW[raAt]; spRight _ NARROW[raRight]; SELECT TRUE FROM spAt#NIL, spLeft#NIL AND CARD[byteAddress-spLeft.start] < spLeft.size => CCTypes.CCError[cirioError, IO.PutFR1["trying to set breakpoint in a meadow! (at address 0x%x)", [cardinal[byteAddress]] ]]; spLeft=NIL AND spRight=NIL => RETURN[maybe]; ENDCASE => { IF spLeft#NIL THEN leftDist _ byteAddress-spLeft.start; IF spRight#NIL THEN rightDist _ spRight.start+spRight.size - byteAddress; SELECT TRUE FROM leftDist<=rightDist AND NearEnough[byteAddress, spLeft.start]=>{ patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[spLeft.start]]]; patchAreaRep _ [patchAddress, spLeft.size]; RETURN[yes]}; rightDist<=leftDist AND NearEnough[byteAddress, spRight.start+spRight.size] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[spRight.start]]]; patchAreaRep _ [patchAddress, spRight.size]; RETURN[yes]}; leftDist=CARD.LAST OR rightDist=CARD.LAST => RETURN [maybe]; ENDCASE => RETURN [no]}; }; IF symEntry # NIL THEN { fileEntry: CirioNubAccess.FileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, symEntry.fileSeqNum]; IF fileEntry.patchSize>0 THEN { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}}; key _ NEW[SpacerPrivate _ [byteAddress, 0]]; SELECT TrySpacers[] FROM yes => RETURN[patchAreaRep]; maybe => { UpdateSpacers[breaks]; IF TrySpacers[]=yes THEN RETURN[patchAreaRep]; }; no => NULL; ENDCASE => ERROR; IF symEntry # NIL THEN { lo, hi: CARD _ symEntry.fileSeqNum; gohi: BOOL _ TRUE; fileEntry: CirioNubAccess.FileEntry; WHILE gohi OR lo>1 DO IF lo>1 THEN { lo _ lo - 1; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, lo]; SELECT TRUE FROM fileEntry.patchSize=0 => NULL; NearEnough[fileEntry.patchReloc, byteAddress] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}; ENDCASE => lo _ 0; }; IF gohi THEN { hi _ hi + 1; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, hi]; SELECT TRUE FROM fileEntry.seqNum < hi => gohi _ FALSE; fileEntry.patchSize=0 => NULL; NearEnough[fileEntry.patchReloc+fileEntry.patchSize, byteAddress] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}; ENDCASE => gohi _ FALSE; }; ENDLOOP; }; CCTypes.CCError[cirioError, IO.PutFR1["no SymEntry or nearby patch space for address 0x%x", [cardinal[byteAddress]] ]] }; MIPSCirioDebuggeeGetPatchAreaProc: PROC[address: BreakWorldArchitecture.Address] RETURNS [BreakWorldArchitecture.PatchAreaRep] = { ENABLE { MIPSArchitecture.NullMIPSAddress => CCTypes.CCError[cirioError, "MIPSArchitecture.NullMIPSAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; BreakWorldArchitecture.WouldBlock => CCTypes.CCError[cirioError, IO.PutFR1["BreakWorldArchitecture.WouldBlock[%g]", [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; mipsAddress: MIPSArchitecture.MIPSAddress _ MIPSArchitecture.MIPSAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[mipsAddress]; symEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByValue[breaks.nub, byteAddress, 0]; patchAddress: BreakWorldArchitecture.Address _ NIL; patchAreaRep: BreakWorldArchitecture.PatchAreaRep _ [NIL, 0]; key: Spacer; TrySpacers: PROC RETURNS [{no, maybe, yes}] ~ { raLeft, raAt, raRight: REF ANY; spLeft, spAt, spRight: Spacer; leftDist, rightDist: CARD _ CARD.LAST; [raLeft, raAt, raRight] _ breaks.spacers.Lookup3[key]; spLeft _ NARROW[raLeft]; spAt _ NARROW[raAt]; spRight _ NARROW[raRight]; SELECT TRUE FROM spAt#NIL, spLeft#NIL AND CARD[byteAddress-spLeft.start] < spLeft.size => CCTypes.CCError[cirioError, IO.PutFR1["trying to set breakpoint in a meadow! (at address 0x%x)", [cardinal[byteAddress]] ]]; spLeft=NIL AND spRight=NIL => RETURN[maybe]; ENDCASE => { IF spLeft#NIL THEN leftDist _ byteAddress-spLeft.start; IF spRight#NIL THEN rightDist _ spRight.start+spRight.size - byteAddress; SELECT TRUE FROM leftDist<=rightDist AND NearEnough[byteAddress, spLeft.start]=>{ patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[spLeft.start]]]; patchAreaRep _ [patchAddress, spLeft.size]; RETURN[yes]}; rightDist<=leftDist AND NearEnough[byteAddress, spRight.start+spRight.size] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[spRight.start]]]; patchAreaRep _ [patchAddress, spRight.size]; RETURN[yes]}; leftDist=CARD.LAST OR rightDist=CARD.LAST => RETURN [maybe]; ENDCASE => RETURN [no]}; }; IF symEntry # NIL THEN { fileEntry: CirioNubAccess.FileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, symEntry.fileSeqNum]; IF fileEntry.patchSize>0 THEN { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}}; key _ NEW[SpacerPrivate _ [byteAddress, 0]]; SELECT TrySpacers[] FROM yes => RETURN[patchAreaRep]; maybe => { UpdateSpacers[breaks]; IF TrySpacers[]=yes THEN RETURN[patchAreaRep]; }; no => NULL; ENDCASE => ERROR; IF symEntry # NIL THEN { lo, hi: CARD _ symEntry.fileSeqNum; gohi: BOOL _ TRUE; fileEntry: CirioNubAccess.FileEntry; WHILE gohi OR lo>1 DO IF lo>1 THEN { lo _ lo - 1; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, lo]; SELECT TRUE FROM fileEntry.patchSize=0 => NULL; NearEnough[fileEntry.patchReloc, byteAddress] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}; ENDCASE => lo _ 0; }; IF gohi THEN { hi _ hi + 1; fileEntry _ CirioNubAccess.GetFileEntry[breaks.nub, hi]; SELECT TRUE FROM fileEntry.seqNum < hi => gohi _ FALSE; fileEntry.patchSize=0 => NULL; NearEnough[fileEntry.patchReloc+fileEntry.patchSize, byteAddress] => { patchAddress _ NEW[BreakWorldArchitecture.AddressRep_[breakWorld, LOOPHOLE[fileEntry.patchReloc]]]; patchAreaRep _ [patchAddress, fileEntry.patchSize]; RETURN[patchAreaRep]}; ENDCASE => gohi _ FALSE; }; ENDLOOP; }; CCTypes.CCError[cirioError, IO.PutFR1["no SymEntry or nearby patch space for address 0x%x", [cardinal[byteAddress]] ]] }; NearEnough: PROC [a, b: CARD] RETURNS [BOOL] ~ { SELECT TRUE FROM a=b => RETURN [TRUE]; a RETURN [b-a < 2**21]; a>b => RETURN [a-b < 2**21]; ENDCASE => ERROR}; UpdateSpacers: PROC [breaks: CirioBreakSet] ~ { se: CirioNubAccess.SymEntry; target: CirioTargets.Target _ NARROW[breaks.nub.target]; highest: CARD _ 0; some: BOOL _ FALSE; FOR se _ CirioNubAccess.LookupSymEntryByName[h: breaks.nub, sym: target.CNameToLoaderName[target, "SomePatchSpace"], caseSensitive: FALSE, externOnly: FALSE, numToSkip: 0], CirioNubAccess.LookupMatchingSymEntryByName[h: breaks.nub, symID: se.symID, pattern: target.CNameToLoaderName[target, "SomePatchSpace"], caseSensitive: FALSE, wantedTypes: CirioNubAccess.TextType, ignoreClasses: 2--externals--, numToSkip: -1] WHILE se#NIL AND se.value >= breaks.afterLastSpacer DO s: Spacer ~ NEW [SpacerPrivate _ [se.value, spacerSize]]; breaks.spacers.Insert[s, s]; highest _ MAX[highest, se.value]; some _ TRUE; ENDLOOP; IF some THEN breaks.afterLastSpacer _ MAX[breaks.afterLastSpacer, highest+spacerSize]; RETURN}; spacerSize: CARD ~ 8192--that's how much the source reserves--; SpacerGetKey: PROC [data: REF ANY] RETURNS [REF ANY] --RedBlackTree.GetKey-- ~ {RETURN[data]}; SpacerCompare: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- ~ { s1: Spacer ~ NARROW[k]; s2: Spacer ~ NARROW[data]; RETURN Basics.CompareCard[s1.start, s2.start]}; CirioDebuggeeMonitoredCallProc: PROC[address: BreakWorldArchitecture.Address, proc: PROCEDURE [] RETURNS []] = BEGIN ENABLE { SPARCArchitecture.NullSPARCAddress => CCTypes.CCError[cirioError, "SPARCArchitecture.NullSPARCAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; BreakWorldArchitecture.WouldBlock => CCTypes.CCError[cirioError, IO.PutFR1["BreakWorldArchitecture.WouldBlock[%g]", [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; sparcAddress: SPARCArchitecture.SPARCAddress _ SPARCArchitecture.SPARCAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[sparcAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; CirioNubAccess.MonitoredCall[remoteAddress, proc]; END; MIPSCirioDebuggeeMonitoredCallProc: PROC[address: BreakWorldArchitecture.Address, proc: PROCEDURE [] RETURNS []] = BEGIN ENABLE { MIPSArchitecture.NullMIPSAddress => CCTypes.CCError[cirioError, "MIPSArchitecture.NullMIPSAddress"]; BreakWorldArchitecture.Cant => CCTypes.CCError[cirioError, IO.PutFR["BreakWorldArchitecture.Cant[%g, %g]", [atom[code]], [rope[message]] ]]; BreakWorldArchitecture.WouldBlock => CCTypes.CCError[cirioError, IO.PutFR1["BreakWorldArchitecture.WouldBlock[%g]", [rope[message]] ]]; }; breakWorld: BreakWorldArchitecture.BreakWorld _ BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address]; worldAccess: BreakWorldArchitecture.WorldAccess _ BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld]; breaks: CirioBreakSet _ NARROW[worldAccess.data]; mipsAddress: MIPSArchitecture.MIPSAddress _ MIPSArchitecture.MIPSAddressFromTargetAddress[address.address]; byteAddress: CARD32 _ LOOPHOLE[mipsAddress]; remoteAddress: CirioNubAccess.RemoteAddress _ [ breaks.nub, byteAddress, 0, FALSE, TRUE]; CirioNubAccess.MonitoredCall[remoteAddress, proc]; END; ModuleType: CARD = CirioNubAccess.ModuleType; TextType: CARD = CirioNubAccess.TextType; <> <> << >> <> <> <<>> <> FindNamedProcInNamedFile: PROC[nub: CirioNubAccess.Handle, fileStemName: Rope.ROPE, procName: Rope.ROPE] RETURNS[CARD, CARD] = BEGIN target: CirioTargets.Target _ NARROW[nub.target]; loaderName: Rope.ROPE _ target.CNameToLoaderName[target, procName]; lookUpName: Rope.ROPE _ Rope.Concat[loaderName, "_P"]; lookUpNameSize: CARD _ Rope.Length[lookUpName]; moduleEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupFileEntryByStemName[nub, fileStemName, 0]; fileEntry: CirioNubAccess.FileEntry; tocName: Rope.ROPE; tocEntry: CirioNubAccess.SymEntry; tocAddress: CARD; IF moduleEntry # NIL THEN BEGIN previousEntry: CirioNubAccess.SymEntry _ moduleEntry; <> fullName: Rope.ROPE _ Rope.Concat[loaderName, "_P60"]; entry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByName[nub, 0, fullName, FALSE, TextType, 0, 0]; IF entry # NIL THEN RETURN[entry.value, moduleEntry.value]; <> DO nextEntry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByValue[nub, previousEntry.symID, moduleEntry.value, TextType, 0, 1]; <> IF nextEntry = NIL THEN RETURN[0, 0]; -- no such proc in the file IF nextEntry.value >= moduleEntry.value + moduleEntry.size THEN RETURN[0, 0]; -- no such proc in the file IF Rope.Equal[Rope.Substr[nextEntry.name, 0, lookUpNameSize], lookUpName] THEN { fileEntry _ CirioNubAccess.GetFileEntry[nub, moduleEntry.fileSeqNum]; IF fileEntry = NIL THEN RETURN [0, 0]; tocName _ Rope.Substr[nextEntry.name, 1, Rope.Length[nextEntry.name] - 1]; tocEntry _ CirioNubAccess.LookupSymEntryByName[nub, tocName, FALSE, FALSE, 0]; IF tocEntry = NIL THEN RETURN[nextEntry.value, fileEntry.dataReloc]; tocAddress _ CirioNubAccess.RaFromCi[nub, tocEntry.value, 32].Read32BitsAsCard; RETURN[nextEntry.value, tocAddress]; }; <> previousEntry _ nextEntry; ENDLOOP; END ELSE -- we couldnt find the file, so look up the symbol blindly (for compatibility) BEGIN fullName: Rope.ROPE _ Rope.Concat[loaderName, "_P60"]; IF NOT Rope.Equal[procName, "CallDebugger"] THEN RETURN[0, 0] ELSE BEGIN entry: CirioNubAccess.SymEntry _ CirioNubAccess.LookupMatchingSymEntryByName[nub, 0, fullName, FALSE, TextType, 0, 0]; IF entry = NIL THEN RETURN[0, 0]; -- no such proc fileEntry _ CirioNubAccess.GetFileEntry[nub, entry.fileSeqNum]; IF fileEntry = NIL THEN RETURN [0, 0]; tocName _ Rope.Substr[entry.name, 1, Rope.Length[entry.name] - 1]; tocEntry _ CirioNubAccess.LookupSymEntryByName[nub, tocName, FALSE, FALSE, 0]; IF tocEntry = NIL THEN RETURN[entry.value, fileEntry.dataReloc]; tocAddress _ CirioNubAccess.RaFromCi[nub, tocEntry.value, 32].Read32BitsAsCard; RETURN[entry.value, tocAddress]; END; END; END; END.