View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000469 | file | General | public | 2023-08-03 14:31 | 2023-08-05 14:40 |
Reporter | joveler | Assigned To | christos | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | x86, x64, arm64 | OS | Windows 10 | OS Version | 22H2 |
Product Version | 5.45 | ||||
Fixed in Version | HEAD | ||||
Summary | 0000469: dllexport keyword required for building Win32 DLL | ||||
Description | [*] Main issue In Windows, compiled libmagic-1.dll exports too many/empty function symbols. - MSYS2 MinGW-w64: Exports 134 functions - llvm-mingw: Exports 0 functions libmagic does not define any visibility keywords in Win32 builds. As a solution, `file_public` macro must be defined as `__declspec(dllexport)` in Win32. After the patch, clang-compiled libmagic-1.dll contains an almost correct export function table. - llvm-mingw: Exports 20 functions [*] Symbol export visibility issue In POSIX GCC, symbol export visibility is controlled by `__attribute__ ((__visibility__(...)))` keyword. - `__attribute__ ((__visibility__("default")))`: Always export function symbol. - `__attribute__ ((__visibility__("hidden")))`: Must not export symbol. - No Keyword: Decided by compiler policy. In Win32 MSVC, symbol export visibility is more strict. - `__declspec(dllexport)`: Expose function symbol to export table (EAT) - No keyword: Always prevent symbol from being exposed to EAT In MSYS2 MinGW-w64 or llvm-mingw, they have a relaxed policy on the `No Keyword` case. It is because they try to replicate POSIX behavior to some degree. - Latest MSYS2 MinGW-w64 has been exposing every function, at least in `libmagic-1.dll`. - Latest llvm-mingw follows MSVC policy, hiding every function symbol. - llvm-mingw had the same policy as MinGW-w64, but it seems to be changed in 2023. In Windows, all libmagic functions were built without any visibility keyword. Thus MinGW-w64 build is exposing symbols that should have been hidden, like `file_apprentice`. LLVM/Clang build is not exposing any symbols. [*] Solution `__attribute__ ((__visibility__("default")))` and `__declspec(dllexport)` keywords are equivalent. And many other cross-platform libraries are mapping these two. I tested `__declspec(dllexport)` keyword in the Win32 build, and got llvm-mingw working. However, MinGW-w64 still exposes all functions. It would need more investigation. In the meantime, the attached patch will solve the issue at least on LLVM/Clang. The patch uses `WIN32` macro to detect Windows environment because existing code uses it. It may be changed to other macros, such as `__MINGW32__`. | ||||
Steps To Reproduce | [Reproduce Instructions for Windows] 1. Install MSYS2, and download llvm-mingw, and radare2 from its GitHub page. 2. Unpack file-5.45-Win32-reproduce.tar.xz 3. Run `libmagic-msys2.sh` in MSYS2 shell, for example: $ ./libmagic-msys2.sh -t /c/Tools/llvm-mingw-20230614-ucrt-x86_64 -a x86_64 /c/Build/file-5.45 4. Check EAT of `build-x86_64\libmagic-1.dll`. It can be done with radare2: > C:\radare2\bin\r2 build-x86_64\libmagic-1.dll > [0xYYYYYYYY]> is~ 5. Apply `Win32_visibility_dllexport.diff` patch, and retry compiling. | ||||
Additional Information | I have attached lists of exported functions on Linux/Win32 binaries. Look through `symbols_results.zip`. | ||||
Tags | EAT, export, MinGW, Win32 | ||||
|
Win32_visibility_dllexport.diff (781 bytes)
diff --git a/src/file.h b/src/file.h index 2e0494d..a811d8d 100644 --- a/src/file.h +++ b/src/file.h @@ -107,11 +107,18 @@ #define file_private static -#if HAVE_VISIBILITY && !defined(WIN32) -#define file_public __attribute__ ((__visibility__("default"))) -#ifndef file_protected -#define file_protected __attribute__ ((__visibility__("hidden"))) -#endif +#if HAVE_VISIBILITY + #if defined(WIN32) + #define file_public __declspec(dllexport) + #ifndef file_protected + #define file_protected + #endif + #else + #define file_public __attribute__ ((__visibility__("default"))) + #ifndef file_protected + #define file_protected __attribute__ ((__visibility__("hidden"))) + #endif + #endif #else #define file_public #ifndef file_protected |
|
Applied, thanks! |
Date Modified | Username | Field | Change |
---|---|---|---|
2023-08-03 14:31 | joveler | New Issue | |
2023-08-03 14:31 | joveler | Tag Attached: EAT | |
2023-08-03 14:31 | joveler | Tag Attached: export | |
2023-08-03 14:31 | joveler | Tag Attached: MinGW | |
2023-08-03 14:31 | joveler | Tag Attached: Win32 | |
2023-08-03 14:31 | joveler | File Added: symbols_results.zip | |
2023-08-03 14:31 | joveler | File Added: Win32_visibility_dllexport.diff | |
2023-08-03 14:31 | joveler | File Added: file-5.45-Win32-reproduce.tar.xz | |
2023-08-05 14:40 | christos | Assigned To | => christos |
2023-08-05 14:40 | christos | Status | new => assigned |
2023-08-05 14:40 | christos | Status | assigned => resolved |
2023-08-05 14:40 | christos | Resolution | open => fixed |
2023-08-05 14:40 | christos | Fixed in Version | => HEAD |
2023-08-05 14:40 | christos | Note Added: 0003972 |