LLVM address sanitizer: add asan library and rpath on Darwin

Also verified that "make all" works with asan on macOS/AArch64
This commit is contained in:
Jonas Maebe 2022-07-09 20:44:10 +02:00
parent 8c251db2c1
commit 4193563190

View File

@ -34,7 +34,7 @@ implementation
sysutils, sysutils,
cutils,cfileutl,cclasses, cutils,cfileutl,cclasses,
verbose,systems,globtype,globals, verbose,systems,globtype,globals,
symconst,cscript, symconst,cscript,triplet,
fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef, fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
import,export,link,comprsrc,rescmn,i_darwin,expunix, import,export,link,comprsrc,rescmn,i_darwin,expunix,
cgutils,cgbase,cgobj,cpuinfo,ogbase; cgutils,cgbase,cgobj,cpuinfo,ogbase;
@ -60,6 +60,8 @@ implementation
function GetSysroot: TCmdStr; function GetSysroot: TCmdStr;
function GetLibSearchPath: TCmdStr; function GetLibSearchPath: TCmdStr;
function GetLibraries: TCmdStr; function GetLibraries: TCmdStr;
function InitSanitizersLibraryNameAndPath(const platformname: TCmdStr; out sanitizerLibraryDir, asanLibraryPath: TCmdStr): boolean;
public public
constructor Create;override; constructor Create;override;
procedure SetDefaultInfo;override; procedure SetDefaultInfo;override;
@ -128,16 +130,16 @@ implementation
programs with problems that require Valgrind will have more programs with problems that require Valgrind will have more
than 60KB of data (first 4KB of address space is always invalid) than 60KB of data (first 4KB of address space is always invalid)
} }
ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'; ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS $RPATH -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
if not(cs_gdb_valgrind in current_settings.globalswitches) then if not(cs_gdb_valgrind in current_settings.globalswitches) then
ExeCmd[1]:=ExeCmd[1]+' -pagezero_size 0x10000'; ExeCmd[1]:=ExeCmd[1]+' -pagezero_size 0x10000';
{$else ndef cpu64bitaddr} {$else ndef cpu64bitaddr}
ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'; ExeCmd[1]:='ld $PRTOBJ $TARGET $OPT $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS $RPATH -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
{$endif ndef cpu64bitaddr} {$endif ndef cpu64bitaddr}
if (apptype<>app_bundle) then if (apptype<>app_bundle) then
DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -dylib -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES' DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS $RPATH -dynamic -dylib -L. -o $EXE $ARCH $VERSION $SYSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'
else else
DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS -dynamic -bundle -L. -o $EXE $ARCH $VERSION $SYRSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES'; DllCmd[1]:='ld $PRTOBJ $TARGET $OPT $GCSECTIONS $MAP $LTO $ORDERSYMS $RPATH -dynamic -bundle -L. -o $EXE $ARCH $VERSION $SYRSROOT $LIBSEARCHPATH $FILELIST $LIBRARIES';
DllCmd[2]:='strip -x $EXE'; DllCmd[2]:='strip -x $EXE';
DynamicLinker:=''; DynamicLinker:='';
end; end;
@ -441,7 +443,56 @@ implementation
end; end;
Function tlinkerdarwin.WriteFileList: TCmdStr; function tlinkerdarwin.InitSanitizersLibraryNameAndPath(const platformname: TCmdStr; out sanitizerLibraryDir, asanLibraryPath: TCmdStr): boolean;
var
clang,
clangsearchdirs,
textline,
clangsearchdirspath: TCmdStr;
searchrec: TSearchRec;
searchres: longint;
clangsearchdirsfile: text;
begin
result:=false;
if (cs_sanitize_address in current_settings.moduleswitches) and
not(cs_link_on_target in current_settings.globalswitches) then
begin
{ ask clang }
clang:=FindUtil('clang'+llvmutilssuffix);
if clang<>'' then
begin
clangsearchdirspath:=outputexedir+UniqueName('clangsearchdirs');
searchres:=shell(maybequoted(clang)+' -target '+targettriplet(triplet_llvm)+' -print-file-name=lib > '+clangsearchdirspath);
if searchres=0 then
begin
AssignFile(clangsearchdirsfile,clangsearchdirspath);
{$push}{$i-}
reset(clangsearchdirsfile);
{$pop}
if ioresult=0 then
begin
readln(clangsearchdirsfile,textline);
sanitizerLibraryDir:=FixFileName(textline+'/'+platformname);
if target_info.system in systems_macosx then
asanLibraryPath:=FixFileName(sanitizerLibraryDir+'/')+target_info.sharedClibprefix+'clang_rt.asan_osx_dynamic'+target_info.sharedClibext
else if target_info.system in systems_ios then
asanLibraryPath:=FixFileName(sanitizerLibraryDir+'/')+target_info.sharedClibprefix+'clang_rt.asan_ios_dynamic'+target_info.sharedClibext
else if target_info.system in systems_iphonesym then
asanLibraryPath:=FixFileName(sanitizerLibraryDir+'/')+target_info.sharedClibprefix+'clang_rt.asan_iossim_dynamic'+target_info.sharedClibext
else
internalerror(2022071010);
result:=FileExists(asanLibraryPath,false);
end;
end;
if FileExists(clangsearchdirspath,false) then
DeleteFile(clangsearchdirspath);
end;
end;
end;
function tlinkerdarwin.WriteFileList: TCmdStr;
Var Var
FilesList : TScript; FilesList : TScript;
s : TCmdStr; s : TCmdStr;
@ -481,11 +532,14 @@ implementation
extdbgbinstr, extdbgbinstr,
extdbgcmdstr, extdbgcmdstr,
ltostr, ltostr,
asanstr,
ordersymfile, ordersymfile,
linkfiles: TCmdStr; linkfiles: TCmdStr;
GCSectionsStr, GCSectionsStr,
StaticStr, StaticStr,
StripStr : TCmdStr; StripStr,
asanLibraryName,
sanitizerLibraryDir: TCmdStr;
success : boolean; success : boolean;
begin begin
if not(cs_link_nolink in current_settings.globalswitches) then if not(cs_link_nolink in current_settings.globalswitches) then
@ -519,9 +573,6 @@ implementation
ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib'); ltostr:='-lto_library '+maybequoted(utilsdirectory+'/../lib/libLTO.dylib');
end; end;
{ Write list of files to link }
linkfiles:=WriteFileList;
{ Write symbol order file } { Write symbol order file }
ordersymfile:=WriteSymbolOrderFile; ordersymfile:=WriteSymbolOrderFile;
@ -538,6 +589,19 @@ implementation
else else
Replace(cmdstr,'$ORDERSYMS',''); Replace(cmdstr,'$ORDERSYMS','');
if InitSanitizersLibraryNameAndPath('darwin',sanitizerLibraryDir,asanLibraryName) then
begin
ObjectFiles.Concat(asanLibraryName);
Replace(cmdstr,'$RPATH','-rpath '+sanitizerLibraryDir)
end
else
begin
Replace(cmdstr,'$RPATH','');
end;
{ Write list of files to link }
linkfiles:=WriteFileList;
Replace(cmdstr,'$STATIC',StaticStr); Replace(cmdstr,'$STATIC',StaticStr);
Replace(cmdstr,'$STRIP',StripStr); Replace(cmdstr,'$STRIP',StripStr);
Replace(cmdstr,'$GCSECTIONS',GCSectionsStr); Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
@ -582,7 +646,7 @@ implementation
end; end;
Function tlinkerdarwin.MakeSharedLibrary:boolean; function tlinkerdarwin.MakeSharedLibrary: boolean;
var var
InitStr, InitStr,
FiniStr, FiniStr,
@ -595,7 +659,9 @@ implementation
extdbgbinstr, extdbgbinstr,
extdbgcmdstr, extdbgcmdstr,
linkfiles, linkfiles,
GCSectionsStr : TCmdStr; GCSectionsStr,
sanitizerLibraryDir,
asanLibraryName: TCmdStr;
exportedsyms: text; exportedsyms: text;
success : boolean; success : boolean;
begin begin
@ -606,9 +672,6 @@ implementation
if not(cs_link_nolink in current_settings.globalswitches) then if not(cs_link_nolink in current_settings.globalswitches) then
Message1(exec_i_linking,current_module.sharedlibfilename); Message1(exec_i_linking,current_module.sharedlibfilename);
{ Write list of files to link }
linkfiles:=WriteFileList;
{ Write symbol order file } { Write symbol order file }
ordersymfile:=WriteSymbolOrderFile; ordersymfile:=WriteSymbolOrderFile;
@ -647,6 +710,20 @@ implementation
Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile)) Replace(cmdstr,'$ORDERSYMS','-order_file '+maybequoted(ordersymfile))
else else
Replace(cmdstr,'$ORDERSYMS',''); Replace(cmdstr,'$ORDERSYMS','');
{ add asan library if known }
if InitSanitizersLibraryNameAndPath('darwin',sanitizerLibraryDir,asanLibraryName) then
begin
ObjectFiles.Concat(asanLibraryName);
Replace(cmdstr,'$RPATH','-rpath '+sanitizerLibraryDir)
end
else
begin
Replace(cmdstr,'$RPATH','');
end;
{ Write list of files to link }
linkfiles:=WriteFileList;
Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true)); Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
Replace(cmdstr,'$ARCH', GetLinkArch); Replace(cmdstr,'$ARCH', GetLinkArch);
Replace(cmdstr,'$VERSION',GetLinkVersion); Replace(cmdstr,'$VERSION',GetLinkVersion);