Press enter to see results or esc to cancel.

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;