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