Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 23177 - ModuleInfo is not exported on Windows #14200

Merged
merged 3 commits into from
Jun 12, 2022

Conversation

rikkimax
Copy link
Contributor

I'm first only adding the test for this to ensure it does in fact break what I think it breaks, then I'll push the fix (which I expect to be a one liner).

@dlang-bot
Copy link
Contributor

dlang-bot commented Jun 11, 2022

Thanks for your pull request and interest in making D better, @rikkimax! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
23177 blocker ModuleInfo is not exported on Windows

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "stable + dmd#14200"

@rikkimax
Copy link
Contributor Author

Welp I've messed up something to do with bugzilla referencing.

Link: https://issues.dlang.org/show_bug.cgi?id=23177

@rikkimax rikkimax changed the title Fix issue 23177 - ModuleInfo is not exported on Windows Fix Issue 23177 - ModuleInfo is not exported on Windows Jun 11, 2022
@dkorpel
Copy link
Contributor

dkorpel commented Jun 11, 2022

Welp I've messed up something to do with bugzilla referencing.

You can git commit --amend your commit message to contain "fix issue 23177" and the bot will pick it up. It doesn't recognize issue23177 without a space.

@rikkimax
Copy link
Contributor Author

Welp I've messed up something to do with bugzilla referencing.

You can git commit --amend your commit message to contain "fix issue 23177" and the bot will pick it up. It doesn't recognize issue23177 without a space.

The fix is coming next, as soon as I make Windows fail the CI, so I'll word it like that, thanks!

@rikkimax
Copy link
Contributor Author

Windows except for OMF has failed the CI. This is what I was wanting to see, pushing fix now.

@rikkimax
Copy link
Contributor Author

Good news and bad news.

Good news: this PR is doing what I set out to do!

Bad news: The test runner is not aware of import and export library generation and is causing failures because MSVC linker is writing a message i.e. Creating library {{RESULTS_DIR}}\runnable\test11934_0.lib and object {{RESULTS_DIR}}\runnable\test11934_0.exp.

@rikkimax
Copy link
Contributor Author

Unfortunately, the test runner is going to have to be linker aware of this particular message.

Otherwise, we are going to need to make the tests themselves aware of linkers (which is far worse).

I don't think there is any way around this. MSVC linker just doesn't let you disable this message and export tables need to be used far more heavily with D if we want decent shared library support.

