@@ -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
4386struct 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}
115158end
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+
117191function 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