Closed eliottness closed 1 year ago
This should be easy to implement. Given an empty string purego pass a null pointer. However, I think it's important to decide if the feature is needed. Have you noticed a bottleneck caused when searching for shared objects? Each feature has a cost so it's important to make sure we are okay with paying it.
think it's important to decide if the feature is needed
I see 2 advantages over some other methods to perform symbol lookup on already loaded symbols.
The edge this technique has over a usual dlopen("libc.so.6")
is the ability to be agnostic of the library name. For example if we already know that the libc (or its equivalent on other platform) is loaded in some way or another, we can be pretty sure that dlsym(RTLD_DEFAULT, "strlen")
will succeed.
The edge this method has over go:cgo_import_dynamic
is the ability to perform logic on the symbol lookup. For example if the symbol "strnlen" cannot be found, we fallback on "strlen".
This should be easy to implement. Given an empty string purego pass a null pointer
Concerning the implementation I was more inclined to add a new function to the api. Something like this:
func DefaultDSO() (uintptr, error) {
u, _, _ := SyscallN(dlopenABI0, 0, uintptr(RTLD_GLOBAL)) // mode does not impact the behaviour
if u == 0 {
return 0, Dlerror{fnDlerror()}
}
return u, nil
}
Do tell me if you have a better idea for the name of the function or its implementation @TotallyGamerJet
Have you noticed a bottleneck caused when searching for shared objects?
No, this issue is not about performances but about being feature-complete regarding what libdl
has to offer.
I looked up the Posix spec. And it says that RTLD_DEFAULT is used in dlsym like your example. I think adding that constant for use in purego.Dlsym is fine. Why do you prefer DefaultDSO
over matching the C API?
Why do you prefer DefaultDSO over matching the C API?
Indeed, the ideal case is to directly run dlsym(RTLD_DEFAULT, "strlen")
, directly skipping any call to dlopen
. The initial issue is the following:
the macro RTLD_DEFAULT which not accessible from go code obviously and is implementation defined
Since the value of RTLD_DEFAULT is implementation defined, you can be sure this value will change over time and over distros. And I already know some older musl versions have a different value than the glibc. Which themselves have a different value that on darwin. Sure RTLD_DEFAULT is the matching C API, and would obviously be better, but in this case I do not see how we could manage to pull this off. @TotallyGamerJet
Since the value of RTLD_DEFAULT is implementation defined, you can be sure this value will change over time and over distros.
I don't think it is the case that it will change and be different across distros. The value must be the same for each dynamic linker. AFAIK, there is only one on Linux. As for the value being different on Darwin that is fine since purego already uses build tags to separate Linux and Darwin constants.
I looked it up and glibc and musl have the same value ((void *)0)
. This further supports my claim that it is the same for all Linux systems. Plus, if the value did change all existing C programs would break bc they would be providing the wrong value.
I feel that you understood my concern. If you think that’s fine then I am also fine with it. I’ve done the PR
As per the man page,
dlopen(NULL)
is supposed to return the equivalent of the macroRTLD_DEFAULT
which not accessible from go code obviously and is implementation defined. This function is especially useful to run already loaded symbols like the ones loaded with the pragmago:cgo_import_dynamic
.But since we pass a string to Dlopen, a nil value cannot be passed as parameter. How could we give access to this feature ?