+ correctly handle COMDAT sections in COFF files (at least as long as the COMDAT selection isn't IMAGE_COMDAT_SELECT_ASSOCIATIVE or IMAGE_COMDAT_SELECT_EXACT_MATCH), fixes the .refptr problems mentioned in Mantis #30614

git-svn-id: trunk@36197 -
This commit is contained in:
svenbarth 2017-05-12 15:57:31 +00:00
parent b74b3b0047
commit e9c40f5b24
5 changed files with 491 additions and 314 deletions

View File

@ -2986,7 +2986,7 @@ execinfo_x_stackcommit=09134_X_Stack space committed: $1 bytes
#
# Internal linker messages
#
# 09208 is the last used one
# 09220 is the last used one
#
# BeginOfTeX
% \section{Linker messages}
@ -3016,6 +3016,36 @@ link_e_com_program_uses_segment_relocations=09207_E_Cannot create a .COM file, b
% directive (either in pascal's built-in inline assembler, or in an externally
% linked assembly module).
link_w_program_uses_checkpointer=09208_W_Program "$1" uses experimental CheckPointer option
link_e_duplicate_symbol=09209_E_Multiple defined symbol "$1"
% The specified symbol is already defined inside the whole collection of object files.
link_e_comdat_select_unsupported=09210_E_COMDAT selection mode $1 not supported (section: "$1")
% The specified COMDAT selection mode is not supported.
link_e_comdat_associative_section_expected=09211_E_Associative section expected for COMDAT section "$1"
% The specified COMDAT section is specified as expecting an associative section,
% but none is specified.
link_e_comdat_not_matching=09212_E_COMDAT section selection mode doesn't match for section "$1" and symbol "$2"
% All COMDAT symbols/sections need to use the same selection mode.
link_e_comdat_associative_section_not_found=09213_E_Associative COMDAT section for section "$1" not found
% The COMDAT section expects an associative section, but it was not found inside the object file.
link_d_comdat_discard_any=09214_D_Discarding duplicate symbol "$1" due to COMDAT selection mode
% The COMDAT section specifies that any section with the same name might be selected and this
% specific section was selected to be discarded.
link_d_comdat_discard_size=09215_D_Discarding duplicate symbol "$1" with same size due to COMDAT selection mode
% The COMDAT section specifies that any section with the same name and size might be selected
% and this specific section was selected to be discarded.
link_d_comdat_discard_content=09216_D_Discarding duplicate symbol "$1" with same content due to COMDAT selection mode
% The COMDAT section specifies that any section with the same name and content might be selected
% and this specific section was selected to be discarded.
link_d_comdat_replace_size=09217_D_Replacing duplicate symbol "$1" with smaller size due to COMDAT selection mode
% The COMDAT section specifies that the largest section with the same name should be selected
% this specific section was larger than the previous largest one.
link_e_comdat_size_differs=09218_E_Size of duplicate COMDAT symbol "$1" differs
% The COMDAT section specifies that all sections with the same name need to have the same size,
% but this section had a different size.
link_e_comdat_content_differs=09219_E_Content of duplicate COMDAT symbol "$1" differs
% The COMDAT section specifies that all sections with the same name need to have the same content,
% but this section had a different size.
link_e_comdat_selection_differs=09220_E_COMDAT selection mode for symbol "$1" differs
%\end{description}
# EndOfTeX

View File

@ -895,6 +895,18 @@ const
link_e_group_too_large=09206;
link_e_com_program_uses_segment_relocations=09207;
link_w_program_uses_checkpointer=09208;
link_e_duplicate_symbol=09209;
link_e_comdat_select_unsupported=09210;
link_e_comdat_associative_section_expected=09211;
link_e_comdat_not_matching=09212;
link_e_comdat_associative_section_not_found=09213;
link_d_comdat_discard_any=09214;
link_d_comdat_discard_size=09215;
link_d_comdat_discard_content=09216;
link_d_comdat_replace_size=09217;
link_e_comdat_size_differs=09218;
link_e_comdat_content_differs=09219;
link_e_comdat_selection_differs=09220;
unit_t_unitsearch=10000;
unit_t_ppu_loading=10001;
unit_u_ppu_name=10002;
@ -1068,9 +1080,9 @@ const
option_info=11024;
option_help_pages=11025;
MsgTxtSize = 79313;
MsgTxtSize = 80114;
MsgIdxMax : array[1..20] of longint=(
27,102,347,124,96,58,132,33,209,67,
27,102,347,124,96,58,132,33,221,67,
60,20,30,1,1,1,1,1,1,1
);

File diff suppressed because it is too large Load Diff

View File

@ -174,11 +174,28 @@ interface
{ Has relocations with explicit addends (ELF-specific) }
oso_rela_relocs,
{ Supports bss-like allocation of data, even though it is written in file (i.e. also has oso_Data) }
oso_sparse_data
oso_sparse_data,
{ Section to support the resolution of multiple symbols with the same name }
oso_comdat
);
TObjSectionOptions = set of TObjSectionOption;
TObjSectionComdatSelection = (
{ Section is not a COMDAT section }
oscs_none,
{ Select any of the symbols }
oscs_any,
{ Select any symbol, but abort if they differ in size }
oscs_same_size,
{ Select any symbol, but abort if they differ in size or content }
oscs_exact_match,
{ Select the symbol only if the associated symbol is linked as well }
oscs_associative,
{ Select the largest symbol }
oscs_largest
);
TObjSectionGroup = class;
TObjSymbol = class(TFPHashObject)
@ -250,6 +267,7 @@ interface
private
FData : TDynamicArray;
FSecOptions : TObjSectionOptions;
FComdatSelection : TObjSectionComdatSelection;
FCachedFullName : pshortstring;
procedure SetSecOptions(Aoptions:TObjSectionOptions);
procedure SectionTooLargeError;
@ -263,6 +281,8 @@ interface
DataPos : PUInt;
MemPos : qword;
Group : TObjSectionGroup;
AssociativeSection : TObjSection;
ComdatSelection : TObjSectionComdatSelection;
DataAlignBytes : shortint;
{ Relocations (=references) to other sections }
ObjRelocations : TFPObjectList;
@ -2493,7 +2513,44 @@ implementation
exesym.State:=symstate_defined;
end
else
Comment(V_Error,'Multiple defined symbol '+objsym.name);
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
case objsym.objsection.ComdatSelection of
oscs_none:
Message1(link_e_duplicate_symbol,objsym.name);
oscs_any:
Message1(link_d_comdat_discard_any,objsym.name);
oscs_same_size:
if exesym.ObjSymbol.size<>objsym.size then
Message1(link_e_comdat_size_differs,objsym.name)
else
Message1(link_d_comdat_discard_size,objsym.name);
oscs_exact_match:
if (exesym.ObjSymbol.size<>objsym.size) and not exesym.ObjSymbol.objsection.Data.equal(objsym.objsection.Data) then
Message1(link_e_comdat_content_differs,objsym.name)
else
Message1(link_d_comdat_discard_content,objsym.name);
oscs_associative:
{ this is handled in a different way }
Message1(link_e_duplicate_symbol,objsym.name);
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;
end;
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;
AB_EXTERNAL :
begin

View File

@ -490,6 +490,7 @@ implementation
select : byte;
empty : array[0..2] of char;
end;
pcoffsectionrec=^coffsectionrec;
coffreloc=packed record
address : longword;
sym : longword;
@ -820,6 +821,8 @@ const pemagic : array[0..3] of byte = (
include(aoptions,oso_data);
if (flags and (PE_SCN_LNK_REMOVE or PE_SCN_MEM_DISCARDABLE)=0) then
include(aoptions,oso_load);
if flags and PE_SCN_LNK_COMDAT<>0 then
include(aoptions,oso_comdat);
{ read/write }
if flags and PE_SCN_MEM_WRITE<>0 then
include(aoptions,oso_write);
@ -1800,11 +1803,13 @@ const pemagic : array[0..3] of byte = (
strname : string;
auxrec : array[0..sizeof(coffsymbol)-1] of byte;
boauxrec : array[0..sizeof(coffbigobjsymbol)-1] of byte;
secrec : pcoffsectionrec;
objsec : TObjSection;
secidx : longint;
symvalue : longword;
auxcount : byte;
symcls : byte;
comdatsel : TObjSectionComdatSelection;
{ keeps string manipulations out of main routine }
procedure UnsupportedSymbolType;
@ -1935,6 +1940,63 @@ const pemagic : array[0..3] of byte = (
end;
FSymTbl^[symidx]:=objsym;
{ read aux records }
{ handle COMDAT symbols }
if (symcls=COFF_SYM_LOCAL) and (auxcount=1) and (symvalue=0) and (oso_comdat in objsym.objsection.SecOptions) then
begin
if bigobj then
begin
FCoffSyms.Read(boauxrec,sizeof(boauxrec));
secrec:=pcoffsectionrec(@boauxrec[0]);
end
else
begin
FCoffSyms.Read(auxrec,sizeof(auxrec));
secrec:=pcoffsectionrec(@auxrec);
end;
case secrec^.select of
IMAGE_COMDAT_SELECT_NODUPLICATES:
comdatsel:=oscs_none;
IMAGE_COMDAT_SELECT_ANY:
comdatsel:=oscs_any;
IMAGE_COMDAT_SELECT_SAME_SIZE:
comdatsel:=oscs_same_size;
IMAGE_COMDAT_SELECT_EXACT_MATCH:
comdatsel:=oscs_exact_match;
IMAGE_COMDAT_SELECT_ASSOCIATIVE:
comdatsel:=oscs_associative;
IMAGE_COMDAT_SELECT_LARGEST:
comdatsel:=oscs_largest;
else begin
comdatsel:=oscs_none;
Message2(link_e_comdat_select_unsupported,inttostr(secrec^.select),objsym.objsection.name);
end;
end;
if comdatsel in [oscs_associative,oscs_exact_match] then
{ only temporary }
Comment(V_Error,'Associative or exact match COMDAT sections are not yet supported (symbol: '+objsym.objsection.Name+')')
else if (comdatsel=oscs_associative) and (secrec^.assoc=0) then
Message1(link_e_comdat_associative_section_expected,objsym.objsection.name)
else if (objsym.objsection.ComdatSelection<>oscs_none) and (comdatsel<>oscs_none) and (objsym.objsection.ComdatSelection<>comdatsel) then
Message2(link_e_comdat_not_matching,objsym.objsection.Name,objsym.Name)
else
begin
objsym.objsection.ComdatSelection:=comdatsel;
if (secrec^.assoc<>0) and not assigned(objsym.objsection.AssociativeSection) then
begin
objsym.objsection.AssociativeSection:=GetSection(secrec^.assoc);
if not assigned(objsym.objsection.AssociativeSection) then
Message1(link_e_comdat_associative_section_not_found,objsym.objsection.Name);
end;
end;
dec(auxcount);
inc(symidx);
end;
for i:=1 to auxcount do
begin
if bigobj then