2022-06-11T18:09:25.6870465Z TARGET FAILED: runnable\testTypePropAsm.d
2022-06-11T18:09:25.6871269Z >>> TARGET FAILED: runnable\testUTF32.d
2022-06-11T18:09:25.6872024Z >>> TARGET FAILED: runnable\testv.d
2022-06-11T18:09:25.6872715Z >>> TARGET FAILED: runnable\testxmm.d
2022-06-11T18:09:25.6873483Z >>> TARGET FAILED: runnable\testxmm2.d
2022-06-11T18:09:25.6874598Z >>> TARGET FAILED: runnable\test_dip1006.d
2022-06-11T18:09:25.6876755Z >>> TARGET FAILED: runnable\test_dip1006b.d
2022-06-11T18:09:25.6877634Z >>> TARGET FAILED: runnable\test_dip1006c.d
2022-06-11T18:09:25.6878455Z >>> TARGET FAILED: runnable\tls.d
2022-06-11T18:09:25.6879205Z >>> TARGET FAILED: runnable\traits_child.d
2022-06-11T18:09:25.6880099Z >>> TARGET FAILED: runnable\traits_getUnitTests.d
2022-06-11T18:09:25.6880996Z >>> TARGET FAILED: runnable\traits_getVirtualIndex.d
2022-06-11T18:09:25.6881866Z >>> TARGET FAILED: runnable\traits_getPointerBitmap.d
2022-06-11T18:09:25.6882758Z >>> TARGET FAILED: runnable\tuple_default_parameters.d
2022-06-11T18:09:25.6883914Z >>> TARGET FAILED: runnable\traits_initSymbol.d
2022-06-11T18:09:25.6884787Z >>> TARGET FAILED: runnable\uda.d
2022-06-11T18:09:25.6886911Z >>> TARGET FAILED: runnable\ufcs.d
2022-06-11T18:09:25.6887614Z >>> TARGET FAILED: runnable\unique_typeinfo_names.d
2022-06-11T18:09:25.6888431Z >>> TARGET FAILED: runnable\uniformctor.d
2022-06-11T18:09:25.6889393Z >>> TARGET FAILED: runnable\version.d
2022-06-11T18:09:25.6890166Z >>> TARGET FAILED: runnable\variadic.d
2022-06-11T18:09:25.6890899Z >>> TARGET FAILED: runnable\warning1.d
2022-06-11T18:09:25.6891617Z >>> TARGET FAILED: runnable\untag.d
2022-06-11T18:09:25.6892345Z >>> TARGET FAILED: runnable\wc.d
2022-06-11T18:09:25.6893096Z >>> TARGET FAILED: runnable\wc2.d
2022-06-11T18:09:25.6894285Z >>> TARGET FAILED: runnable\xdtor.d
2022-06-11T18:09:25.6896013Z >>> TARGET FAILED: runnable\whetstone.d
2022-06-11T18:09:25.6897509Z >>> TARGET FAILED: runnable\xpostblit.d
2022-06-11T18:09:25.6898304Z >>> TARGET FAILED: runnable\wc3.d
2022-06-11T18:09:25.6899097Z >>> TARGET FAILED: runnable\xtest47.d
2022-06-11T18:09:25.6900037Z >>> TARGET FAILED: runnable\xtestenum.d
2022-06-11T18:09:25.6900855Z >>> TARGET FAILED: runnable\xtest55.d
2022-06-11T18:09:25.6901644Z >>> TARGET FAILED: runnable\testpdb.d
2022-06-11T18:09:25.6903386Z >>> TARGET FAILED: compilable\needsmod.d
2022-06-11T18:09:25.6904632Z >>> TARGET FAILED: compilable\needsmods.d
2022-06-11T18:09:25.6906793Z >>> TARGET FAILED: compilable\needspkg.d
2022-06-11T18:09:25.6907692Z >>> TARGET FAILED: compilable\needspkgmod.d
2022-06-11T18:09:25.6908495Z >>> TARGET FAILED: compilable\noreturn_main.d
2022-06-11T18:09:25.6909306Z >>> TARGET FAILED: compilable\test14198.d
2022-06-11T18:09:25.6910092Z >>> TARGET FAILED: compilable\test14954.d
2022-06-11T18:09:25.6910885Z >>> TARGET FAILED: compilable\test20653.d
2022-06-11T18:09:25.6911650Z >>> TARGET FAILED: compilable\test21299a.d
2022-06-11T18:09:25.6912499Z >>> TARGET FAILED: compilable\test21299b.d
2022-06-11T18:09:25.6913317Z >>> TARGET FAILED: compilable\test21299d.d
2022-06-11T18:09:25.6914478Z >>> TARGET FAILED: compilable\test318.d
2022-06-11T18:09:25.6916598Z >>> TARGET FAILED: compilable\vastartend.c
2022-06-11T18:09:25.6917455Z >>> TARGET FAILED: dshell\test9377.d
2022-06-11T18:09:25.6918186Z >>> TARGET FAILED: dshell\sameenv.d

@rikkimax rikkimax force-pushed the fix23177 branch 2 times, most recently from 4474626 to 677b882 Compare June 11, 2022 19:33
@rikkimax
Copy link
Contributor Author

I don't know how to solve this:

Test 'runnable\testmodule.d' failed. The logged output:
D:\a\1\s\generated\windows\release\64\dmd.exe -conf= -m64 -Irunnable -odD:\a\1\s\test\test_results\runnable -ofD:\a\1\s\test\test_results\runnable\testmodule_0.exe runnable\testmodule.d

Creating library D:\a\1\s\test\test_results\runnable\testmodule_0.lib and object D:\a\1\s\test\test_results\runnable\testmodule_0.exp

testmodule_0.exp : error LNK2001: unresolved external symbol _D3run17unicode_06_哪里12__ModuleInfoZ

Hint on symbols that are defined and could potentially match:

_D3run17unicode_06_哪里12__ModuleInfoZ

D:\a\1\s\test\test_results\runnable\testmodule_0.exe : fatal error LNK1120: 1 unresolved externals

@kinke
Copy link
Contributor

kinke commented Jun 11, 2022

I don't think there is any way around this.

There definitely is - LDC only exports the ModuleInfos with -fvisibility=public.

Note that the export is simple, but the accompanying dllimport is tricky for data symbols, especially if referenced in static data initializers (such as ModuleInfos in other binaries referencing dllimported ones). LDC emits a CRT constructor to 'relocate' these manually at startup. For some context, see

@rikkimax
Copy link
Contributor Author

I don't think there is any way around this.

There definitely is - LDC only exports the ModuleInfos with -fvisibility=public.

That comment was only about the message that MSVC linker emits to say that it is generating import and export files. Test suite was hard coded for one output, but it adds output, therefore failed.

I did solve it, via changing the test runners to remove the message (it does it for dmd already).

@kinke
Copy link
Contributor

