mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-16 02:30:41 +01:00
+ 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:
parent
b74b3b0047
commit
e9c40f5b24
@ -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
|
||||
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user