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

gcc/g++ compiled 32 bits dll doesn't work #10

Closed
lifenjoiner opened this issue May 19, 2021 · 13 comments
Closed

gcc/g++ compiled 32 bits dll doesn't work #10

lifenjoiner opened this issue May 19, 2021 · 13 comments
Labels
building Build process issue

Comments

@lifenjoiner
Copy link
Contributor

The reason is that the exported stdcall function names contains @n suffixes. GetProcAddress on the origin function name does not work.
--kill-at: https://sourceware.org/binutils/docs/ld/Options.html

Patch:
Strip-stdcall-suffixes-from-exported-symbols-generated-by-MinGW-w64.zip

BTW:
Scintilla also needs it.

@nyamatongwe
Copy link
Member

gcc/g++ compiled Lexilla.dll does work. Its one of the most tested paths.

C:\u\hg\lexilla\bin>dumpbin /exports lexilla.dll
Microsoft (R) COFF/PE Dumper Version 14.28.29915.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file lexilla.dll

File Type: DLL

  Section contains the following exports for lexilla.dll

    00000000 characteristics
    60A58900 time date stamp Thu May 20 07:54:08 2021
        0.00 version
           1 ordinal base
           8 number of functions
           8 number of names

    ordinal hint RVA      name

          1    0 00001639 CreateLexer
          2    1 00001581 GetLexerCount
          3    2 00001618 GetLexerFactory
          4    3 000015A1 GetLexerName
          5    4 00001510 GetLibraryPropertyNames
          6    5 00001519 GetNameSpace
          7    6 0000169E LexerNameFromID
          8    7 00001518 SetLibraryProperty

@lifenjoiner
Copy link
Contributor Author

That's strange. Can you run TestLexers successfully? I can't.

Here is my screenshot:
TestLexers-Err

Due to GetProcAddress failure with mismatched function names:
stdcall-gcc-exports

Ref:
https://www.willus.com/mingw/yongweiwu_stdcall.html

@lifenjoiner
Copy link
Contributor Author

After testing x64 builds, I found that it doesn't have the @n suffixes.
So, striping the @n suffixes explicitly is required by i686 GCC.

@lifenjoiner lifenjoiner changed the title gcc/g++ compiled dll doesn't work gcc/g++ compiled 32 bits dll doesn't work May 22, 2021
@rdipardo
Copy link
Contributor

rdipardo commented May 22, 2021

Here is my screenshot:
TestLexers-Err

