Skip to content

Commit d7b7aa6

Browse files
committed
Add jl_RTLD_DEFAULT_handle for interop/interactive use, rearrange things
1 parent 1873529 commit d7b7aa6

File tree

4 files changed

+183
-177
lines changed

4 files changed

+183
-177
lines changed

src/StaticTools.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module StaticTools
2323
const AbstractMallocdMemory = Union{MallocString, MallocArray}
2424

2525
# Here there be `llvmcall`s
26-
include("llvminterop.jl") # dlopen/sym/close, @ptrcall, @symbolcall
26+
include("llvminterop.jl") # dlopen/sym/close, @ptrcall, @symbolcall, @externload
2727
include("llvmio.jl") # Best way to print things? LLVM IR obviously!
2828
include("llvmlibc.jl") # strtod, strtol, parse, etc...
2929

src/llvminterop.jl

Lines changed: 0 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -19,182 +19,6 @@ Ptr{Int64} @0x000000015751af00
1919
@inline (x) = Base.pointer(x)
2020
@inline (x::Ref{T}) where {T} = Ptr{T}(Base.pointer_from_objref(x))
2121

22-
## --- dlopen
23-
24-
const RTLD_LOCAL = Int32(1)
25-
const RTLD_GLOBAL = Int32(2)
26-
const RTLD_LAZY = Int32(4)
27-
const RTLD_NOW = Int32(8)
28-
29-
"""
30-
```julia
31-
dlopen(name::AbstractString, flag=RTLD_LOCAL|RTLD_LAZY)
32-
```
33-
Libc `dlopen` function, accessed by direct `llvmcall`.
34-
35-
Returns a handle (pointer) to a `.so`/`.dylib` shared library specified by
36-
`name` opened with the mode or combination of modes specified by `flag`.
37-
Returns `C_NULL` on failure. Valid modes include:
38-
39-
Required:
40-
41-
`RTLD_LOCAL` (default): Symbols will not be made available for subsequently loaded libraries. The opposite of `RTLD_GLOBAL`.
42-
43-
`RTLD_GLOBAL`: Symbols will be made available for subsequently loaded libraries. The opposite of `RTLD_LOCAL`.
44-
45-
Optional:
46-
47-
`RTLD_LAZY` (default): Lazy binding: only resolve symbols as the code that references them is executed. The opposite of `RLTD_NOW`.
48-
49-
`RTLD_NOW`: Eager binding: resolve all symbols before `dlopen` returns. The opposite of `RTLD_LAZY`
50-
51-
Modes from the two categories can be combined with bitwise `or` (`|`)
52-
53-
See also: `StaticTools.dlsym`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
54-
55-
## Examples
56-
```julia
57-
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
58-
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
59-
60-
julia> fp = StaticTools.dlsym(lib, c"time")
61-
Ptr{Nothing} @0x00007fffa773dfa4
62-
63-
julia> dltime() = @ptrcall fp()::Int
64-
ctime (generic function with 1 method)
65-
66-
julia> dltime()
67-
1654320146
68-
69-
julia> StaticTools.dlclose(lib)
70-
0
71-
```
72-
"""
73-
@inline dlopen(name::AbstractMallocdMemory, flag=RTLD_LOCAL|RTLD_LAZY) = dlopen(pointer(name), flag)
74-
@inline dlopen(name, flag=RTLD_LOCAL|RTLD_LAZY) = GC.@preserve name dlopen(pointer(name), flag)
75-
@inline function dlopen(name::Ptr{UInt8}, flag::Int32)
76-
Base.llvmcall(("""
77-
; External declaration of the dlopen function
78-
declare i8* @dlopen(i8*, i32)
79-
80-
define i64 @main(i64 %jlname, i32 %flag) #0 {
81-
entry:
82-
%name = inttoptr i64 %jlname to i8*
83-
%fp = call i8* (i8*, i32) @dlopen(i8* %name, i32 %flag)
84-
%jlfp = ptrtoint i8* %fp to i64
85-
ret i64 %jlfp
86-
}
87-
88-
attributes #0 = { alwaysinline nounwind ssp uwtable }
89-
""", "main"), Ptr{DYLIB}, Tuple{Ptr{UInt8}, Int32}, name, flag)
90-
end
91-
92-
@static if Sys.isapple()
93-
const DLEXT = c".dylib"
94-
elseif Sys.iswindows()
95-
const DLEXT = c".dll"
96-
else
97-
const DLEXT = c".so"
98-
end
99-
100-
## --- dylsym
101-
102-
"""
103-
```julia
104-
dlsym(lib::Ptr{DYLIB}, symbol::AbstractString)
105-
```
106-
Libc `dlsym` function, accessed by direct StaticCompiler-safe `llvmcall`.
107-
108-
Takes a handle (`lib`) to a `.so`/`.dylib` shared library previously opened with
109-
`StaticTools.dlopen`, along with a null-terminated symbol name string (`symbol`),
110-
and returns the location in memory of that symbol. Returns `C_NULL` on failure.
111-
112-
See also: `StaticTools.dlopen`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
113-
114-
## Examples
115-
```julia
116-
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
117-
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
118-
119-
julia> fp = StaticTools.dlsym(lib, c"time")
120-
Ptr{Nothing} @0x00007fffa773dfa4
121-
122-
julia> dltime() = @ptrcall fp()::Int
123-
dltime (generic function with 1 method)
124-
125-
julia> dltime()
126-
1654320146
127-
128-
julia> StaticTools.dlclose(lib)
129-
0
130-
```
131-
"""
132-
@inline dlsym(handle::Ptr{DYLIB}, symbol::AbstractMallocdMemory) = dlsym(handle, pointer(symbol))
133-
@inline dlsym(handle::Ptr{DYLIB}, symbol) = GC.@preserve symbol dlsym(handle, pointer(symbol))
134-
@inline function dlsym(handle::Ptr{DYLIB}, symbol::Ptr{UInt8})
135-
Base.llvmcall(("""
136-
; External declaration of the dlsym function
137-
declare i8* @dlsym(i8*, i8*)
138-
139-
define i64 @main(i64 %jlh, i64 %jls) #0 {
140-
entry:
141-
%handle = inttoptr i64 %jlh to i8*
142-
%symbol = inttoptr i64 %jls to i8*
143-
%fp = call i8* (i8*, i8*) @dlsym(i8* %handle, i8* %symbol)
144-
%jlfp = ptrtoint i8* %fp to i64
145-
ret i64 %jlfp
146-
}
147-
148-
attributes #0 = { alwaysinline nounwind ssp uwtable }
149-
""", "main"), Ptr{Nothing}, Tuple{Ptr{DYLIB}, Ptr{UInt8}}, handle, symbol)
150-
end
151-
152-
## --- dlclose
153-
154-
"""
155-
```julia
156-
dlclose(lib::Ptr{DYLIB})
157-
```
158-
Libc `dlclose` function, accessed by direct StaticCompiler-safe `llvmcall`.
159-
160-
Close a shared library `lib` given a pointer (handle) previously obtained from
161-
`StaticTools.dlopen`.
162-
163-
See also: `StaticTools.dlopen`, `StaticTools.dlsym`, `StaticTools.@ptrcall`
164-
165-
## Examples
166-
```julia
167-
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
168-
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
169-
170-
julia> fp = StaticTools.dlsym(lib, c"time")
171-
Ptr{Nothing} @0x00007fffa773dfa4
172-
173-
julia> dltime() = @ptrcall fp()::Int
174-
dltime (generic function with 1 method)
175-
176-
julia> dltime()
177-
1654320146
178-
179-
julia> StaticTools.dlclose(lib)
180-
0
181-
```
182-
"""
183-
@inline function dlclose(handle::Ptr{DYLIB})
184-
Base.llvmcall(("""
185-
; External declaration of the dlclose function
186-
declare i32 @dlclose(i8*)
187-
188-
define i32 @main(i64 %jlh) #0 {
189-
entry:
190-
%handle = inttoptr i64 %jlh to i8*
191-
%status = call i32 (i8*) @dlclose(i8* %handle)
192-
ret i32 %status
193-
}
194-
195-
attributes #0 = { alwaysinline nounwind ssp uwtable }
196-
""", "main"), Int32, Tuple{Ptr{DYLIB}}, handle)
197-
end
19822