kinke commented Jun 11, 2022

That comment was only about the message that MSVC linker emits to say that it is generating import and export files. Test suite was hard coded for one output, but it adds output, therefore failed.

I know, LDC had the same problem of course. But I don't think it's desirable to always export them (after all, the user sees the linker messages and extra files too), and DMD needs the -fvisibilityoption anyway sooner or later.

@rikkimax
Copy link
Contributor Author

Yeah, unfortunately, I'm at the end of what I can do.

Unless somebody tells me how to solve that latest problem, this PR is dead sadly.

@kinke
Copy link
Contributor

kinke commented Jun 11, 2022

This is apparently just some MS linker shortcoming that you're hitting now with the embedded /EXPORT directives. See https://github.com/ldc-developers/dmd-testsuite/blob/04d6f174b71032ea2e7ba96db81ed136e6eb1329/runnable/testmodule.d#L3-L7.

@rikkimax
Copy link
Contributor Author

This is apparently just some MS linker shortcoming that you're hitting now with the embedded /EXPORT directives. See https://github.com/ldc-developers/dmd-testsuite/blob/04d6f174b71032ea2e7ba96db81ed136e6eb1329/runnable/testmodule.d#L3-L7.

Excellent!

Thank you. I couldn't find this documented anywhere.

Now I can disable that test :D

richard andrew cattermole added 2 commits June 12, 2022 09:39
@thewilsonator thewilsonator merged commit ea3ebd6 into dlang:stable Jun 12, 2022
@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

@thewilsonator: Please revert. As the test adaptations clearly show, this shouldn't be done unconditionally!

@rikkimax
Copy link
Contributor Author

@thewilsonator: Please revert. As the test adaptations clearly show, this shouldn't be done unconditionally!

It wouldn't matter if we did revert it, the problem still remains.

We need to modify mangling so that Unicode will not be emitted for MSVC linker with extern(D).

runnable/testmodule.d is an incomplete test, dshell/dll should be including a similar module in its test, which would also not work right now.

I've already taken a look mangling code, it doesn't look like it's as simple as just turning on compression or something else, so it's out of my area to fix.

@rikkimax
Copy link
Contributor Author

I've found where in dmangle I would need to change, mangleIdentifier but I'm going to need somebody to tell me what to transform it into, e.g. hex.

@rikkimax
Copy link
Contributor Author

@rikkimax
Copy link
Contributor Author

If we can't find a way around the mangling issue, @kinke is right, we'll need to revert for our non-english speakers, I was wrong about that.

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

[I wasn't referring to the Unicode issue, but the unconditional export in general, see the revert PR above for rationale.]

I don't understand why the extended dshell/dll.d test works; AFAIU, that definitely shouldn't work via export only, but as stated above, the import needs much more work, including a runtime relocation. Have you checked whether the testdll.exe executable really does import ModuleInfos from the DLL?

@rikkimax
Copy link
Contributor Author

I don't understand why the extended dshell/dll.d test works; AFAIU, that definitely shouldn't work via export only, but as stated above, the import needs much more work, including a runtime relocation. Have you checked whether the testdll.exe executable really does import ModuleInfos from the DLL?

The CI was run with only the test change. It definitely was broken without the fix.

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

Yeah, but I meant checking the produced code, e.g., running dumpbin /imports testdll.exe to check whether ModuleInfos are actually imported.

@rikkimax
Copy link
Contributor Author

Yeah, but I meant checking the produced code, e.g., running dumpbin /imports testdll.exe to check whether ModuleInfos are actually imported.

Yeah you're asking for something a bit different than what I did. I left it to the linker/system linker to tell me if symbol X was missing. Rather than an explicit where it was referencing it (objdump failed on me to do this during my previous testing of shared library support).

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

I understand, and the added test should IMO cover the expected behavior just fine. But knowing the problems I had to tackle for this with LDC, I'm just wondering how on earth it can work, and expect some other problem to hide it. So I meant checking the .exe locally on your box with a DMD build, just for confirmation, not complicating the test itself (for now at least, as long as my suspicion hasn't been confirmed yet). And maybe checking that the exe doesn't export some stub or so itself (dumpbin /exports).

@rikkimax
Copy link
Contributor Author

Yeah, but I meant checking the produced code, e.g., running dumpbin /imports testdll.exe to check whether ModuleInfos are actually imported.

Okay this comment won't be helpful, as I'm going to need a patched copy of dmd for this. So I'll need to compile dmd with this PR.

