DIRECTORY CirioTypes USING [BitAddr], IO USING [STREAM], PFSNames USING [PATH], Rope USING[ROPE], SystemInterface USING[CirioFile]; ObjectFiles: CEDAR DEFINITIONS = BEGIN ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; BitAddr: TYPE ~ CirioTypes.BitAddr; UnreadableObjectFile: ERROR[msg: ROPE]; Parsed: TYPE = REF ParsedBody; ParsedBody: TYPE; CreateParsed: PROC[f: SystemInterface.CirioFile, fs: ROPE _ NIL, targetData: REF ANY _ NIL] RETURNS[Parsed]; GetObjectFile: PROC[whole: Parsed] RETURNS[SystemInterface.CirioFile]; GetFormatString: PROC[whole: Parsed] RETURNS[Rope.ROPE]; Module: TYPE = REF ModuleBody; ModuleBody: TYPE; ModuleInfo: TYPE = RECORD[ whole: Parsed, fileName: PATH, instance: INT]; GetModule: PROC[info: ModuleInfo] RETURNS[Module]; GetModuleInfo: PROC[Module] RETURNS[REF ModuleInfo]; ModuleFromParsedAndPC: PROC [whole: Parsed, spc: FileSegmentPC, moduleRope: ROPE _ NIL] RETURNS [Module]; DescribeModule: PROC [Module] RETURNS [ROPE]; MemorySegmentId: TYPE ~ RECORD [segName: ROPE, segNum: INT]; FileSegmentId: TYPE ~ RECORD [fSegNum: INT, fSegName: ROPE]; noMSeg: MemorySegmentId = [NIL, 0]; noFSeg: FileSegmentId = [0, NIL]; SimpleSeg: TYPE ~ {text, data, bss}; simpleMSeg: READONLY ARRAY SimpleSeg OF MemorySegmentId; simpleFSeg: READONLY ARRAY SimpleSeg OF FileSegmentId; VarLoc: TYPE = REF VarLocBody; GlobalVarLoc: TYPE ~ REF fSegment VarLocBody; IndirectVarLoc: TYPE ~ REF indirect VarLocBody; VarLocCase: TYPE ~ {register, frame, frameExtension, fSegment, mSegment, namedCommon, indirect, unknown}; VarLocBody: TYPE = RECORD[ bitSize: CARD, where: SELECT case: VarLocCase FROM register => [regNum: CARD], frame => [bitOffset: INT], frameExtension => [bitOffset: INT], fSegment => [fSeg: FileSegmentId, bitOffset, fileByteOffset: CARD], mSegment => [mSeg: MemorySegmentId, bitOffset, fileByteOffset: CARD], namedCommon => [name: ROPE, bitOffset, absBase: CARD, absFound, absValid: BOOL], indirect => [base: VarLoc, offset: BitAddr], unknown => [why: ROPE], ENDCASE]; unspecdBitSize: CARD ~ CARD.LAST; LoadedVarLoc: TYPE ~ RECORD [VarLoc]; CGrammar: TYPE ~ {UNKNOWN, SunADotOut, XCOFF, SGIOBJ}; UnreadableDotO: ERROR[msg: Rope.ROPE]; RopeForStabType: PROC [type: StabType] RETURNS[Rope.ROPE]; CNameOfStab: PROC[stab: Stab] RETURNS[rope: Rope.ROPE]; CGrammarOfStab: PROC[stab: Stab] RETURNS[CGrammar]; VarLocFromStab: PUBLIC PROC [stab: Stab] RETURNS [VarLoc _ NIL]; MakeUnknownVarLoc: PROC [why: ROPE] RETURNS [VarLoc]; VersionStampInfo: TYPE = RECORD[ varLoc: GlobalVarLoc, contents: ROPE]; FindVersionStamp: PROC[whole: Module] RETURNS[REF VersionStampInfo]; FindGlobalFrameVar: PROC[whole: Module] RETURNS[GlobalVarLoc]; ReadInstruction: PROC[module: Module, spc: FileSegmentPC] RETURNS[inst: CARD]; GetSPOffset: PROC[module: Module, spc: FileSegmentPC] RETURNS[INT]; FunHandle: TYPE = REF FunHandleBody; FunHandleBody: TYPE; FunInfo: TYPE = RECORD[stab: Stab, cName: ROPE, pcs: PCRange]; GenFuns: PROC[module: Module, for: PROC[FunHandle] RETURNS[--stop-- BOOLEAN]]; GetFunInfo: PROC[fun: FunHandle] RETURNS[FunInfo]; GetFunBrackets: PROC[fun: FunHandle] RETURNS[BracketPair]; BracketPair: TYPE = REF BracketPairBody; BracketPairBody: TYPE; BracketNest: TYPE = LIST OF BracketPair; BracketPairKind: TYPE = {syntheticOuter, syntheticFun, actual, nil}; SymbolProc: TYPE = PROC[Stab] RETURNS[--stop-- BOOLEAN]; BracketProc: TYPE = PROC[BracketPair] RETURNS[--stop-- BOOLEAN]; PCRange: TYPE = RECORD[first, limit: CARD]; GenOtherSymbolStabs: PROC[module: Module, for: SymbolProc]; GenFunBracketPairs: PROC[module: Module, for: BracketProc]; GetOuterBracketPair: PROC[module: Module] RETURNS[BracketPair]; GetFunStab: PROC[bp: BracketPair] RETURNS[Stab]; GetFunHandle: PROC[bp: BracketPair] RETURNS[FunHandle]; GetFunHandleFromNest: PROC[nest: BracketNest] RETURNS[FunHandle]; GetBracketPairKind: PROC[bp: BracketPair] RETURNS[BracketPairKind]; GetPCRange: PROC[bp: BracketPair] RETURNS[PCRange]; GenSubBracketPairs: PROC[bp: BracketPair, for: BracketProc]; GenSymbolStabs: PROC[bp: BracketPair, for: SymbolProc]; GetBracketNestForPC: PROC[module: Module, spc: FileSegmentPC] RETURNS[BracketNest]; GetTypeRef: PROC[module: Module, sourceStream: IO.STREAM] RETURNS [Rope.ROPE]; FileSegmentPC: TYPE ~ RECORD [fSeg: FileSegmentId, relPC: CARD]; NoFileSegmentPC: FileSegmentPC = [fSeg: noFSeg, relPC: 0]; GetPCForLineNum: PROC[module: Module, cLineNum: CARD] RETURNS[FileSegmentPC]; GetLineNumForPC: PROC[module: Module, spc: FileSegmentPC] RETURNS[CARD]; Stab: TYPE = REF StabBody; StabBody: TYPE = RECORD[ module: Module, stabX: CARD, stabType: StabType _ Invalid, stabStorClass: StorageClass _ SCInvalid, size: CARD _ 0, --LAST[CARD], value: CARD32, rope: ROPE, index: CARD _ 0, extRef: BOOLEAN _ FALSE, fdIndex: INT32 _ 0 ]; StabType: TYPE ~ { Invalid, Unspecified, LBrac, RBrac, SLine, Fun, PSym, LSym, RSym, STSym, LCSym, GSym, Main, SO, BIncl, EIncl, Excl, SOL }; StorageClass: TYPE ~ { SCInvalid, SCNil, SCText, SCData, SCBss, SCRegister, SCAbs, SCUnspecified, SCBits, SCInfo, SCRegImage, SCUserStruct, SCSData, SCSBss, SCRData, SCCommon, SCSCommon, SCVerRegister, SCVariant, SCSUndefined }; NameAndNumber: TYPE = RECORD[name: ROPE, char: CHAR, number: INT, trailer: ROPE, valid: BOOLEAN]; ParseNameRope: PROC[stab: Stab] RETURNS[NameAndNumber]; RopeForBracketPair: PROC[bp: BracketPair] RETURNS[ROPE]; END.. h ObjectFiles.mesa Copyright Σ 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Adapted from DotOAccess Laurie Horton, June 19, 1992 10:56 am PDT Spreitzer, December 13, 1991 8:08 am PST Philip James, September 12, 1991 7:53 pm PDT Katsuyuki Komatsu December 23, 1992 5:05 pm PST Jas, January 5, 1993 10:46 am PST Useful shorthands Errors generally means that some sort of assumed invariant has failed Whole Object Files fs identifies the object file format. We leave it up to someone else to avoid creating more than one cookie for the same file. returns the file used for the objectFile returns the format specific string for the objectFile Modules A Module represents an element of a composite object file; the results of a single compilation. The fileName is as reported in the symbols. Thus, the directory part may no longer be relevent, because we copy files around. The extension, if any, what the source file actually had; if the symbols provide no reliable indication of extension, it doesn't show up here. When multiple Modules in a Parsed share the same base of fileName, instance distinguishes them. Returns NIL if can't find the info. Returns the module responsible for the given pc. Globalish variables A VarLoc represents where a variable is to be found. Relative to a FileEntry from the incremental loader. Relative to a Parsed. If the symbols don't specify a size, this field is unspecdBitSize. Maybe not all compilers produce these... Relative to a file segment in a Parsed; something in LoadStateAccess should be able to resolve this to a segment VarLoc. Relative to a memory segment in a FileEntry from the incremental loader. Represents a VarLoc that's in memory terms, not file terms. The fSegment variant is forbidden, and absValid must be TRUE. returns NIL if no version stamp found returns NIL if no global frame var the global frame var contains the global frame variables as embedded fields (At the time of this writing it is not recorded in a recognizable way in the mob, but rather is found by its name in the whole file.) Instructions Given PC is relative to the given file segment of the given Parsed. Given PC is relative to the given file segment of the given Parsed. Functions pcs are relative to the containing whole the returned bp will be a syntheticFun. Bracket Pairs A BracketPair represents a C-level scope. We create one synthetic bracket pair covering the entire module. Notice that a BracketPair contains the entire tree of brackets included in the pair. A BracketPair encloses a PC if the PC is greaterOrEqual to the PC of the LBrac, and less than the PC of the RBrac. A BracketNest defines a scope. It need not include an innermost pair of brackets. The first bracketPair in the nest is the one that covers the entire module, the last bracket pair is the innermost bracket pair of the list. Represents the pcs >= first and < limit. Generates all non-SLine stabs that occur outside the range of a Function definition. Enumerates the functions occurring in the whole. To be used by clients of GenFunBracketPairs to find the Fun stab for the functions. Returns NIL unless bp is the outer (synthetic) bracket pair for a function, in which case it returns the appropriate Fun stab. Returns NIL unless bp is the outer (synthetic) bracket pair for a function, in which case it returns the appropriate Fun stab. Generates the immediate descendents of bp. Generates the symbol stabs corresponding to bp. (For current Sun compilers, these symbol stabs occur BEFORE the LBrac of the pair.) These are the symbols belonging to the static name scope corresponding to bp. Thus, in order to see all symbol stabs (internal to a function) visible to a given bracket nest, call GenStabsForBracketPair on each BracketPair in the nest. Produces a BracketNest whose innermost bracket pair is the tightest bracket pair enclosing the given relative PC. The outermost bracket pair is the synthetic bracket pair covering the entire Module file. The relativePC is relative to the given file segment of the Parsed. The FunHandle for the enclosing function may be obtained by: nest: BracketNest _ GetBracketNestForPC[module, spc]; fun: FunHandle _ GetFunHandleFromNest[nest]; C Line-Number to Relative-PC maps The FileSegmentId is included because we have no guarantee of only one code segment per module. The relPC is relative to the Parsed. The FileSegmentId is included because we have no guarantee of only one code segment per module. The relPC is relative to the Parsed. Returned pc is relative to containing Parsed. Returns [noFseg, 0] if can't map. Returns 0 if can't map. Stabs Note: Each of our Stabs covers the set of DBX stabs that should be put together because they cover one string continued across several stabs; rope is the whole string. Note: if the stab.type = LBrac or RBrac, then stab.value will be corrected by adding an appropriate relocation to the raw value read from the file. Thus, the client need not worry about the fact that component whole files have not had their symbol table LBrac and RBrac entries properly relocated. Name ropes Variable names in the C file are described in [PCedar2.0]C2CNamingDoc.tioga. The format is . In addition, within a whole file this name is followed by a . The parsing routines return a NameAndNumber to represent all this information. name is the initial rope char is the optionalChar (blank if not present) number is number trailer is optionalTrailer (empty if not present) valid = TRUE only if the name was structured as described case is always blank. Printing An errorless way to describe a BracketPair. Κ Χ•NewlineDelimiter ™codešœ™K™HK™K™)K™(K™,K™/K™!—K˜šΟk ˜ Kšœ œ ˜Kšœœœ˜Kšœ œœ˜Kšœœœ˜Kšœœ ˜!—K˜KšΠbn œœ œ˜!Kš˜K˜™Kšœœœ˜Kšœœ œ˜Kšœ œ˜#—K˜™K™šΟnœœœ˜'K™>——K™™K™Kšœœœ ˜Kšœ œ˜K˜šŸ œœ#œœœœœœ ˜lKšΟeœ#™%KšœX™X—K™šŸ œœœ˜FK™(K™—šŸœœœœ˜8K™5——K™™K˜Kšœœœ ˜šœ œ˜Kšœ_™_—K˜šœ œœ˜K˜Kšœ œ˜Kšœ œ˜Kšœ œ‚™ŽKšœ9 œ œ™_—K˜KšŸ œœœ ˜2K˜šŸ œœ œœ ˜4K™#—K˜š Ÿœœ1œœœ ˜iK™0K˜—KšŸœœ œœ˜-—K˜™K˜Kšœ4™4K™š œœœ œ œ˜K™"™KK™…———K™™ K˜šŸœœ%œœ˜NKšœC™CK™—šŸ œœ%œœ˜CKšœC™C——K™™ K™Kšœ œœ˜$Kšœœ˜K˜šœ œœœ˜>K™(—K˜Kš Ÿœœœ œ‘œœ˜NK˜KšŸ œœœ ˜2K˜šŸœœœ˜:Kšœ'™'——K˜™ K™Kšœ œœ˜(šœœ˜KšœΑ™ΑK™r—K˜šœ œœœ ˜(Kšœΰ™ΰ—K˜Kšœœ/˜DK˜Kš œ œœœ‘œœ˜8Kš œ œœœ‘œœ˜@K˜šœ œœœ˜+Kšœ œ œ™(—K˜šŸœœ"˜;K™T—K™šŸœœ#˜;Kšœ0™0—K™KšŸœœœ˜?K˜šŸ œœœ˜0KšœS™SK™~—K™šŸ œœœ ˜7K™~K˜—KšŸœœœ ˜AK˜KšŸœœœ˜CK˜KšŸ œœœ ˜3K˜šŸœœ$˜