diff --git a/Project.toml b/Project.toml index a030befd..203e31dd 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.6.4" [deps] ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63" BinaryBuilderBase = "7f725544-6523-48cd-82d1-3fa08ff4056e" +Binutils_jll = "489e263e-5428-50b0-a723-147a141b401e" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" GitHub = "bc5e4493-9b4d-5f90-b8aa-2b2bcaad7a26" @@ -34,6 +35,7 @@ ghr_jll = "07c12ed4-43bc-5495-8a2a-d5838ef8d533" [compat] ArgParse = "1.1" +Binutils_jll = "2" BinaryBuilderBase = "1.35.2" Downloads = "1" GitHub = "5.1" diff --git a/src/Auditor.jl b/src/Auditor.jl index 52788c7a..139845f9 100644 --- a/src/Auditor.jl +++ b/src/Auditor.jl @@ -18,9 +18,9 @@ const AUDITOR_LOGGING_LOCK = ReentrantLock() # Helper function to run a command and print to `io` its invocation and full # output (mimim what the sandbox does normally, but outside of it). -function run_with_io(io::IO, cmd::Cmd) +function run_with_io(io::IO, cmd::Cmd; wait::Bool=true) println(io, "---> $(join(cmd.exec, " "))") - run(pipeline(cmd; stdout=io, stderr=io)) + run(pipeline(cmd; stdout=io, stderr=io); wait) end include("auditor/instruction_set.jl") diff --git a/src/auditor/compiler_abi.jl b/src/auditor/compiler_abi.jl index f60bf08b..d384d3cc 100644 --- a/src/auditor/compiler_abi.jl +++ b/src/auditor/compiler_abi.jl @@ -1,5 +1,6 @@ import Base.BinaryPlatforms: detect_libstdcxx_version, detect_cxxstring_abi using ObjectFile +using Binutils_jll: Binutils_jll csl_warning(lib) = @lock AUDITOR_LOGGING_LOCK @warn( """ @@ -171,15 +172,24 @@ function cppfilt(symbol_names::Vector, platform::AbstractPlatform; strip_undersc seekstart(input) output = IOBuffer() - mktempdir() do dir - # No need to acquire a sandbox lock here because we use a (hopefully) - # different temporary directory for each run. - ur = preferred_runner()(dir; cwd="/workspace/", platform=platform) - cmd = Cmd(`/opt/bin/$(triplet(ur.platform))/c++filt`; ignorestatus=true) - if strip_underscore - cmd = `$(cmd) --strip-underscore` + cmd = if Binutils_jll.is_available() + ignorestatus(Binutils_jll.cxxfilt()) + else + Cmd(`/opt/bin/$(triplet(platform))/c++filt`; ignorestatus=true) + end + if strip_underscore + cmd = `$(cmd) --strip-underscore` + end + + if Binutils_jll.is_available() + run(pipeline(cmd; stdin=input, stdout=output)) + else + mktempdir() do dir + # No need to acquire a sandbox lock here because we use a (hopefully) + # different temporary directory for each run. + ur = preferred_runner()(dir; cwd="/workspace/", platform=platform) + run_interactive(ur, cmd; stdin=input, stdout=output) end - run_interactive(ur, cmd; stdin=input, stdout=output) end return filter!(s -> !isempty(s), split(String(take!(output)), "\n")) diff --git a/src/auditor/soname_matching.jl b/src/auditor/soname_matching.jl index 49d51346..06408731 100644 --- a/src/auditor/soname_matching.jl +++ b/src/auditor/soname_matching.jl @@ -1,3 +1,5 @@ +using Patchelf_jll: patchelf + # Not everything has an SONAME get_soname(oh::ObjectHandle) = nothing @@ -63,20 +65,16 @@ function ensure_soname(prefix::Prefix, path::AbstractString, platform::AbstractP end # Otherwise, set the SONAME - ur = preferred_runner()(prefix.path; cwd="/workspace/", platform=platform) - set_soname_cmd = `` - - if Sys.isapple(platform) - install_name_tool = "/opt/bin/$(triplet(ur.platform))/install_name_tool" - set_soname_cmd = `$install_name_tool -id $(soname) $(rel_path)` - elseif Sys.islinux(platform) || Sys.isbsd(platform) - patchelf = "/usr/bin/patchelf" - set_soname_cmd = `$patchelf $(patchelf_flags(platform)) --set-soname $(soname) $(rel_path)` - end - - # Create a new linkage that looks like @rpath/$lib on OSX, + # Create a new linkage that looks like @rpath/$lib on OSX, retval = with_logfile(prefix, "set_soname_$(basename(rel_path))_$(soname).log"; subdir) do io - @lock AUDITOR_SANDBOX_LOCK run(ur, set_soname_cmd, io; verbose=verbose) + if Sys.isapple(platform) + ur = preferred_runner()(prefix.path; cwd="/workspace/", platform=platform) + install_name_tool = "/opt/bin/$(triplet(ur.platform))/install_name_tool" + set_soname_cmd = `$install_name_tool -id $(soname) $(rel_path)` + @lock AUDITOR_SANDBOX_LOCK run(ur, set_soname_cmd, io; verbose=verbose) + elseif Sys.islinux(platform) || Sys.isbsd(platform) + success(run_with_io(io, `$(patchelf()) $(patchelf_flags(platform)) --set-soname $(soname) $(realpath(path))`; wait=false)) + end end if !retval diff --git a/test/auditing.jl b/test/auditing.jl index a0e0ab3a..f21faba3 100644 --- a/test/auditing.jl +++ b/test/auditing.jl @@ -27,8 +27,12 @@ using BinaryBuilder.Auditor: compatible_marchs, valid_library_path "__ZNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_S5_ESt10_Select1stIS8_ESt4lessIS5_ESaIS8_EE7_M_copyINSE_11_Alloc_nodeEEEPSt13_Rb_tree_nodeIS8_EPKSI_PSt18_Rb_tree_node_baseRT_", ] unmangled_symbol_names = Auditor.cppfilt(mangled_symbol_names, Platform("x86_64", "macos"); strip_underscore=true) - @test all(unmangled_symbol_names .== [ - "std::__cxx11::basic_string, std::allocator >::basic_string(char const*, std::allocator const&) (.isra.41)", + # binutils and llvm c++filt slightly disagree on the formatting of final annotation of + # this symbol (`[clone .isra.41]` for the former, `(.isra.41)` for the latter), so we + # only compare the rest. + @test startswith(unmangled_symbol_names[1], + "std::__cxx11::basic_string, std::allocator >::basic_string(char const*, std::allocator const&)") + @test all(unmangled_symbol_names[2:end] .== [ "std::__cxx11::basic_string, std::allocator > std::operator+, std::allocator >(std::__cxx11::basic_string, std::allocator >&&, char const*)", "std::vector, std::allocator >, std::map, std::allocator >, std::__cxx11::basic_string, std::allocator >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > > >, std::allocator, std::allocator >, std::map, std::allocator >, std::__cxx11::basic_string, std::allocator >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > > > > >::~vector()", "std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >* std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_M_copy, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Alloc_node>(std::_Rb_tree_node, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > const*, std::_Rb_tree_node_base*, std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, std::__cxx11::basic_string, std::allocator > >, std::_Select1st, std::allocator > const, std::__cxx11::basic_string, std::allocator > > >, std::less, std::allocator > >, std::allocator, std::allocator > const, std::__cxx11::basic_string, std::allocator > > > >::_Alloc_node&)",