fix Issue 14555 - ModuleInfo should weakly link against classes#4638
fix Issue 14555 - ModuleInfo should weakly link against classes#4638MartinNowak wants to merge 2 commits intodlang:masterfrom
Conversation
|
What a pity for the time spent on maintaining an outdated backend. Ironically now that weak external symbols work it turns out that weak linking imported ModuleInfo (here) doesn't work. |
|
Correction, I do know why it works on Win32, b/c we're skipping weak external definitions there too. |
|
A solution would be to emit an undefined external reference to the ModuleInfo into every multiobj, that way the ModuleInfo get dragged into any binary that uses part of a module. |
|
Requires dlang/druntime#1265. |
|
I think this approach will unfortunately break many uses of Object.factory. I imagine that most of its use case is about instantiating classes that are never otherwise referenced. Question, can we instead create a separate ModuleInfo-like construct just for Object.factory, which is only pulled in if Object.factory is called anywhere in the program, and otherwise GC'd by the linker? |
Yeah, it might cause some trouble. The main use-case for Object.factory is instantiating classes based on runtime data though. And already today you can only load classes whose modules are linked.
Pretty difficult because the use of Object.factory is separate from the classes, maybe by emitting a special section that is only referenced by the factory. GCing a reference to a class after the class already has been dragged into the binary doesn't GC that class IIRC. |
That's what I meant (I think).
Let's see, as I understand we have: ModuleInfo.localClasses -> ClassInfo.vtbl <-> virtual method table -> virtual method bodies -> ... Which of these are emitted in their own section? |
Most of them are in a separate object files (dmd's -lib switch outputs multilibs) except for ClassInfo and vtable. |
|
So I guess that will need to be fixed. The |
|
Let's deprecate the current Object.factory functionality and only make sure that every linked class is contstructable. This change can be accompanied with a warning and fallback to the old solution for some time. |
|
How do you plan on making Object.factory know about the classes that have been "linked in"? Weak references to all ClassInfos? Aren't those arranged in a linked list right now? |
Not since the big ModuleInfo rewrite for proper shared library support. |
|
As the title of this PR says "ModuleInfo should weakly link against classes". |
- can't use weak linkage for ModuleInfo b/c of ctors/dtors
|
Note that Object.factory already doesn't work when the ModuleInfo is missing, i.e. b/c a module doesn't have a constructor and wasn't explicitly linked as object into the binary. |
|
rebased and fixed test |
Derp, thanks. Tests are still failing: |
We cannot remove |
These classes depend on other non-classes phobos stuff, so in the end you'll end up pulling most of phobos into every executable. On my linux machine this increases the size of a empty main-function program from 500kB to 8,9MB. It also means you'll have to always link all libraries included by ping @andralex @WalterBright |
|
The best solution to this is to only pay the cost of |
|
Can we just check if |
|
Can we have an option to specify by name which classes can be constructed via |
|
Is Benjamin Thaut on github so we can ask him? |
|
I don't see how we can do this for static libraries w/o resorting to custom linker scripts, only referenced object files will end up in a binary but the compiler doesn't necessarily know all classes. |
See the proposed deprecation #4638 (comment). |
Yeah, I've seen that. I don't agree that it should be deprecated.
It can if the compiler outputs the all the necessary data. |
|
With time, it has become increasingly clear to me that Jacob, can you describe your use case? Is there something non-obvious that's preventing migrating your code away from the built-in |
I use it in my serialization library. |
So... does that mean that I can feed any program that uses your serialization library a blob of serialized data, which would cause the program to instantiate an arbitrary class anywhere in the program (incl. private classes)? If so, honestly, I think that only proves my point. |
|
There are many languages that allow you do to this. |
|
Indeed: https://www.google.com/search?q=ruby+serialization+vulnerability Again, proving my point. |
|
You can do a lot of stupid things in many ways in many programming languages, what's your point? |
|
BTW, I forgot that my serialization library is driven by static typing. That is, it will only try to deserialize the types you give it. Example: class Foo
{
int a;
int b;
}
class Bar
{
Foo foo;
}
auto bar = deserialize!(Bar)(data);The above code can only deserialize |
That
Then why do you even need |
That's a good point 😃, I need to check. |
|
Currently it needs that due to how it's designed. The deserializer has the static type but not the unarchiver. The (un)archiver is format (XML, JSON) dependent and the (de)serializer is not. The (un)archiver is polymorphic and therefore cannot have any templated methods. But maybe I can move the instantiation of the object to the deserializer instead. |
|
From your description, it sounds like you could also make the deserializer On Sep 23, 2016 19:41, "jacob-carlborg" notifications@github.com wrote:
|
Yes, I already have something similar, the library requires to register sub classes that should be (de)serialized through a base class reference. I should be able to construct the actual instance using the same mechanism. |
|
As this is still based on the C++ frontend, it might take a serious effort to revive it. |
61 line changes is nothing. |
|
(I just did a swipe through the PR queue to make sure that these instructions are easily accessible. Maybe I should have used a better text. Sorry) |
No description provided.