DIRECTORY Basics USING [ShortNumber, LongNumber], MoberyPrivate, IO, Rope, UXStrings, UnixTypes; MoberyObjectFileImpl: CEDAR PROGRAM IMPORTS IO, MoberyPrivate, Rope, UXStrings ~ BEGIN ROPE: TYPE = Rope.ROPE; aoutHeaderBytes: INT = 4+4*7; -- size of header for a.out .o files aoutTextSizeOffset: INT = 4; -- byte offset of text size field in a.out .o files aoutMagicOffset: INT = 2; -- byte offset of magic number in a.out .o files xcoffMagicOffset: INT = 0; -- byte offset of magic number in xcoff files xcoffHeaderBytes: INT = 4+4*3+4; -- size of header for xcoff filehdr xcoffOptionalHdrSizeOffset: INT = 16; -- offset of optional header (aouthdr) size in filehdr xcoffScnHdrSectionNameOffset: INT = 0; -- byte offset of section name field within xcoff scn xcoffScnHdrSectionStartOffset: INT = 8; -- byte offset of section start offset within xcoff scn xcoffScnHdrSize: INT = 40; -- size of xcoff section header xcoffScnNameLen: INT = 8; -- size of xcoff section name xcoffDataSectionName: ROPE = ".data"; ReadBinaryShort: PROC [s: IO.STREAM] RETURNS [INT16] ~ { sn: Basics.ShortNumber _ [si[0]]; sn.hi _ IO.GetByte[s]; sn.lo _ IO.GetByte[s]; RETURN [sn.sc]; }; ReadBinaryINT: PROC [stream: IO.STREAM] RETURNS [INT] ~ { ln: Basics.LongNumber _ [li[0]]; ln.hh _ IO.GetByte[stream]; ln.hl _ IO.GetByte[stream]; ln.lh _ IO.GetByte[stream]; ln.ll _ IO.GetByte[stream]; RETURN [ln.li] }; ReadBinaryUINT: PROC [stream: IO.STREAM] RETURNS [CARD] ~ { ln: Basics.LongNumber _ [lc[0]]; ln.hh _ IO.GetByte[stream]; ln.hl _ IO.GetByte[stream]; ln.lh _ IO.GetByte[stream]; ln.ll _ IO.GetByte[stream]; RETURN [ln.lc] }; MoberyXCoffTester: MoberyPrivate.ObjectFileTypeMatcherProc ~ { magicNumber, numOfSections, optHdrLength: INT; isXCoff: PROC[num: INT] RETURNS [BOOLEAN] = INLINE { RETURN [num = 0730B OR num = 0735B OR num = 0737B OR num = 6201H OR num = 0160H]; }; readSectionName: PROC [s: IO.STREAM] RETURNS [REF TEXT] ~ { b: REF TEXT = NEW[TEXT[xcoffScnNameLen]]; [] _ IO.GetBlock[self: s, block: b, count: xcoffScnNameLen]; RETURN [b]; }; IF NOT stream.EndOf[] THEN { IO.SetIndex[self: stream, index: xcoffMagicOffset]; magicNumber _ ReadBinaryShort[stream]; IF isXCoff[magicNumber] THEN { matches _ TRUE; numOfSections _ ReadBinaryShort[stream]; -- read number of sections IO.SetIndex[self: stream, index: xcoffOptionalHdrSizeOffset]; optHdrLength _ ReadBinaryShort[stream]; -- get length of optional header (a.out) IO.SetIndex[stream, IO.GetIndex[self: stream] - 2 + optHdrLength + (xcoffHeaderBytes - xcoffOptionalHdrSizeOffset)]; WHILE (numOfSections > 0) DO scnName: REF TEXT; scnName _ readSectionName[stream]; IF Rope.EqualSubstrs[s1: xcoffDataSectionName, len1: xcoffDataSectionName.Length[], s2: Rope.FromRefText[s: scnName], len2: xcoffDataSectionName.Length[]] THEN { size: CARD; [] _ ReadBinaryUINT[stream]; -- skip physical address field [] _ ReadBinaryUINT[stream]; -- skip virtual address field size _ ReadBinaryUINT[stream]; start _ ReadBinaryUINT[stream]; end _ start + size; EXIT; }; numOfSections _ numOfSections - 1; IO.SetIndex[stream, IO.GetIndex[stream] - xcoffScnNameLen + xcoffScnHdrSize]; -- advance to next section header ENDLOOP; IF (numOfSections <= 0) OR (NOT start IN [0..end) AND end <= IO.GetLength[stream]) THEN { start _ 0; end _ IO.GetLength[stream]; }; }; }; }; MoberyADotOutTester: MoberyPrivate.ObjectFileTypeMatcherProc ~ { magicNumber: INT; isADotOut: PROC[num: INT] RETURNS [BOOLEAN] = INLINE { RETURN [num = 0407B OR num = 0410B OR num = 0413B]; }; IO.SetIndex[self: stream, index: aoutMagicOffset]; IF NOT stream.EndOf[] THEN { magicNumber _ ReadBinaryShort[stream]; IF isADotOut[magicNumber] THEN { matches _ TRUE; IO.SetIndex[self: stream, index: aoutTextSizeOffset]; start _ aoutHeaderBytes + ReadBinaryINT[stream]; end _ start + ReadBinaryINT[stream]; IF NOT start IN [0..end) AND end <= IO.GetLength[stream] THEN { start _ 0; end _ IO.GetLength[stream]; }; }; }; }; MoberyPrivate.RegisterObjectFileType[MoberyADotOutTester]; MoberyPrivate.RegisterObjectFileType[MoberyXCoffTester]; END. – MoberyObjectFileImpl.mesa Mna, May 3, 1992 4:27 pm PDT IO USING [EndOf, GetBlock, GetByte, GetIndex, GetLength, SetIndex, STREAM], a.out portions of this file created from MoberyImpl.mesa. a.out know-how (thanks to Michael Plass) XCOFF know-how (thanks to IBM documentation) This routine handles both XCOFF (AIX) and ECOFF (DEC/MIPS/SGI) as the differences in the object file formats between ECOFF and XCOFF are not large enough to affect the stamp-finding algorithm. PROC[stream: IO.STREAM] RETURNS [matches: BOOLEAN _ FALSE, start, end: CARD] isXCoff also checks if the binary is a valid dec ECOFF executable. an object file. seek to section headers at end of optional a.out header find data section section and determine where to search for stamps confusion! search whole file. PROC[stream: IO.STREAM] RETURNS [matches: BOOLEAN _ FALSE, start, end: CARD] an object file. confusion! search whole file. Κ”•NewlineDelimiter – "cedar" style™™J™—J™codešΟk ˜ Kšœœ˜'Kšœ˜Kšœœ;œ™KKšœ˜K˜K˜—K˜KšΠbnœœ˜#Kšœœ ˜*šœ˜K˜Kšœœœ˜K˜K™9K™Kšœ)™)K˜Kšœœ Οc$˜BKšœœŸ3˜PKšœœŸ0˜JK˜Kšœ,™,K˜KšœœŸ-˜HKšœœ Ÿ#˜DKšœœŸ6˜\KšœœŸ5˜\KšœœŸ7˜_KšœœŸ˜:KšœœŸ˜7Kšœœ ˜%K˜š žœœœœœœ˜8Kšœ!˜!Kšœœ ˜Kšœœ ˜Kšœ ˜K˜—K˜š Οn œœ œœœœ˜9K˜ Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜K˜—K˜š  œœ œœœœ˜;K˜ Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜K˜—˜K˜—K™ΑK˜šžœ-˜>KšœL™LKšœ*œ˜.K˜š Οbœœœœœœ˜4K™DKš œœ œ œ œ˜QK˜—š‘œœœœœœœ˜;Kš œœœœœ˜)Kšœœ5˜