* correctly handle PE COMDAT sections: like for the Comdat groups in ELF files the unused symbols need to be converted to externals so that relocations are handled correctly

git-svn-id: trunk@43359 -
This commit is contained in:
svenbarth 2019-11-02 12:36:30 +00:00
parent c6a08cdc6e
commit ccb169b0f1

View File

@ -2548,8 +2548,10 @@ implementation
j : longint;
hs : string;
exesym : TExeSymbol;
tmpsym,
objsym : TObjSymbol;
grp : TObjSectionGroup;
makeexternal : boolean;
begin
for j:=0 to ObjData.ObjSymbolList.Count-1 do
begin
@ -2607,26 +2609,20 @@ implementation
begin
exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
exesym.ObjSymbol:=objsym;
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
end
else
begin
if assigned(objsym.objsection) and assigned(exesym.objsymbol.objsection) then
begin
if (oso_comdat in exesym.ObjSymbol.objsection.SecOptions) and
(oso_comdat in objsym.objsection.SecOptions) then
begin
if exesym.ObjSymbol.objsection.ComdatSelection=objsym.objsection.ComdatSelection then
begin
makeexternal:=true;
case objsym.objsection.ComdatSelection of
oscs_none:
Message1(link_e_duplicate_symbol,objsym.name);
makeexternal:=false;
oscs_any:
Message1(link_d_comdat_discard_any,objsym.name);
oscs_same_size:
@ -2641,22 +2637,48 @@ implementation
Message1(link_d_comdat_discard_content,objsym.name);
oscs_associative:
{ this is handled in a different way }
Message1(link_e_duplicate_symbol,objsym.name);
makeexternal:=false;
oscs_largest:
if objsym.size>exesym.ObjSymbol.size then
begin
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;
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
else
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