11import Base. BinaryPlatforms: detect_libstdcxx_version, detect_cxxstring_abi
22using ObjectFile
3+ using ObjectFile. ELF
34using Binutils_jll: Binutils_jll
45
56csl_warning (lib) = @lock AUDITOR_LOGGING_LOCK @warn (
@@ -195,6 +196,84 @@ function cppfilt(symbol_names::Vector, platform::AbstractPlatform; strip_undersc
195196 return filter! (s -> ! isempty (s), split (String (take! (output)), " \n " ))
196197end
197198
199+ function dynamic_abi_symbols (oh:: ELFHandle )
200+ dyn_sections = findall (Sections (oh), " .dynsym" )
201+ if ! isempty (dyn_sections)
202+ return Symbols (first (dyn_sections))
203+ end
204+ return nothing
205+ end
206+
207+ abi_symbol_names (syms) = symbol_name .(syms)
208+
209+ function lookup_strtab (strtab:: AbstractVector{UInt8} , index:: Integer )
210+ i = Int (index) + 1
211+ j = findnext (== (0x00 ), strtab, i)
212+ j === nothing && return String (strtab[i: end ])
213+ return String (strtab[i: j- 1 ])
214+ end
215+
216+ function abi_symbol_names (syms:: ELFSymbols )
217+ strtab = read (StrTab (syms). section_ref)
218+ return [lookup_strtab (strtab, deref (sym). st_name) for sym in syms]
219+ end
220+
221+ has_cxx11_marker (symbol_name:: AbstractString ) = occursin (" St7__cxx11" , symbol_name) ||
222+ occursin (" __cxx11" , symbol_name) ||
223+ occursin (" B5cxx11" , symbol_name)
224+ has_cxx03_marker (symbol_name:: AbstractString ) = startswith (symbol_name, " _ZNSs" ) || startswith (symbol_name, " _ZNSb" )
225+
226+ function detect_cxxstring_abi (symbol_names:: Vector{<:AbstractString} , platform:: AbstractPlatform )
227+ # Fast paths on mangled names. These avoid invoking c++filt for large C++
228+ # libraries when the ABI evidence is already visible in the raw symbol names.
229+ if any (has_cxx11_marker, symbol_names)
230+ return " cxx11"
231+ end
232+ if any (has_cxx03_marker, symbol_names)
233+ return " cxx03"
234+ end
235+
236+ demangled_names = cppfilt (symbol_names, platform; strip_underscore= Sys. isapple (platform))
237+ if any (occursin (" [abi:cxx11]" , c) || occursin (" std::__cxx11" , c) for c in demangled_names)
238+ return " cxx11"
239+ end
240+ if any (occursin (" std::string" , c) || occursin (" std::basic_string" , c) ||
241+ occursin (" std::list" , c) for c in demangled_names)
242+ return " cxx03"
243+ end
244+ return nothing
245+ end
246+
247+ detect_cxxstring_abi_from_symbols (syms, platform:: AbstractPlatform ) = detect_cxxstring_abi (abi_symbol_names (syms), platform)
248+
249+ function detect_dynamic_cxx11_abi (oh:: ELFHandle )
250+ syms = dynamic_abi_symbols (oh)
251+ syms === nothing && return nothing
252+
253+ strtab = read (StrTab (syms). section_ref)
254+ for sym in syms
255+ symbol_name = lookup_strtab (strtab, deref (sym). st_name)
256+ has_cxx11_marker (symbol_name) && return " cxx11"
257+ end
258+ return nothing
259+ end
260+
261+ function detect_cxxstring_abi_from_symbols (syms:: ELFSymbols , platform:: AbstractPlatform )
262+ strtab = read (StrTab (syms). section_ref)
263+ symbol_names = String[]
264+ found_cxx03 = false
265+ for sym in syms
266+ symbol_name = lookup_strtab (strtab, deref (sym). st_name)
267+ if has_cxx11_marker (symbol_name)
268+ return " cxx11"
269+ end
270+ found_cxx03 |= has_cxx03_marker (symbol_name)
271+ push! (symbol_names, symbol_name)
272+ end
273+ found_cxx03 && return " cxx03"
274+ return detect_cxxstring_abi (symbol_names, platform)
275+ end
276+
198277"""
199278 detect_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform)
200279
@@ -210,20 +289,12 @@ function detect_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform)
210289 return nothing
211290 end
212291
213- # GCC on macOS prepends an underscore to symbols, strip it.
214- symbol_names = cppfilt (symbol_name .(Symbols (oh)), platform; strip_underscore= Sys. isapple (platform))
215- # Shove the symbol names through c++filt (since we don't want to have to
216- # reimplement the parsing logic in Julia). If anything has `cxx11` tags,
217- # then mark it as such.
218- if any (occursin (" [abi:cxx11]" , c) || occursin (" std::__cxx11" , c) for c in symbol_names)
219- return " cxx11"
220- end
221- # Otherwise, if we still have `std::string`'s or `std::list`'s in there, it's implicitly a
222- # `cxx03` binary, even though we don't have a __cxx03 namespace or something. Mark it.
223- if any (occursin (" std::string" , c) || occursin (" std::basic_string" , c) ||
224- occursin (" std::list" , c) for c in symbol_names)
225- return " cxx03"
292+ if isa (oh, ELFHandle)
293+ cxx_abi = detect_dynamic_cxx11_abi (oh)
294+ cxx_abi === nothing || return cxx_abi
226295 end
296+
297+ return detect_cxxstring_abi_from_symbols (Symbols (oh), platform)
227298 catch e
228299 if isa (e, InterruptException)
229300 rethrow (e)
0 commit comments