P:\dub\test\issue2258-dynLib-exe-dep>P:\dub\bin\dub build --compiler=dmd
Performing "debug" build using dmd for x86_64.
dynlib-simple ~master: building configuration "library"...
Linking...
LINK : P:\dub\test\1-dynLib-simple\.dub\build\library-debug-windows-x86_64-dmd_v2.100.0-dirty-BD90D4AEA3A6133E914DFD91A3177610\dynlib-simple.dll not found or not built by the last incremental link; performing full link
   Creating library P:\dub\test\1-dynLib-simple\.dub\build\library-debug-windows-x86_64-dmd_v2.100.0-dirty-BD90D4AEA3A6133E914DFD91A3177610\dynlib-simple.lib and object P:\dub\test\1-dynLib-simple\.dub\build\library-debug-windows-x86_64-dmd_v2.100.0-dirty-BD90D4AEA3A6133E914DFD91A3177610\dynlib-simple.exp
dynlib-exe-dep ~master: building configuration "application"...
Linking...
dynlib-exe-dep.obj : error LNK2001: unresolved external symbol _D6dynlib3app12__ModuleInfoZ
.dub\build\application-debug-windows-x86_64-dmd_v2.100.0-dirty-DF15FC69DD8B01E023D4A031C979D5BD\dynlib-exe-dep.exe : fatal error LNK1120: 1 unresolved externals
Error: linker exited with status 1120
dmd failed with exit code 1.

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

So I'll need to compile dmd with this PR.

Yeah, I assumed you had one lying around anyway for local testing. :) - I can check it myself too, but can't promise when I find some time.

@rikkimax
Copy link
Contributor Author

Nah it's all good, I'll compile it.

I try to do as much leg work on these sorts of issues as I can, at the very least it means that somebody else doesn't have to do it and can read my failed attempts instead :)

@rikkimax
Copy link
Contributor Author

Ugh, this is going to take me longer than I was expecting.

https://github.com/CyberShadow/DustMite/issues/75

@rikkimax
Copy link
Contributor Author

rikkimax commented Jun 12, 2022

Output (ignoring Kernel32.dll, cos that won't be helpful):

P:\dub\test\issue2258-dynLib-exe-dep>dumpbin /imports dynlib-exe-dep.exe
Microsoft (R) COFF/PE Dumper Version 14.00.24210.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file dynlib-exe-dep.exe

File Type: EXECUTABLE IMAGE

  Section contains the following imports:

    dynlib-simple.dll
             14007F360 Import Address Table
             14007F768 Import Name Table
                     0 time date stamp
                     0 Index of first forwarder reference

                           0 _D6dynlib3app12__ModuleInfoZ
                           1 _D6dynlib3app5entryFZv

So yeah, it's emitting the reference into the imports @kinke.

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

Hmm. Please try this main() in the executable and see if you hit no access violation and sane output:

void main() {
    import std.stdio;
    foreach (m; ModuleInfo) {
        writeln(m.name);
        if (auto i = m.importedModules()) {
            foreach (j; i)
                writeln("  - ", j.name);
        }
    }
}

@rikkimax
Copy link
Contributor Author

Oh goodness, this really is far more broken than I thought.

void main() {
    import std.stdio;
    foreach (m; ModuleInfo) {
        writeln(m.name);
        if (auto i = m.importedModules()) {
            writeln(i);
            stdout.flush;
            foreach (j; i) {
                writeln("  - ", j.name.ptr);
                stdout.flush;
            }
        }
    }
}
P:\dub\test\issue2258-dynLib-exe-dep>P:\dub\bin\dub run --compiler=dmd
Performing "debug" build using dmd for x86_64.
dynlib-simple ~master: target for configuration "library" is up to date.
dynlib-exe-dep ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running dynlib-exe-dep.exe
app
[7FF60A21AC20, 7FF60A2A51D0, 7FF60A2A52B0, 7FF60A2A52F0, 7FF60A2A5320, 7FF60A2A5370]
Program exited with code -1073741819

@kinke
Copy link
Contributor

kinke commented Jun 12, 2022

Okay, finally. ;) - I guess the import lib contains some seemingly dangerous _D6dynlib3app12__ModuleInfoZ then, but it's not to be used; instead, the compiler should use *__imp__D6dynlib3app12__ModuleInfoZ then (dereferencing the import indirection), which requires a runtime relocation for static initializers and so the non-trivial stuff I linked to above. [With LDC, the executable needs to be compiled with -dllimport=all.]

@rikkimax
Copy link
Contributor Author

At least now we know for certain that it isn't just a simple fix of setting export on ModuleInfo.

In the meantime, I'm throwing some more code at the CI to try and solve the mangling issue. #14207

@rikkimax rikkimax deleted the fix23177 branch June 3, 2024 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants