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;