Browse Source

+ write the entry table to the NewExe file

git-svn-id: trunk@42628 -
nickysn 6 years ago
parent
commit
9f0f31a1e9
1 changed files with 118 additions and 2 deletions
  1. 118 2
      compiler/ogomf.pas

+ 118 - 2
compiler/ogomf.pas

@@ -584,10 +584,12 @@ interface
         FFlags: TNewExeEntryPointFlags;
         FSegment: Byte;
         FOffset: Word;
+        function GetFlagsByte: Byte;
       public
         property Flags: TNewExeEntryPointFlags read FFlags write FFlags;
         property Segment: Byte read FSegment write FSegment;
         property Offset: Word read FOffset write FOffset;
+        property FlagsByte: Byte read GetFlagsByte;
       end;
 
       { TNewExeEntryTable }
@@ -600,6 +602,8 @@ interface
         function GetItems(i: Integer): TNewExeEntryPoint;
         function GetSize: QWord;
         procedure SetItems(i: Integer; AValue: TNewExeEntryPoint);
+        function CanBeInSameBundle(i,j:Integer):Boolean;
+        function BundleSize(StartingElement:Integer): Byte;
       public
         destructor Destroy;override;
 
@@ -3982,14 +3986,47 @@ cleanup:
           end;
       end;
 
+{****************************************************************************
+                            TNewExeEntryPoint
+****************************************************************************}
+
+    function TNewExeEntryPoint.GetFlagsByte: Byte;
+      begin
+        Result:=0;
+        if neepfExported in Flags then
+          Result:=Result or 1;
+        if neepfSingleData in Flags then
+          Result:=Result or 2;
+      end;
+
 {****************************************************************************
                             TNewExeEntryTable
 ****************************************************************************}
 
     function TNewExeEntryTable.GetSize: QWord;
+      var
+        CurBundleStart, i: Integer;
+        CurBundleSize: Byte;
+        cp: TNewExeEntryPoint;
       begin
-        { todo: implement }
         Result:=0;
+        CurBundleStart:=1;
+        repeat
+          CurBundleSize:=BundleSize(CurBundleStart);
+          Inc(Result,2);
+          if CurBundleSize>0 then
+            begin
+              if Items[CurBundleStart]=nil then
+                { a bundle of null entries }
+              else if neepfMovableSegment in Items[CurBundleStart].Flags then
+                { a bundle of movable segment records }
+                Inc(Result,6*CurBundleSize)
+              else
+                { a bundle of fixed segment records }
+                Inc(Result,3*CurBundleSize);
+            end;
+          Inc(CurBundleStart,CurBundleSize);
+        until CurBundleSize=0;
       end;
 
     procedure TNewExeEntryTable.SetItems(i: Integer; AValue: TNewExeEntryPoint);
@@ -3999,6 +4036,30 @@ cleanup:
         FItems[i-1]:=AValue;
       end;
 
+    function TNewExeEntryTable.CanBeInSameBundle(i, j: Integer): Boolean;
+      begin
+        if (Items[i]=nil) or (Items[j]=nil) then
+          Result:=(Items[i]=nil) and (Items[j]=nil)
+        else if not (neepfMovableSegment in Items[i].Flags) and
+                not (neepfMovableSegment in Items[j].Flags) then
+          Result:=Items[i].Segment=Items[j].Segment
+        else
+          Result:=(neepfMovableSegment in Items[i].Flags)=
+                  (neepfMovableSegment in Items[j].Flags);
+      end;
+
+    function TNewExeEntryTable.BundleSize(StartingElement:Integer): Byte;
+      begin
+        if StartingElement>Count then
+          Result:=0
+        else
+          begin
+            Result:=1;
+            while (Result<255) and ((StartingElement+Result)<=Count) and CanBeInSameBundle(StartingElement,StartingElement+Result) do
+              Inc(Result);
+          end;
+      end;
+
     function TNewExeEntryTable.GetCount: Word;
       begin
         Result:=Length(FItems);
@@ -4021,8 +4082,63 @@ cleanup:
       end;
 
     procedure TNewExeEntryTable.WriteTo(aWriter: TObjectWriter);
+      var
+        CurBundleStart, i: Integer;
+        CurBundleSize: Byte;
+        buf: array [0..5] of Byte;
+        cp: TNewExeEntryPoint;
       begin
-        { todo: implement }
+        CurBundleStart:=1;
+        repeat
+          CurBundleSize:=BundleSize(CurBundleStart);
+          aWriter.write(CurBundleSize,1);
+          if CurBundleSize>0 then
+            begin
+              if Items[CurBundleStart]=nil then
+                begin
+                  { a bundle of null entries }
+                  buf[0]:=0;
+                  aWriter.write(buf[0],1);
+                end
+              else if neepfMovableSegment in Items[CurBundleStart].Flags then
+                begin
+                  { a bundle of movable segment records }
+                  buf[0]:=$ff;
+                  aWriter.write(buf[0],1);
+                  for i:=CurBundleStart to CurBundleStart+CurBundleSize-1 do
+                    begin
+                      cp:=Items[i];
+                      buf[0]:=cp.FlagsByte;
+                      buf[1]:=$CD;  { INT 3Fh instruction }
+                      buf[2]:=$3F;
+                      buf[3]:=Byte(cp.Segment);
+                      buf[4]:=Byte(cp.Offset);
+                      buf[5]:=Byte(cp.Offset shr 8);
+                      aWriter.write(buf[0],6);
+                    end;
+                end
+              else
+                begin
+                  { a bundle of fixed segment records }
+                  buf[0]:=Items[CurBundleStart].Segment;
+                  aWriter.write(buf[0],1);
+                  for i:=CurBundleStart to CurBundleStart+CurBundleSize-1 do
+                    begin
+                      cp:=Items[i];
+                      buf[0]:=cp.FlagsByte;
+                      buf[1]:=Byte(cp.Offset);
+                      buf[2]:=Byte(cp.Offset shr 8);
+                      aWriter.write(buf[0],3);
+                    end;
+                end;
+            end;
+          Inc(CurBundleStart,CurBundleSize);
+        until CurBundleSize=0;
+        { finish the end marker - a null bundle of 0 entries - must be 2 zero
+          bytes. The first one was already written by the loop, time to add the
+          second one. }
+        buf[0]:=0;
+        aWriter.write(buf[0],1);
       end;
 
     procedure TNewExeEntryTable.GrowTo(aNewCount: Word);