mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 19:49:31 +02:00
llvm: generalised sanitizer linking support
Also enabled automatic detection of sanitizer library + setting rpath to Linux
This commit is contained in:
parent
75c16b6126
commit
7ef33cf4b2
@ -82,7 +82,8 @@ interface
|
||||
TExternalLinker = class(TLinker)
|
||||
protected
|
||||
Function WriteSymbolOrderFile: TCmdStr;
|
||||
Function GetSanitizersLibraryNameAndPath(const platformname, asanlibinfix: TCmdStr; out sanitizerLibraryDir, asanLibraryPath: TCmdStr): boolean;
|
||||
Function GetSanitizerLibName(const basename: TCmdStr; withArch: boolean): TCmdStr;
|
||||
Function AddSanitizerLibrariesAndGetSearchDir(const platformname: TCmdStr; out sanitizerlibrarydir: TCmdStr): boolean;
|
||||
public
|
||||
Info : TLinkerInfo;
|
||||
Constructor Create;override;
|
||||
@ -174,7 +175,7 @@ Implementation
|
||||
{$ifdef hasUnix}
|
||||
baseunix,
|
||||
{$endif hasUnix}
|
||||
cscript,globals,verbose,comphook,ppu,fpchash,triplet,
|
||||
cscript,globals,verbose,comphook,ppu,fpchash,triplet,tripletcpu,
|
||||
aasmbase,aasmcpu,
|
||||
ogmap;
|
||||
|
||||
@ -679,16 +680,50 @@ Implementation
|
||||
end;
|
||||
|
||||
|
||||
Function TExternalLinker.GetSanitizersLibraryNameAndPath(const platformname, asanlibinfix: TCmdStr; out sanitizerLibraryDir, asanLibraryPath: TCmdStr): boolean;
|
||||
Function TExternalLinker.GetSanitizerLibName(const basename: TCmdStr; withArch: boolean): TCmdStr;
|
||||
begin
|
||||
result:=target_info.sharedClibprefix+'clang_rt.'+basename;
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
{ Darwin never adds the arch, it uses fat binaries. But it has the
|
||||
extra '_dynamic' for some reason, and also adds the platform type
|
||||
}
|
||||
if target_info.system in systems_macosx then
|
||||
result:=result+'_osx_dynamic'
|
||||
else if target_info.system in systems_ios then
|
||||
result:='_ios_dynamic'
|
||||
else if target_info.system in systems_iphonesym then
|
||||
result:='_iossim_dynamic'
|
||||
else
|
||||
internalerror(2022071010);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if withArch then
|
||||
begin
|
||||
result:=result+'-'+tripletcpustr(triplet_llvmrt);
|
||||
if target_info.system in systems_android then
|
||||
result:=result+'-android';
|
||||
end;
|
||||
end;
|
||||
result:=result+target_info.sharedClibext;
|
||||
end;
|
||||
|
||||
|
||||
function TExternalLinker.AddSanitizerLibrariesAndGetSearchDir(const platformname: TCmdStr; out sanitizerlibrarydir: TCmdStr): boolean;
|
||||
var
|
||||
clang,
|
||||
clangsearchdirs,
|
||||
textline,
|
||||
clangsearchdirspath: TCmdStr;
|
||||
clangsearchdirspath,
|
||||
sanitizerlibname,
|
||||
sanitizerlibrarypath: TCmdStr;
|
||||
sanitizerlibraryfiles: TCmdStrList;
|
||||
searchrec: TSearchRec;
|
||||
searchres: longint;
|
||||
clangsearchdirsfile: text;
|
||||
begin
|
||||
sanitizerlibraryfiles:=TCmdStrList.Create;
|
||||
result:=false;
|
||||
if (cs_sanitize_address in current_settings.moduleswitches) and
|
||||
not(cs_link_on_target in current_settings.globalswitches) then
|
||||
@ -708,15 +743,33 @@ Implementation
|
||||
if ioresult=0 then
|
||||
begin
|
||||
readln(clangsearchdirsfile,textline);
|
||||
sanitizerLibraryDir:=FixFileName(textline+'/'+platformname);
|
||||
asanLibraryPath:=FixFileName(sanitizerLibraryDir+'/')+target_info.sharedClibprefix+'clang_rt.asan_'+asanlibinfix+'_dynamic'+target_info.sharedClibext;
|
||||
result:=FileExists(asanLibraryPath,false);
|
||||
sanitizerlibrarydir:=FixFileName(textline+'/'+platformname);
|
||||
sanitizerlibrarypath:=FixFileName(sanitizerlibrarydir+'/');
|
||||
{ from clang:
|
||||
Check for runtime files in the new layout without the architecture first.
|
||||
}
|
||||
sanitizerlibname:=GetSanitizerLibName('asan',false);
|
||||
result:=FileExists(sanitizerlibrarypath+sanitizerlibname,false);
|
||||
if result then
|
||||
begin
|
||||
sanitizerlibraryfiles.Concat(sanitizerlibrarypath+sanitizerlibname);
|
||||
end
|
||||
else
|
||||
begin
|
||||
sanitizerlibname:=GetSanitizerLibName('asan',true);
|
||||
result:=FileExists(sanitizerlibrarypath+sanitizerlibname,false);
|
||||
if result then
|
||||
sanitizerlibraryfiles.Concat(sanitizerlibrarypath+sanitizerlibname);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if FileExists(clangsearchdirspath,false) then
|
||||
DeleteFile(clangsearchdirspath);
|
||||
end;
|
||||
end;
|
||||
if result then
|
||||
ObjectFiles.concatList(sanitizerlibraryfiles);
|
||||
sanitizerlibraryfiles.free;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -61,7 +61,6 @@ implementation
|
||||
function GetLibSearchPath: TCmdStr;
|
||||
function GetLibraries: TCmdStr;
|
||||
|
||||
function GetSanitizerLibraryInfix: TCmdStr;
|
||||
public
|
||||
constructor Create;override;
|
||||
procedure SetDefaultInfo;override;
|
||||
@ -443,19 +442,6 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function tlinkerdarwin.GetSanitizerLibraryInfix: TCmdStr;
|
||||
begin
|
||||
if target_info.system in systems_macosx then
|
||||
result:='osx'
|
||||
else if target_info.system in systems_ios then
|
||||
result:='ios'
|
||||
else if target_info.system in systems_iphonesym then
|
||||
result:='iossim'
|
||||
else
|
||||
internalerror(2022071010);
|
||||
end;
|
||||
|
||||
|
||||
function tlinkerdarwin.WriteFileList: TCmdStr;
|
||||
Var
|
||||
FilesList : TScript;
|
||||
@ -502,7 +488,6 @@ implementation
|
||||
GCSectionsStr,
|
||||
StaticStr,
|
||||
StripStr,
|
||||
asanLibraryName,
|
||||
sanitizerLibraryDir: TCmdStr;
|
||||
success : boolean;
|
||||
begin
|
||||
@ -532,7 +517,7 @@ implementation
|
||||
if (cs_lto in current_settings.moduleswitches) and
|
||||
not(cs_link_on_target in current_settings.globalswitches) and
|
||||
(utilsdirectory<>'') and
|
||||
FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
|
||||
FileExists(utilsdirectory+'/../lib/libLTO.dylib',false) then
|
||||
begin
|
||||
ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
|
||||
end;
|
||||
@ -553,10 +538,11 @@ implementation
|
||||
else
|
||||
Replace(cmdstr,'$ORDERSYMS','');
|
||||
|
||||
if GetSanitizersLibraryNameAndPath('darwin',GetSanitizerLibraryInfix,sanitizerLibraryDir,asanLibraryName) then
|
||||
if AddSanitizerLibrariesAndGetSearchDir('darwin',sanitizerLibraryDir) then
|
||||
begin
|
||||
ObjectFiles.Concat(asanLibraryName);
|
||||
Replace(cmdstr,'$RPATH','-rpath '+sanitizerLibraryDir)
|
||||
{ also add the executable path as search path in case the asan
|
||||
library gets copied into the application bundle }
|
||||
Replace(cmdstr,'$RPATH','-rpath @executable_path -rpath '+maybequoted(sanitizerLibraryDir))
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -624,8 +610,7 @@ implementation
|
||||
extdbgcmdstr,
|
||||
linkfiles,
|
||||
GCSectionsStr,
|
||||
sanitizerLibraryDir,
|
||||
asanLibraryName: TCmdStr;
|
||||
sanitizerLibraryDir: TCmdStr;
|
||||
exportedsyms: text;
|
||||
success : boolean;
|
||||
begin
|
||||
@ -649,7 +634,7 @@ implementation
|
||||
if (cs_lto in current_settings.moduleswitches) and
|
||||
not(cs_link_on_target in current_settings.globalswitches) and
|
||||
(utilsdirectory<>'') and
|
||||
FileExists(utilsdirectory+'/../lib/libLTO.dylib',true) then
|
||||
FileExists(utilsdirectory+'/../lib/libLTO.dylib',false) then
|
||||
begin
|
||||
ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
|
||||
end;
|
||||
@ -675,10 +660,11 @@ implementation
|
||||
else
|
||||
Replace(cmdstr,'$ORDERSYMS','');
|
||||
{ add asan library if known }
|
||||
if GetSanitizersLibraryNameAndPath('darwin',GetSanitizerLibraryInfix,sanitizerLibraryDir,asanLibraryName) then
|
||||
if AddSanitizerLibrariesAndGetSearchDir('darwin',sanitizerLibraryDir) then
|
||||
begin
|
||||
ObjectFiles.Concat(asanLibraryName);
|
||||
Replace(cmdstr,'$RPATH','-rpath '+sanitizerLibraryDir)
|
||||
{ also add the executable path as search path in case the asan
|
||||
library gets copied into the application bundle }
|
||||
Replace(cmdstr,'$RPATH','-rpath @executable_path -rpath '+maybequoted(sanitizerLibraryDir))
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
@ -398,8 +398,8 @@ begin
|
||||
|
||||
with Info do
|
||||
begin
|
||||
ExeCmd[1]:='ld '+platform_select+platformopt+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $LTO -L. -o $EXE';
|
||||
DllCmd[1]:='ld '+platform_select+platformopt+' $OPT $INIT $FINI $SONAME $MAP $LTO -shared $GCSECTIONS -L. -o $EXE';
|
||||
ExeCmd[1]:='ld '+platform_select+platformopt+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $LTO $RPATH -L. -o $EXE';
|
||||
DllCmd[1]:='ld '+platform_select+platformopt+' $OPT $INIT $FINI $SONAME $MAP $LTO $RPATH -shared $GCSECTIONS -L. -o $EXE';
|
||||
{ when we want to cross-link we need to override default library paths;
|
||||
when targeting binutils 2.19 or later, we use the "INSERT" command to
|
||||
augment the default linkerscript, which also requires -T (normally that
|
||||
@ -740,7 +740,9 @@ var
|
||||
binstr,
|
||||
cmdstr,
|
||||
mapstr,
|
||||
ltostr : TCmdStr;
|
||||
ltostr,
|
||||
rpathstr,
|
||||
sanitizerLibraryDir: TCmdStr;
|
||||
success : boolean;
|
||||
DynLinkStr : ansistring;
|
||||
GCSectionsStr,
|
||||
@ -757,6 +759,7 @@ begin
|
||||
DynLinkStr:='';
|
||||
mapstr:='';
|
||||
ltostr:='';
|
||||
rpathstr:='';
|
||||
if (cs_link_staticflag in current_settings.globalswitches) then
|
||||
StaticStr:='-static';
|
||||
if (cs_link_strip in current_settings.globalswitches) and
|
||||
@ -786,6 +789,11 @@ begin
|
||||
ltostr:='-plugin '+maybequoted(utilsdirectory+'/../lib/LLVMgold.so ');
|
||||
end;
|
||||
|
||||
if AddSanitizerLibrariesAndGetSearchDir('linux',sanitizerLibraryDir) then
|
||||
begin
|
||||
rpathstr:='-rpath '+maybequoted(sanitizerLibraryDir);
|
||||
end;
|
||||
|
||||
{ Write used files and libraries }
|
||||
WriteResponseFile(false);
|
||||
|
||||
@ -800,6 +808,7 @@ begin
|
||||
Replace(cmdstr,'$DYNLINK',DynLinkStr);
|
||||
Replace(cmdstr,'$MAP',mapstr);
|
||||
Replace(cmdstr,'$LTO',ltostr);
|
||||
Replace(cmdstr,'$RPATH',rpathstr);
|
||||
|
||||
{ create dynamic symbol table? }
|
||||
if HasExports then
|
||||
@ -853,7 +862,9 @@ var
|
||||
binstr,
|
||||
cmdstr,
|
||||
mapstr,
|
||||
ltostr : TCmdStr;
|
||||
ltostr,
|
||||
rpathstr,
|
||||
sanitizerLibraryDir: TCmdStr;
|
||||
success : boolean;
|
||||
begin
|
||||
MakeSharedLibrary:=false;
|
||||
@ -887,7 +898,12 @@ begin
|
||||
ltostr:='-plugin '+maybequoted(utilsdirectory+'/../lib/LLVMgold.so ');
|
||||
end;
|
||||
|
||||
{ Call linker }
|
||||
if AddSanitizerLibrariesAndGetSearchDir('linux',sanitizerLibraryDir) then
|
||||
begin
|
||||
rpathstr:='-rpath '+maybequoted(sanitizerLibraryDir)
|
||||
end;
|
||||
|
||||
{ Call linker }
|
||||
SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
|
||||
Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
|
||||
Replace(cmdstr,'$OPT',Info.ExtraOptions);
|
||||
@ -897,6 +913,7 @@ begin
|
||||
Replace(cmdstr,'$SONAME',SoNameStr);
|
||||
Replace(cmdstr,'$MAP',mapstr);
|
||||
Replace(cmdstr,'$LTO',ltostr);
|
||||
Replace(cmdstr,'$RPATH',rpathstr);
|
||||
Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
|
||||
success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user