Skip to content

Commit a6fe9fa

Browse files
committed
Add SONAME parsing
1 parent 407bf99 commit a6fe9fa

File tree

1 file changed

+78
-5
lines changed

1 file changed

+78
-5
lines changed

src/runtime_musl_workaround.jl

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,49 @@ manual_gc_roots = String[]
3838
## calculation ourselves, which is more error-prone.
3939

4040

41+
# Define ELF program header structure, depending on our bitwidth
42+
@static if Sys.WORD_SIZE == 32
43+
struct Elf_Phdr
44+
p_type::UInt32
45+
p_offset::UInt32
46+
p_vaddr::UInt32
47+
p_paddr::UInt32
48+
p_filesz::UInt32
49+
p_memsz::UInt32
50+
p_flags::UInt32
51+
p_align::UInt32
52+
end
53+
struct ELF_DynEntry
54+
d_tag::UInt32
55+
# We drop the `d_un` union, and use only `d_val`, omitting `d_ptr`.
56+
d_val::UInt32
57+
end
58+
else
59+
struct Elf_Phdr
60+
p_type::UInt32
61+
p_flags::UInt32
62+
p_offset::UInt64
63+
p_vaddr::UInt64
64+
p_paddr::UInt64
65+
p_filesz::UInt64
66+
p_memsz::UInt64
67+
p_align::UInt64
68+
end
69+
struct ELF_DynEntry
70+
d_tag::UInt64
71+
# We drop the `d_un` union, and use only `d_val`, omitting `d_ptr`.
72+
d_val::UInt64
73+
end
74+
end
75+
76+
# Taken from `include/elf.h`
77+
# https://github.com/ifduyue/musl/blob/aad50fcd791e009961621ddfbe3d4c245fd689a3/include/elf.h#L595
78+
const PT_DYNAMIC = 2
79+
# Taken from `include/elf.h`
80+
#https://github.com/ifduyue/musl/blob/aad50fcd791e009961621ddfbe3d4c245fd689a3/include/elf.h#L735
81+
const DT_SONAME = 14
82+
const DT_STRTAB = 5
83+
4184
# This structure taken from `libc.h`
4285
# https://github.com/ifduyue/musl/blob/aad50fcd791e009961621ddfbe3d4c245fd689a3/src/internal/libc.h#L14-L18
4386
struct musl_tls_module
@@ -61,7 +104,7 @@ struct musl_dso
61104
next::Ptr{musl_dso}
62105
prev::Ptr{musl_dso}
63106

64-
phdr::Ptr{Cvoid}
107+
phdr::Ptr{Elf_Phdr}
65108
phnum::Cint
66109
phentsize::Csize_t
67110

@@ -114,6 +157,37 @@ struct musl_dso
114157
got::Ptr{Csize_t}
115158
end
116159

160+
function parse_soname(dso::musl_dso)
161+
soname_offset = nothing
162+
strtab_addr = nothing
163+
164+
for idx in 1:dso.phnum
165+
phdr = unsafe_load(Ptr{Elf_Phdr}(dso.phdr), idx)
166+
if phdr.p_type == PT_DYNAMIC
167+
@debug("Found dynamic section", idx, phdr.p_vaddr, phdr.p_memsz)
168+
dyn_entries = Ptr{ELF_DynEntry}(phdr.p_vaddr + dso.base)
169+
num_dyn_entries = div(phdr.p_memsz, sizeof(ELF_DynEntry))
170+
for dyn_idx in 1:num_dyn_entries
171+
de = unsafe_load(dyn_entries, dyn_idx)
172+
if de.d_tag == DT_SONAME
173+
@debug("Found SONAME dynamic entry!", de.d_tag, de.d_val)
174+
soname_offset = de.d_val
175+
elseif de.d_tag == DT_STRTAB
176+
@debug("Found STRTAB dynamic entry!", de.d_tag, de.d_val)
177+
strtab_addr = Ptr{UInt8}(de.d_val + dso.base)
178+
end
179+
end
180+
end
181+
end
182+
183+
if strtab_addr !== nothing && soname_offset !== nothing
184+
soname = unsafe_string(strtab_addr + soname_offset)
185+
@debug("Found SONAME entry", soname)
186+
return soname
187+
end
188+
return nothing
189+
end
190+
117191
function replace_musl_shortname(lib_handle::Ptr{Cvoid})
118192
# First, find the absolute path of the library we're talking about
119193
lib_path = abspath(dlpath(lib_handle))
@@ -138,10 +212,9 @@ function replace_musl_shortname(lib_handle::Ptr{Cvoid})
138212
# Calculate the offset of `shortname` from the base pointer of the DSO object
139213
shortname_offset = fieldoffset(musl_dso, findfirst(==(:shortname), fieldnames(musl_dso)))
140214

141-
# Replace the shortname with the basename of lib_path. Note that, in general, this
142-
# should be the SONAME, but not always. If we wanted to be pedantic, we should
143-
# actually parse out the SONAME of this object. But we don't want to be.
144-
new_shortname = basename(lib_path)
215+
# Replace the shortname with the SONAME of this loaded ELF object. If it does not
216+
# exist, use the basename() of the library.
217+
new_shortname = something(parse_soname(dso), basename(lib_path))
145218
push!(manual_gc_roots, new_shortname)
146219
unsafe_store!(Ptr{Ptr{UInt8}}(lib_handle + shortname_offset), pointer(new_shortname))
147220
@debug("musl workaround successful", shortname=new_shortname)

0 commit comments

Comments
 (0)