Importing Object Files |
Turbo Pascal can import and link object files created with any other compiler that can create Relocatable Object Module Format file.
OMF file is a collection of object records with the following format:
PObjectFileRecord = ^TObjectFileRecord; TObjectFileRecord = Record RecordType: Byte; RecordLength: Word; Case Byte of $88: (Comment: Record ComType: Byte; Class: Byte; Case Byte of $00: (Translator: String); $98: (SourceFileNumber: Byte; SourceFileName: String); end); $8C: (ExternalName: String); $90: (BaseGroupIndex, BaseSegmentIndex: Byte); $96: (Name: String); $98: (SegDef: TSegDef); $A0: (EnumSegmentIndex: Byte; EnumeratedDataOffset: Word; EnumData: Byte); $A2: (ItSegmentIndex: Byte; IteratedDataOffset: Word); end; Turbo Pascal loads object files and processes records - only few object file record types are supported: Procedure ImportObjectFiles; Var UsedFilesBlockRecord: PUsedFilesBlockRecord; ObjectFile: File; ObjectFileParagraphSize: Word; Procedure ReadObjectFile; Var ObjectFileSizeRec: LongRec; begin FindUsedFilePath (UsedFilesBlockRecord, @Identifier); OpenFile (ObjectFile, @Identifier); {$IFDEF DEBUGOMF} Writeln (' OBJECT FILE: ', PChar (@Identifier)); {$ENDIF} ObjectFileSizeRec.Long := FileSize (ObjectFile); If (ObjectFileSizeRec.WordH <> 0) or (ObjectFileSizeRec.WordL > $FFF0) then FileError (@Identifier, ObjectFileTooLarge); ObjectFileSize := ObjectFileSizeRec.WordL; ObjectFileParagraphSize := (ObjectFileSizeRec.WordL + $000F) shr 4; If HeapEndRec.Seg - ObjectFileParagraphSize < HeapPtrRec.Seg then Error (OutOfMemory); Dec (HeapEndRec.Seg, ObjectFileParagraphSize); ObjectFileSegment := HeapEndRec.Seg; BlockRead (ObjectFile, HeapEnd^, ObjectFileSizeRec.WordL); Close (ObjectFile); end; Procedure ProcessObjectFileRecords; Const LinkProc: Array [0..$11] of Procedure = ( OMF_Dummy, OMF_Dummy, OMF_Dummy, OMF_Dummy, OMF_COMENT, OMF_MODEND, OMF_EXTDEF, OMF_Dummy, OMF_PUBDEF, OMF_Dummy, OMF_LINNUM, OMF_Dummy, OMF_SEGDEF, OMF_Dummy, OMF_FIXUPP, OMF_Dummy, OMF_LEDATA, OMF_LIDATA); Var RecordType: Byte; begin SegmentCounter := 0; CodeSegmentIndex := 0; TypedConstantsSegmentIndex := 0; VariablesSegmentIndex := 0; ReferencesSymbolTable := stMain; LastSourceFileNumber := 0; SourceFileNumber := 0; ExtrnDefinitionsCounter := 0; OMF_ReferencedModule := AddReferencedModule (SymbolTable [stMain].Segment); ObjectFilePtr := Ptr (ObjectFileSegment, 0); Return := False; Repeat If Ofs (ObjectFilePtr^) >= ObjectFileSize then FileError (@Identifier, InvalidObjectFileRecord); RecordType := ObjectFilePtr^.RecordType; If Odd (RecordType) or (RecordType < $80) or (RecordType > $A2) then FileError (@Identifier, InvalidObjectFileRecord); ObjectRecordChecksumOffset := ObjectFilePtr^.RecordLength + Ofs (ObjectFilePtr^) + 2; LinkProc [(RecordType - $80) shr 1]; If Return then Exit; ObjectFilePtr := Ptr (ObjectFileSegment, ObjectRecordChecksumOffset + 1); until False; end; begin {$IFDEF DEBUGOMF} Writeln (#13#10'#OMF IMPORT BEGIN'); {$ENDIF} UsedFilesBlockRecord := Ptr (SymbolTable [stUsedFiles].Segment, 0); While Ofs (UsedFilesBlockRecord^) <> SymbolTable [stUsedFiles].UsedSize do begin If UsedFilesBlockRecord^.FileType = ufObjectFile then begin ReadObjectFile; ProcessObjectFileRecords; Inc (HeapEndRec.Seg, ObjectFileParagraphSize); CreateProgramCodeBlockRecord; CreateTypedConstantsBlockRecord; CreateVariablesBlockRecord; UsedFilesBlockRecord := Ptr (SymbolTable [stUsedFiles].Segment, Ofs (UsedFilesBlockRecord^)); end; Inc (PChar (UsedFilesBlockRecord), UsedFilesBlockRecord^.Name.Len + 8); end; {$IFDEF DEBUGOMF} Writeln ('#OMF IMPORT END'); {$ENDIF} end; |