{ Copyright (c) 2015 by Nikolay Nikolov Contains the binary Relocatable Object Module Format (OMF) reader and writer This is the object format used on the i8086-msdos platform. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit ogomf; {$i fpcdefs.inc} interface uses { common } cclasses,globtype, { target } systems, { assembler } cpuinfo,cpubase,aasmbase,assemble,link, { OMF definitions } omfbase, { output } ogbase, owbase; type TOmfObjData = class(TObjData) public function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override; procedure writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override; end; { TOmfObjOutput } TOmfObjOutput = class(tObjOutput) private FLNames: TOmfOrderedNameCollection; FSegments: TFPHashObjectList; FGroups: TFPHashObjectList; procedure AddSegment(const name,segclass: string; Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination; Use: TOmfSegmentUse); property LNames: TOmfOrderedNameCollection read FLNames; property Segments: TFPHashObjectList read FSegments; property Groups: TFPHashObjectList read FGroups; protected function writeData(Data:TObjData):boolean;override; public constructor create(AWriter:TObjectWriter);override; destructor Destroy;override; end; TOmfAssembler = class(tinternalassembler) constructor create(smart:boolean);override; end; implementation uses SysUtils, cutils,verbose,globals, fmodule,aasmtai,aasmdata, ogmap, version ; {**************************************************************************** TOmfObjData ****************************************************************************} function TOmfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string; begin result:=aname; end; procedure TOmfObjData.writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType); begin end; {**************************************************************************** TOmfObjOutput ****************************************************************************} procedure TOmfObjOutput.AddSegment(const name, segclass: string; Alignment: TOmfSegmentAlignment; Combination: TOmfSegmentCombination; Use: TOmfSegmentUse); var s: TOmfRecord_SEGDEF; begin s:=TOmfRecord_SEGDEF.Create; Segments.Add(name,s); s.SegmentNameIndex:=LNames.Add(name); s.ClassNameIndex:=LNames.Add(segclass); s.OverlayNameIndex:=1; s.Alignment:=Alignment; s.Combination:=Combination; s.Use:=Use; end; function TOmfObjOutput.writeData(Data:TObjData):boolean; var RawRecord: TOmfRawRecord; Header: TOmfRecord_THEADR; Translator_COMENT: TOmfRecord_COMENT; LNamesRec: TOmfRecord_LNAMES; I: Integer; SegDef: TOmfRecord_SEGDEF; GrpDef: TOmfRecord_GRPDEF; SegList: TSegmentList; begin { write header record } RawRecord:=TOmfRawRecord.Create; Header:=TOmfRecord_THEADR.Create; Header.ModuleName:=Data.Name; Header.EncodeTo(RawRecord); RawRecord.WriteTo(FWriter); Header.Free; { write translator COMENT header } Translator_COMENT:=TOmfRecord_COMENT.Create; Translator_COMENT.CommentClass:=CC_Translator; Translator_COMENT.CommentString:='FPC '+full_version_string+ ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname; Translator_COMENT.EncodeTo(RawRecord); RawRecord.WriteTo(FWriter); Translator_COMENT.Free; LNames.Clear; LNames.Add(''); { insert an empty string, which has index 1 } if not (cs_huge_code in current_settings.moduleswitches) then AddSegment({CodeSectionName(current_module.modulename^)}'text','code',saRelocatableByteAligned,scPublic,suUse16); AddSegment('rodata','data',saRelocatableByteAligned,scPublic,suUse16); AddSegment('data','data',saRelocatableWordAligned,scPublic,suUse16); AddSegment('fpc','data',saRelocatableByteAligned,scPublic,suUse16); AddSegment('bss','bss',saRelocatableByteAligned,scPublic,suUse16); AddSegment('stack','stack',saRelocatableParaAligned,scStack,suUse16); AddSegment('heap','heap',saRelocatableParaAligned,scPublic,suUse16); GrpDef:=TOmfRecord_GRPDEF.Create; Groups.Add('dgroup',GrpDef); GrpDef.GroupNameIndex:=LNames.Add('dgroup'); if current_settings.x86memorymodel=mm_tiny then begin //AsmWriteLn('GROUP dgroup text rodata data fpc bss heap') SetLength(SegList,6); SegList[0]:=Segments.FindIndexOf('text'); SegList[1]:=Segments.FindIndexOf('rodata'); SegList[2]:=Segments.FindIndexOf('data'); SegList[3]:=Segments.FindIndexOf('fpc'); SegList[4]:=Segments.FindIndexOf('bss'); SegList[5]:=Segments.FindIndexOf('heap'); end else if current_settings.x86memorymodel in x86_near_data_models then begin //AsmWriteLn('GROUP dgroup rodata data fpc bss stack heap') SetLength(SegList,6); SegList[0]:=Segments.FindIndexOf('rodata'); SegList[1]:=Segments.FindIndexOf('data'); SegList[2]:=Segments.FindIndexOf('fpc'); SegList[3]:=Segments.FindIndexOf('bss'); SegList[4]:=Segments.FindIndexOf('stack'); SegList[5]:=Segments.FindIndexOf('heap'); end else begin //AsmWriteLn('GROUP dgroup rodata data fpc bss'); SetLength(SegList,4); SegList[0]:=Segments.FindIndexOf('rodata'); SegList[1]:=Segments.FindIndexOf('data'); SegList[2]:=Segments.FindIndexOf('fpc'); SegList[3]:=Segments.FindIndexOf('bss'); end; GrpDef.SegmentList:=SegList; { write LNAMES record(s) } LNamesRec:=TOmfRecord_LNAMES.Create; LNamesRec.Names:=LNames; while LNamesRec.NextIndex<=LNames.Count do begin LNamesRec.EncodeTo(RawRecord); RawRecord.WriteTo(FWriter); end; LNamesRec.Free; { write SEGDEF record(s) } for I:=1 to Segments.Count-1 do begin SegDef:=TOmfRecord_SEGDEF(Segments[I]); SegDef.EncodeTo(RawRecord); RawRecord.WriteTo(FWriter); end; { write GRPDEF record(s) } for I:=1 to Groups.Count-1 do begin GrpDef:=TOmfRecord_GRPDEF(Groups[I]); GrpDef.EncodeTo(RawRecord); RawRecord.WriteTo(FWriter); end; RawRecord.Free; result:=true; end; constructor TOmfObjOutput.create(AWriter:TObjectWriter); begin inherited create(AWriter); cobjdata:=TOmfObjData; FLNames:=TOmfOrderedNameCollection.Create; FSegments:=TFPHashObjectList.Create; FSegments.Add('',nil); FGroups:=TFPHashObjectList.Create; FGroups.Add('',nil); end; destructor TOmfObjOutput.Destroy; begin FGroups.Free; FSegments.Free; FLNames.Free; inherited Destroy; end; {**************************************************************************** TOmfAssembler ****************************************************************************} constructor TOmfAssembler.Create(smart:boolean); begin inherited Create(smart); CObjOutput:=TOmfObjOutput; end; {***************************************************************************** Initialize *****************************************************************************} {$ifdef i8086} const as_i8086_omf_info : tasminfo = ( id : as_i8086_omf; idtxt : 'OMF'; asmbin : ''; asmcmd : ''; supported_targets : [system_i8086_msdos]; flags : [af_outputbinary,af_needar,af_no_debug]; labelprefix : '..@'; comment : '; '; dollarsign: '$'; ); {$endif i8086} initialization {$ifdef i8086} RegisterAssembler(as_i8086_omf_info,TOmfAssembler); {$endif i8086} end.