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?
-
Mingw 3.4.5 distributed by AS PPM randomly creates DLLs that SEGVin DllMain
by bulk88