19923
## -- Macro for calling function pointers (as obtained from e.g. dlsym) via llvm
20024

src/llvmlibc.jl

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,4 +589,184 @@ end
589589
# Convenient parsing for argv (slight type piracy)
590590
@inline Base.parse(::Type{T}, argv::Ptr{Ptr{UInt8}}, n::Integer) where {T} = parse(T, MallocString(argv, n))
591591

592+
## --- dlopen
593+
594+
const RTLD_LOCAL = Int32(1)
595+
const RTLD_GLOBAL = Int32(2)
596+
const RTLD_LAZY = Int32(4)
597+
const RTLD_NOW = Int32(8)
598+
599+
"""
600+
```julia
601+
dlopen(name::AbstractString, flag=RTLD_LOCAL|RTLD_LAZY)
602+
```
603+
Libc `dlopen` function, accessed by direct `llvmcall`.
604+
605+
Returns a handle (pointer) to a `.so`/`.dylib` shared library specified by
606+
`name` opened with the mode or combination of modes specified by `flag`.
607+
Returns `C_NULL` on failure. Valid modes include:
608+
609+
Required:
610+
611+
`RTLD_LOCAL` (default): Symbols will not be made available for subsequently loaded libraries. The opposite of `RTLD_GLOBAL`.
612+
613+
`RTLD_GLOBAL`: Symbols will be made available for subsequently loaded libraries. The opposite of `RTLD_LOCAL`.
614+
615+
Optional:
616+
617+
`RTLD_LAZY` (default): Lazy binding: only resolve symbols as the code that references them is executed. The opposite of `RLTD_NOW`.
618+
619+
`RTLD_NOW`: Eager binding: resolve all symbols before `dlopen` returns. The opposite of `RTLD_LAZY`
620+
621+
Modes from the two categories can be combined with bitwise `or` (`|`)
622+
623+
See also: `StaticTools.dlsym`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
624+
625+
## Examples
626+
```julia
627+
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
628+
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
629+
630+
julia> fp = StaticTools.dlsym(lib, c"time")
631+
Ptr{Nothing} @0x00007fffa773dfa4
632+
633+
julia> dltime() = @ptrcall fp()::Int
634+
ctime (generic function with 1 method)
635+
636+
julia> dltime()
637+
1654320146
638+
639+
julia> StaticTools.dlclose(lib)
640+
0
641+
```
642+
"""
643+
@inline dlopen(name::AbstractMallocdMemory, flag=RTLD_LOCAL|RTLD_LAZY) = dlopen(pointer(name), flag)
644+
@inline dlopen(name, flag=RTLD_LOCAL|RTLD_LAZY) = GC.@preserve name dlopen(pointer(name), flag)
645+
@inline function dlopen(name::Ptr{UInt8}, flag::Int32)
646+
Base.llvmcall(("""
647+
; External declaration of the dlopen function
648+
declare i8* @dlopen(i8*, i32)
649+
650+
define i64 @main(i64 %jlname, i32 %flag) #0 {
651+
entry:
652+
%name = inttoptr i64 %jlname to i8*
653+
%fp = call i8* (i8*, i32) @dlopen(i8* %name, i32 %flag)
654+
%jlfp = ptrtoint i8* %fp to i64
655+
ret i64 %jlfp
656+
}
657+
658+
attributes #0 = { alwaysinline nounwind ssp uwtable }
659+
""", "main"), Ptr{DYLIB}, Tuple{Ptr{UInt8}, Int32}, name, flag)
660+
end
661+
662+
@static if Sys.isapple()
663+
const DLEXT = c".dylib"
664+
elseif Sys.iswindows()
665+
const DLEXT = c".dll"
666+
else
667+
const DLEXT = c".so"
668+
end
669+
670+
## --- dylsym
671+
672+
"""
673+
```julia
674+
dlsym(lib::Ptr{DYLIB}, symbol::AbstractString)
675+
```
676+
Libc `dlsym` function, accessed by direct StaticCompiler-safe `llvmcall`.
677+
678+
Takes a handle (`lib`) to a `.so`/`.dylib` shared library previously opened with
679+
`StaticTools.dlopen`, along with a null-terminated symbol name string (`symbol`),
680+
and returns the location in memory of that symbol. Returns `C_NULL` on failure.
681+
682+
See also: `StaticTools.dlopen`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
683+
684+
## Examples
685+
```julia
686+
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
687+
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
688+
689+
julia> fp = StaticTools.dlsym(lib, c"time")
690+
Ptr{Nothing} @0x00007fffa773dfa4
691+
692+
julia> dltime() = @ptrcall fp()::Int
693+
dltime (generic function with 1 method)
694+
695+
julia> dltime()
696+
1654320146
697+
698+
julia> StaticTools.dlclose(lib)
699+
0
700+
```
701+
"""
702+
@inline dlsym(handle::Ptr{DYLIB}, symbol::AbstractMallocdMemory) = dlsym(handle, pointer(symbol))
703+
@inline dlsym(handle::Ptr{DYLIB}, symbol) = GC.@preserve symbol dlsym(handle, pointer(symbol))
704+
@inline function dlsym(handle::Ptr{DYLIB}, symbol::Ptr{UInt8})
705+
Base.llvmcall(("""
706+
; External declaration of the dlsym function
707+
declare i8* @dlsym(i8*, i8*)
708+
709+
define i64 @main(i64 %jlh, i64 %jls) #0 {
710+
entry:
711+
%handle = inttoptr i64 %jlh to i8*
712+
%symbol = inttoptr i64 %jls to i8*
713+
%fp = call i8* (i8*, i8*) @dlsym(i8* %handle, i8* %symbol)
714+
%jlfp = ptrtoint i8* %fp to i64
715+
ret i64 %jlfp
716+
}
717+
718+
attributes #0 = { alwaysinline nounwind ssp uwtable }
719+
""", "main"), Ptr{Nothing}, Tuple{Ptr{DYLIB}, Ptr{UInt8}}, handle, symbol)
720+
end
721+
722+
# Return default handle to what Julia has already dlopened, for interactive use
723+
jl_RTLD_DEFAULT_handle() = @externload jl_RTLD_DEFAULT_handle::Ptr{DYLIB}
724+
725+
## --- dlclose
726+
727+
"""
728+
```julia
729+
dlclose(lib::Ptr{DYLIB})
730+
```
731+
Libc `dlclose` function, accessed by direct StaticCompiler-safe `llvmcall`.
732+
733+
Close a shared library `lib` given a pointer (handle) previously obtained from
734+
`StaticTools.dlopen`.
735+
736+
See also: `StaticTools.dlopen`, `StaticTools.dlsym`, `StaticTools.@ptrcall`
737+
738+
## Examples
739+
```julia
740+
julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
741+
Ptr{StaticTools.DYLIB} @0x000000010bf49b78
742+
743+
julia> fp = StaticTools.dlsym(lib, c"time")
744+
Ptr{Nothing} @0x00007fffa773dfa4
745+
746+
julia> dltime() = @ptrcall fp()::Int
747+
dltime (generic function with 1 method)
748+
749+
julia> dltime()
750+
1654320146
751+
752+
julia> StaticTools.dlclose(lib)
753+
0
754+
```
755+
"""
756+
@inline function dlclose(handle::Ptr{DYLIB})
757+
Base.llvmcall(("""
758+
; External declaration of the dlclose function
759+
declare i32 @dlclose(i8*)
760+
761+
define i32 @main(i64 %jlh) #0 {
762+
entry:
763+
%handle = inttoptr i64 %jlh to i8*
764+
%status = call i32 (i8*) @dlclose(i8* %handle)
765+
ret i32 %status
766+
}
767+
768+
attributes #0 = { alwaysinline nounwind ssp uwtable }
769+
""", "main"), Int32, Tuple{Ptr{DYLIB}}, handle)
770+
end
771+
592772
## ---

test/testllvminterop.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171

7272
## --- @externptr / @externload
7373

74+
@test Ptr{Nothing}(StaticTools.jl_RTLD_DEFAULT_handle()) != C_NULL
75+
7476
if Sys.isapple()
7577
foo() = @externload __stderrp::Ptr{UInt8}
7678
else

0 commit comments

Comments
 (0)