develooper Front page | perl.perl5.porters | Postings from July 2013

Mingw 3.4.5 distributed by AS PPM randomly creates DLLs that SEGVin DllMain

From:
bulk88
Date:
July 11, 2013 03:24
Subject:
Mingw 3.4.5 distributed by AS PPM randomly creates DLLs that SEGVin DllMain
Message ID:
BLU0-SMTP432FCCF98BE6C600A37F810DF7B0@phx.gbl
This post will be cross posted on different mailing lists.

The Mingw 3.4.5 ("gcc version 3.4.5 (mingw-vista special r3)") 
distributed by AS's PPM as MinGW-5.1.4.1.tar.gz on a Win 7 machine 
(other OSes not tested) randomly creates XS DLLs which can not be 
LoadLibrary()ed. LoadLibrary returns 998 ERROR_NOACCESS "Invalid access 
to memory location". This causes a certain CPANTesters smoker to 
randomly return reports like 
http://www.cpantesters.org/cpan/report/7ba97b19-75dd-1014-9f60-dcb4233f278b 
and
http://www.cpantesters.org/cpan/report/4f0e57f8-6e7f-1014-b513-ef14947b1b84 
(the site is down, I can't check the contents of those links) 
http://www.perlmonks.org/?node_id=1003763 .

The ERROR_NOACCESS is caused by "call 0" in the assembly in 
__w32_eh_shared_initialize() which is called from the GCC supplied 
DllMain. __w32_eh_shared_initialize comes inlined into 
__w32_sharedptr_initialize which comes from libgcc.a with the mingw 
compiler tarball. The call 0 is caused by the GCC linker. The call asm 
opcode should be to memset. The memset appears as normal in the import 
table of broken DLL, but there are no references to it in the DLL from a 
asm viewpoint. The memset jmp opcode thunk is missing. The jmp thunks 
are present for other c std lib functions from msvcrt.dll. In every 
broken DLL, the access vio will happen at the exact same line of C code, 
the memset in __w32_eh_shared_initialize.

An asm dump/C debugger view of the problem 
http://tinypic.com/view.php?pic=2mqmhvk&s=5.

_______________________________________________________
61BC2197 FF 15 04 71 BC 61 call        dword ptr ds:[61BC7104h]
61BC219D 0F B7 C0         movzx       eax,ax
61BC21A0 83 EC 04         sub         esp,4
61BC21A3 85 C0            test        eax,eax
61BC21A5 0F 85 71 01 00 00 jne         61BC231C
61BC21AB C7 04 24 54 00 00 00 mov         dword ptr [esp],54h
61BC21B2 E8 91 FD FF FF   call        61BC1F48
61BC21B7 85 C0            test        eax,eax
61BC21B9 89 C3            mov         ebx,eax
61BC21BB 0F 84 8F 01 00 00 je          61BC2350
61BC21C1 89 04 24         mov         dword ptr [esp],eax
61BC21C4 31 C9            xor         ecx,ecx
61BC21C6 BE 54 00 00 00   mov         esi,54h
61BC21CB 89 4C 24 04      mov         dword ptr [esp+4],ecx
61BC21CF 89 74 24 08      mov         dword ptr [esp+8],esi
61BC21D3 E8 28 DE 43 9E   call        00000000
61BC21D8 C7 43 04 68 23 BC 61 mov         dword ptr [ebx+4],61BC2368h
61BC21DF B9 01 00 00 00   mov         ecx,1
61BC21E4 C7 43 08 40 20 BC 61 mov         dword ptr [ebx+8],61BC2040h
_______________________________________________________

If you look at the opcode at 0x61BC21D3, take its 32 bit LE offset, and 
do the math, the offset is to NULL, (0x61BC21D3 + 0x9E43DE28 + 0x4) % 
0xFFFFFFFF = 0x0

Only certain functions will cause it, and they cause it on 100% of 
compiles if the functions appear in the DLL. So far, my research shows 
that DebugBreak, CloseHandle and ReadProcessMemory from kernel32.dll 
will cause broken DLLs. Win32::API, Win32API::File, and 
Win32::Process::Memory are affected.

The Mingw 3.4.5 vista special r3 included with strawberry perl (SP) 
5.8.9 has never generated such DLLs for me. The libkernel32.a files have 
the exact same length between Strawberry Perl GCC and ActiveState (AS) 
GCC, 657818 bytes long, but different crc32 checksums of the 2 lib 
files. Using dlltool included with AS GCC and a .def I made my own 
libkernl32.a, then compiled the DLL again using the AS GCC, the memset 
worked and the DLL loaded into the process uneventfully ("perl -MWin32 
-e"print(Win32::LoadLibrary('./blib/arch/auto/Win32/Process/Memory/Memory.dll').\" 
\".($^E+0));""). Using MSVC dumpbin on AS libkernel32.a and SP 
libkernel32.a and then doing a diff between the 2 textual dumps, shows 
the AS libkernel32.a has archive/section(right term IDK) COFF flag of "2 
byte align" or "4 byte align", flags 0x200000 and 0x300000 on nearly all 
or all, COFF sections in the lib. SP libkernel32.a does not have these 
align flags. I am attached a rar of the patch file showing the 
difference. I did not use dumpbin on my DIY libkernel32.a.

IDK where AS got their libkernel32.a from, and why it is not checksum 
identical to the SP libkernel32.a when both GCC compilers call 
themselves "gcc version 3.4.5 (mingw-vista special r3)", and I assume 
came from the same tarball from mingw.org.

-V of the Perl being used
_______________________________________________________
Summary of my perl5 (revision 5 version 16 subversion 0) configuration:

  Platform:
    osname=MSWin32, osvers=5.2, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='C:/Perl16/site/bin/gcc.exe', ccflags ='-DNDEBUG -DWIN32 
-D_CONSOLE -DNO_STRICT -DPERL_TEXTMODE_SCRIPTS -DUSE_SITECUSTOMIZE 
-DPERL_IMPLICIT_CONTEXT -DPER
L_IMPLICIT_SYS -DUSE_PERLIO -D_USE_32BIT_TIME_T -DHASATTRIBUTE 
-fno-strict-aliasing -mms-bitfields',
    optimize='-O2',
    cppflags='-DWIN32'
    ccversion='', gccversion='3.4.5 (mingw-vista special r3)', 
gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=8
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', 
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='C:\Perl16\site\bin\g++.exe', ldflags ='-L"C:\Perl16\lib\CORE"'
    libpth=\lib
    libs=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 
-lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm 
-lversion -lodbc32 -
lodbccp32 -lcomctl32 -lmsvcrt
    perllibs=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 
-ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr 
-lwinmm -lversion -lodbc
32 -lodbccp32 -lcomctl32 -lmsvcrt
    libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl516.lib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-mdll -L"C:\Perl16\lib\CORE"'


Characteristics of this binary (from libperl):
  Compile-time options: HAS_TIMES HAVE_INTERP_INTERN MULTIPLICITY
                        PERLIO_LAYERS PERL_DONT_CREATE_GVSV
                        PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
                        PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PL_OP_SLAB_ALLOC
                        USE_ITHREADS USE_LARGE_FILES USE_LOCALE
                        USE_LOCALE_COLLATE USE_LOCALE_CTYPE
                        USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF
                        USE_SITECUSTOMIZE
  Locally applied patches:
        ActivePerl Build 1600 [295879]
  Built under MSWin32
  Compiled at Jun 11 2012 12:43:38
  @INC:
    C:/Perl16/site/lib
    C:/Perl16/lib
    .
_______________________________________________________

So what can ActiveState do about the old Mingw they distribute or does 
anyone have ideas on how to fix this linker bug as an XS author or Perl 
level without getting a new/upgraded Mingw distro?



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About