Check the line endings of the *.properties files in the test/example directory:

     git ls-files --eol test/examples/*.properties

I've noticed that TestLexers will fail to parse *.properties files when they have CRLF line endings on a Unix platform such as MSYS2 (as I see in the title bar of your capture). This could happen if you cloned the source with a Windows git client, then compiled in a MSYS2 session. Here's a demonstration using WSL:

rob@AcerNotebook:/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla (master=)
$ uname -a
Linux AcerNotebook 4.4.0-19041-Microsoft #488-Microsoft Mon Sep 01 13:43:00 PST 2020 x86_64 x86_64 x86_64 GNU/Linux

rob@AcerNotebook:/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla (master=)
$ git ls-files --eol test/examples/*.properties
i/lf    w/crlf  attr/text               test/examples/batch/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/cpp/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/d/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/errorlist/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/fsharp/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/hypertext/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/julia/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/latex/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/lua/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/makefile/SciTE.properties
i/-text w/-text attr/text               test/examples/markdown/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/mmixal/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/nim/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/perl/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/python/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/raku/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/ruby/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/tcl/SciTE.properties
i/lf    w/crlf  attr/text               test/examples/vb/SciTE.properties

rob@AcerNotebook:/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla (master=)
$ cd src && make
g++ -DNDEBUG -I ../include -I ../../scintilla/include -I ../src -I ../lexlib -fvisibility=hidden --std=c++17 -fPIC -Os -Wpedantic -Wall -Wextra   -c Lexilla.cxx -o Lexilla.o
[ . . . ]
ranlib ../bin/liblexilla.a

rob@AcerNotebook:/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla/src (master=)
$ cd ../test && make test
g++ -DNDEBUG -I ../../scintilla/include -I ../include -I ../access --std=c++2a -Os -Wpedantic -Wall -Wextra   -c TestLexers.cxx -o TestLexers.o
g++ -DNDEBUG -I ../../scintilla/include -I ../include -I ../access --std=c++2a -Os -Wpedantic -Wall -Wextra   -c TestDocument.cxx -o TestDocument.o
g++ -DNDEBUG -I ../../scintilla/include -I ../include -I ../access --std=c++2a -Os -Wpedantic -Wall -Wextra   -c ../access/LexillaAccess.cxx -o LexillaAccess.o
g++ --std=c++2a -Os -Wpedantic -Wall -Wextra   TestLexers.o TestDocument.o LexillaAccess.o -ldl  -o TestLexers
./TestLexers
Found Lexilla at /mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla
Lexing batch/x.bat

/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla/test/examples/batch/x.bat:1: has no lexer

Lexing cpp/Bug2245.cxx

/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla/test/examples/cpp/Bug2245.cxx:1: has no lexer

Lexing cpp/x.cxx

/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla/test/examples/cpp/x.cxx:1: has no lexer

Lexing d/x.d

/mnt/c/Users/Rob/source/git/scintilla-contrib/lexilla/test/examples/d/x.d:1: has no lexer
[ . . . ]
make: *** [makefile:55: test] Error 1

As a guess, the fault could lie with TestLexers.cxx calling std:getline on the *.properties files without taking the system's line delimiter into account:

std::map<std::string, std::string> PropertiesFromFile(std::filesystem::path path) {
std::map<std::string, std::string> m;
std::ifstream ifs(path);
std::string line;
std::string logicalLine;
while (std::getline(ifs, line)) {

nyamatongwe added a commit that referenced this issue May 22, 2021
@nyamatongwe
Copy link
Member

Added a chomp after the getline with 3377db1.

@lifenjoiner
Copy link
Contributor Author

@rdipardo Thanks for you help.

  1. I think you also generated export function names with @n suffixes.
  2. Here you use nmake. Are you using GCC? Which version? I used (MSYS2 + )i686-GCC (10.2.0 as the screenshot shows).
    1 0 00001705 CreateLexer = _CreateLexer@4 shows it exported both _CreateLexer@4 and CreateLexer. You can also observe it with VS shipped depends.exe or other PE tools.
  3. I debugged the TestLexers.exe with x32dbg, and found GetProcAddress fails with return value 0 (NULL). And with --kill-at linking option, it works well.
    CreateLexerFn fnCL = FunctionPointer<CreateLexerFn>(
    FindSymbol(lexillaDL, LEXILLA_CREATELEXER));
    LexerNameFromIDFn fnLNFI = FunctionPointer<LexerNameFromIDFn>(
    FindSymbol(lexillaDL, LEXILLA_LEXERNAMEFROMID));
    GetLibraryPropertyNamesFn fnGLPN = FunctionPointer<GetLibraryPropertyNamesFn>(
    FindSymbol(lexillaDL, LEXILLA_GETLIBRARYPROPERTYNAMES));
    SetLibraryPropertyFn fnSLP = FunctionPointer<SetLibraryPropertyFn>(
    FindSymbol(lexillaDL, LEXILLA_SETLIBRARYPROPERTY));
    GetNameSpaceFn fnGNS = FunctionPointer<GetNameSpaceFn>(
    FindSymbol(lexillaDL, LEXILLA_GETNAMESPACE));

And please refer to ld Options Specific to i386 PE Targets. It says "--kill-at is specific to the i386 PE targeted port of the linker". It could be a reason with this option there.

BTW:
I use Git for Windows which does the \r\n and \r conversion automatically.
I'm using Windows 10 20H2.

@lifenjoiner
Copy link
Contributor Author

Actually, CALLING_CONVENTION is not necessary for Windows.

EXPORT_FUNCTION Scintilla::ILexer5 * CALLING_CONVENTION CreateLexer(const char *name) {

#define CALLING_CONVENTION __stdcall

Different types of functions calling are recognized/converted while compiling/linking with header files declaring.

ILexer5 * LEXILLA_CALL CreateLexer(const char *name);

#define LEXILLA_CALL __stdcall

The saying "The __stdcall calling convention is used to call Win32 API functions" is for WINAPI which is used by Windows OS APIs, not requiring all to adopt it, I think, just default __cdecl works well.

@lifenjoiner
Copy link
Contributor Author

lifenjoiner commented May 23, 2021

Here I added a CI testing file: lifenjoiner@a2c7523
As windir in makefile doesn't work with MSYS2, it just uses mingw32-make.

You can see the failure: https://github.com/lifenjoiner/lexilla/runs/2648803500
Only mingw32-LEXILLA_SHARED testing fails.

@lifenjoiner
Copy link
Contributor Author

lifenjoiner commented May 23, 2021

@nyamatongwe
Copy link
Member

Actually, CALLING_CONVENTION is not necessary for Windows.

A different calling convention would work but its necessary to have both the library and caller use the same calling convention so its specified. Since x64 has a common calling convention, you don't see failures there but on x86 calling convention mismatches can cause crashes.

ILexer uses stdcall as stdcall is used for COM and interfaces like ILexer are similar to COM. Then, for consistency, the external lexer interface was stdcall as well. Lexilla extends the external lexer interface and it would be inconsistent for the new functions to use a different calling convention.

@lifenjoiner
Copy link
Contributor Author

Anyway, problems are there: reported, reproduced, proved, and patches provided. Also #6. I have finished my work.

nyamatongwe added a commit that referenced this issue May 27, 2021
@nyamatongwe
Copy link
Member

clang is using Microsoft link which doesn't like --kill-at so there is an additional condition in
9e60005

@nyamatongwe nyamatongwe added the building Build process issue label May 27, 2021
@nyamatongwe
Copy link
Member

Closed as change included in 5.0.3 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
building Build process issue
Projects
None yet
Development

No branches or pull requests

3 participants