[RFC PATCH 0/5] XAudio PE conversion.
Zebediah Figura (she/her)
zfigura at codeweavers.com
Fri Sep 3 14:11:02 CDT 2021
On 9/3/21 12:02 PM, Alexandre Julliard wrote:
> "Zebediah Figura (she/her)" <zfigura at codeweavers.com> writes:
>
>> On 9/3/21 3:26 AM, Alexandre Julliard wrote:
>>> "Zebediah Figura (she/her)" <zfigura at codeweavers.com> writes:
>>>
>>>> Actually, an alternate solution occurred to me:
>>>>
>>>> If we are loading any library that is a dependency of a builtin
>>>> library, always load it from a fixed path like /usr/lib/wine/ext/, and
>>>> essentially treat it as if we had loaded using an absolute path
>>>> instead of a relative path, so as to skip existing DLLs loaded under
>>>> that name.
>>>>
>>>> Mark that DLL with an internal flag, and don't consider it when
>>>> searching for existing DLLs with that name, to avoid the other side.
>>>>
>>>> I know there are a lot of other things standing in the way of shared
>>>> libraries, and that this would require some nontrivial loader work,
>>>> but does it at least seem plausible? Are there snags I'm not noticing?
>>> Sure, you can try to create a separate namespace for these without
>>> actually changing their names. It's not clear to me how you are going to
>>> determine which DLLs should go into that namespace, and how that's going
>>> to work with apps that do import resolving by hand.
>>> You'll also have to invent some mechanism to have Wine treat them as
>>> builtins even though they don't have the builtin flag.
>>
>> The distinguishing factor I was thinking of is that if it's a system
>> lib or linked to by a system lib, it's marked as a system lib. That
>> doesn't work for libraries loaded dynamically, and there we have the
>> extra caveat that we don't want to mark every dynamically loaded
>> library as a system lib, so I think we'd need an internal flag to
>> LoadLibraryExW().
>
> I don't see how this would work. All such libraries will import msvcrt
> or kernel32, but you can't have these end up in a separate namespace.
>
> And how do you define a "system lib"? Do you somehow tell the PE loader
> the actual Unix path that the dll was loaded from? What if the distro
> installs the Wine DLLs in the same dir?
>
>>> And somehow you
>>> need to differentiate them from the exact same DLLs being shipped by an
>>> app...
>>
>> Sorry, I'm not sure what you mean by this, that's different from what
>> I described above?
>
> Well, you'll need to copy, say, zlib1.dll into the prefix. How do you
> know this is the zlib1.dll from the system package, and not one
> installed by an app? Do you add the builtin flag, altering the binary
> when copying it?
>
I did fail to consider that case, thanks.
After thinking about it for a while I've come up with the following
algorithm:
Suppose that module A imports module B.
1. If module A is marked "builtin" or "system":
a. Try to find a module marked "builtin" or "system" in memory, and
return it if found. (Skip "builtin" if the load order requires.)
b. Try to load a module from WINESYSTEMDLLDIR#. If found, mark the
module as "system".
c. Try to find a module marked "native" in memory, and return it if
found. (Skip this step if the load order requires.)
d. Try to load a builtin or native module using the normal logic.
2. Otherwise, i.e. module A is native:
a. Try to find a module marked "builtin" or "native" (modulo load
order) in memory, and return it if found. Skip "system".
b. Try to load a builtin or native module using the normal logic.
This should avoid ever loading a system module for a native module; it
should avoid loading a native module when we want a system module
(provided that system modules are present; if they aren't things are
already broken). It should also handle e.g. ucrtbase imports, regardless
if ucrtbase is builtin or native.
The downside I can see is that if ucrtbase is native, we'll always
search WINESYSTEMDLLDIRs for it. If that's a performance problem, we
could always bypass step 1b for a predefined list of modules.
This does rely on the fact that WINESYSTEMDLLDIRs are unique and only
contain system libraries. It's not obvious to me that would be a problem
to guarantee. The list might contain one or more paths like:
* C:/windows/system32/wine-ext/ [1]
* Z:/usr/x86_64-w64-mingw32/bin/ [2]
* Z:/usr/lib/wine/ext/
I'm sure this all looks like a pile of hacks. Granted, it doesn't look
unreasonable to me, but I suppose I'm also biased. I'm just trying my
best to make dynamic libraries a possibility, because static libraries
suck for development. And, more importantly, I'm trying to give
distributions an accurate representation of our requirements.
[1] As far as I'm aware, the only reason we need to copy libraries to
the C: drive is that anticheats *might* complain if libraries are loaded
from another drive? Was there a concrete example of this? Or was there
another problem I was missing?
[2] Or distribution equivalent. That's assuming that distributions are
in favor of having us dynamically link to pre-built libraries, though,
and that's an open question. It's also not clear how we would get this path.
More information about the wine-devel
mailing list