Kaynağa Gözat

+ add ability to generate Big Obj COFF files if required due to the section count being higher than $7fff
Note: such files can be linked GNU ld only starting from 2.25; then again the older versions would fail anyway as they'd complain about a too high section count...

git-svn-id: trunk@35380 -

svenbarth 8 yıl önce
ebeveyn
işleme
76445fd4b7
1 değiştirilmiş dosya ile 88 ekleme ve 27 silme
  1. 88 27
      compiler/ogcoff.pas

+ 88 - 27
compiler/ogcoff.pas

@@ -148,10 +148,11 @@ interface
        TCoffObjOutput = class(tObjOutput)
        private
          win32   : boolean;
+         bigobj  : boolean;
          symidx  : longint;
          FCoffSyms,
          FCoffStrs : tdynamicarray;
-         procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+         procedure write_symbol(const name:string;value:aword;section:longint;typ,aux:byte);
          procedure section_write_symbol(p:TObject;arg:pointer);
          procedure section_write_relocs(p:TObject;arg:pointer);
          procedure create_symbols(data:TObjData);
@@ -1236,32 +1237,59 @@ const pemagic : array[0..3] of byte = (
       end;
 
 
-    procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+    procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:longint;typ,aux:byte);
       var
         sym : coffsymbol;
+        bosym : coffbigobjsymbol;
+        strpos : longword;
       begin
-        FillChar(sym,sizeof(sym),0);
         { symbolname }
         if length(name)>8 then
           begin
-            sym.strpos:=FCoffStrs.size+4;
+            strpos:=FCoffStrs.size+4;
             FCoffStrs.writestr(name);
             FCoffStrs.writestr(#0);
           end
         else
-          move(name[1],sym.name,length(name));
-        sym.value:=value;
-        sym.section:=section;
-        sym.typ:=typ;
-        sym.aux:=aux;
-        inc(symidx);
-        FCoffSyms.write(sym,sizeof(sym));
+          strpos:=0;
+
+        if bigobj then
+          begin
+            fillchar(bosym,sizeof(bosym),0);
+            if length(name)>8 then
+              bosym.name.offset.offset:=strpos
+            else
+              move(name[1],bosym.name.shortname,length(name));
+            bosym.value:=value;
+            bosym.SectionNumber:=longword(section);
+            bosym.StorageClass:=typ;
+            bosym.NumberOfAuxSymbols:=aux;
+            inc(symidx);
+            FCoffSyms.write(bosym,sizeof(bosym));
+          end
+        else
+          begin
+            if section>$7fff then
+              internalerror(2017020302);
+            FillChar(sym,sizeof(sym),0);
+            if length(name)>8 then
+              sym.strpos:=strpos
+            else
+              move(name[1],sym.name,length(name));
+            sym.value:=value;
+            sym.section:=section;
+            sym.typ:=typ;
+            sym.aux:=aux;
+            inc(symidx);
+            FCoffSyms.write(sym,sizeof(sym));
+          end;
       end;
 
 
     procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
       var
         secrec : coffsectionrec;
+        padding : word;
       begin
         with TCoffObjSection(p) do
           begin
@@ -1283,6 +1311,11 @@ const pemagic : array[0..3] of byte = (
               secrec.nrelocs:=65535;
             inc(symidx);
             FCoffSyms.write(secrec,sizeof(secrec));
+            { aux recs have the same size as symbols, so we need to add two
+              Byte of padding in case of a Big Obj Coff }
+            padding:=0;
+            if bigobj then
+              FCoffSyms.write(padding,sizeof(padding));
           end;
       end;
 
@@ -1387,7 +1420,8 @@ const pemagic : array[0..3] of byte = (
 
     procedure TCoffObjOutput.create_symbols(data:TObjData);
       var
-        filename   : string[18];
+        filename   : string[20];
+        filenamelen : longint;
         sectionval : word;
         globalval  : byte;
         i          : longint;
@@ -1403,7 +1437,11 @@ const pemagic : array[0..3] of byte = (
            fillchar(filename,sizeof(filename),0);
            filename:=ExtractFileName(current_module.mainsource);
            inc(symidx);
-           FCoffSyms.write(filename[1],sizeof(filename)-1);
+           if bigobj then
+             filenamelen:=sizeof(coffbigobjsymbol)
+           else
+             filenamelen:=sizeof(coffsymbol);
+           FCoffSyms.write(filename[1],filenamelen);
            { Sections }
            secidx:=0;
            ObjSectionList.ForEachCall(@section_write_symbol,@secidx);
@@ -1511,17 +1549,24 @@ const pemagic : array[0..3] of byte = (
         sympos   : aword;
         i        : longint;
         header   : tcoffheader;
+        boheader : tcoffbigobjheader;
       begin
         result:=false;
         FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
         FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
         with TCoffObjData(data) do
          begin
+           bigobj:=(ObjSectionList.Count>$7fff) and win32;
+
            { Create Symbol Table }
            create_symbols(data);
 
            { Calculate the filepositions }
-           datapos:=sizeof(tcoffheader)+sizeof(tcoffsechdr)*ObjSectionList.Count;
+           if bigobj then
+             datapos:=sizeof(tcoffbigobjheader)
+           else
+             datapos:=sizeof(tcoffheader);
+           datapos:=datapos+sizeof(tcoffsechdr)*ObjSectionList.Count;
            { Sections first }
            layoutsections(datapos);
            { relocs }
@@ -1531,23 +1576,39 @@ const pemagic : array[0..3] of byte = (
            sympos:=datapos;
 
            { Generate COFF header }
-           fillchar(header,sizeof(tcoffheader),0);
-           header.mach:=COFF_MAGIC;
-           header.nsects:=ObjSectionList.Count;
-           header.sympos:=sympos;
-           header.syms:=symidx;
-           if win32 then
+           if bigobj then
+             begin
+               fillchar(boheader,sizeof(boheader),0);
+               boheader.Sig1:=0;
+               boheader.Sig2:=$ffff;
+               boheader.Machine:=COFF_MAGIC;
+               boheader.Version:=COFF_BIG_OBJ_VERSION;
+               boheader.NumberOfSections:=longword(ObjSectionList.Count);
+               boheader.NumberOfSymbols:=longword(symidx);
+               boheader.PointerToSymbolTable:=sympos;
+               Move(COFF_BIG_OBJ_MAGIC,boheader.UUID,length(boheader.UUID));
+               FWriter.write(boheader,sizeof(boheader));
+             end
+           else
              begin
+               fillchar(header,sizeof(tcoffheader),0);
+               header.mach:=COFF_MAGIC;
+               header.nsects:=ObjSectionList.Count;
+               header.sympos:=sympos;
+               header.syms:=symidx;
+               if win32 then
+                 begin
 {$ifndef x86_64}
-               header.flag:=PE_FILE_32BIT_MACHINE or
-                            PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
+                   header.flag:=PE_FILE_32BIT_MACHINE or
+                                PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
 {$else x86_64}
-               header.flag:=PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
+                   header.flag:=PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
 {$endif x86_64}
-             end
-           else
-             header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
-           FWriter.write(header,sizeof(header));
+                 end
+               else
+                 header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
+               FWriter.write(header,sizeof(header));
+             end;
            { Section headers }
            ObjSectionList.ForEachCall(@section_write_header,nil);
            { ObjSections }