Browse Source

* patch by Alfred Glänzer (manually "cherry picked"): Fix for internal error 200603061 on fixes, resolves #40758

  (cherry picked from commit ccb169b0f1b3214c6b09b3bd89492e2ce0626fa1)
florian 1 year ago
parent
commit
bff5cbd342
1 changed files with 47 additions and 20 deletions
  1. 47 20
      compiler/ogbase.pas

+ 47 - 20
compiler/ogbase.pas

@@ -2473,13 +2473,15 @@ implementation
           j      : longint;
           j      : longint;
           hs     : string;
           hs     : string;
           exesym : TExeSymbol;
           exesym : TExeSymbol;
+          tmpsym,
           objsym : TObjSymbol;
           objsym : TObjSymbol;
           grp    : TObjSectionGroup;
           grp    : TObjSectionGroup;
+          makeexternal : boolean;
         begin
         begin
           for j:=0 to ObjData.ObjSymbolList.Count-1 do
           for j:=0 to ObjData.ObjSymbolList.Count-1 do
             begin
             begin
               objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
               objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
-              { From the local symbols we are only interressed in the
+              { From the local symbols we are only interested in the
                 VTENTRY and VTINHERIT symbols }
                 VTENTRY and VTINHERIT symbols }
               if objsym.bind=AB_LOCAL then
               if objsym.bind=AB_LOCAL then
                 begin
                 begin
@@ -2532,25 +2534,20 @@ implementation
                 begin
                 begin
                   exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
                   exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
                   exesym.ObjSymbol:=objsym;
                   exesym.ObjSymbol:=objsym;
-                end;
-              objsym.ExeSymbol:=exesym;
-              case objsym.bind of
-                AB_GLOBAL :
-                  begin
-                    if exesym.State<>symstate_defined then
-                      begin
-                        exesym.ObjSymbol:=objsym;
-                        exesym.State:=symstate_defined;
-                      end
-                    else
+                end
+              else
+                begin
+                  if assigned(objsym.objsection) and assigned(exesym.objsymbol.objsection) then
+                    begin
                       if (oso_comdat in exesym.ObjSymbol.objsection.SecOptions) and
                       if (oso_comdat in exesym.ObjSymbol.objsection.SecOptions) and
                          (oso_comdat in objsym.objsection.SecOptions) then
                          (oso_comdat in objsym.objsection.SecOptions) then
                         begin
                         begin
                           if exesym.ObjSymbol.objsection.ComdatSelection=objsym.objsection.ComdatSelection then
                           if exesym.ObjSymbol.objsection.ComdatSelection=objsym.objsection.ComdatSelection then
                             begin
                             begin
+                              makeexternal:=true;
                               case objsym.objsection.ComdatSelection of
                               case objsym.objsection.ComdatSelection of
                                 oscs_none:
                                 oscs_none:
-                                  Message1(link_e_duplicate_symbol,objsym.name);
+                                  makeexternal:=false;
                                 oscs_any:
                                 oscs_any:
                                   Message1(link_d_comdat_discard_any,objsym.name);
                                   Message1(link_d_comdat_discard_any,objsym.name);
                                 oscs_same_size:
                                 oscs_same_size:
@@ -2565,22 +2562,52 @@ implementation
                                     Message1(link_d_comdat_discard_content,objsym.name);
                                     Message1(link_d_comdat_discard_content,objsym.name);
                                 oscs_associative:
                                 oscs_associative:
                                   { this is handled in a different way }
                                   { this is handled in a different way }
-                                  Message1(link_e_duplicate_symbol,objsym.name);
+                                  makeexternal:=false;
                                 oscs_largest:
                                 oscs_largest:
                                   if objsym.size>exesym.ObjSymbol.size then
                                   if objsym.size>exesym.ObjSymbol.size then
                                     begin
                                     begin
                                       Message1(link_d_comdat_replace_size,objsym.name);
                                       Message1(link_d_comdat_replace_size,objsym.name);
-                                      exesym.ObjSymbol.exesymbol:=nil;
-                                      exesym.ObjSymbol:=objsym;
+                                      { we swap the symbols and turn the smaller one to an external
+                                        symbol }
+                                      tmpsym:=exesym.objsymbol;
+                                      exesym.objsymbol:=objsym;
+                                      objsym.exesymbol:=exesym;
+                                      objsym:=tmpsym;
                                     end;
                                     end;
                               end;
                               end;
+                              if makeexternal then
+                                begin
+                                  { Undefine the symbol, causing relocations to it from same
+                                    objdata to be redirected to the symbol that is actually
+                                    used }
+                                  if objsym.bind=AB_GLOBAL then
+                                    objsym.bind:=AB_EXTERNAL;
+                                  { AB_WEAK_EXTERNAL remains unchanged }
+                                  objsym.objsection:=nil;
+                                end;
                             end
                             end
                           else
                           else
                             Message1(link_e_comdat_selection_differs,objsym.name);
                             Message1(link_e_comdat_selection_differs,objsym.name);
-                        end
-                      else
-                        { specific error if ComDat flags are different? }
-                        Message1(link_e_duplicate_symbol,objsym.name);
+                        end;
+                    end;
+                end;
+
+              objsym.ExeSymbol:=exesym;
+              case objsym.bind of
+                AB_GLOBAL,
+                AB_PRIVATE_EXTERN:
+                  begin
+                    if exesym.State<>symstate_defined then
+                      begin
+                        exesym.ObjSymbol:=objsym;
+                        exesym.State:=symstate_defined;
+                      end
+                    else
+                      Message1(link_e_duplicate_symbol,objsym.name);
+
+                    { hidden symbols must become local symbols in the executable }
+                    if objsym.bind=AB_PRIVATE_EXTERN then
+                      objsym.bind:=AB_LOCAL;
                   end;
                   end;
                 AB_EXTERNAL :
                 AB_EXTERNAL :
                   begin
                   begin