Do not hybrid compile and link source code by using VC and GCC!
来源:互联网 发布:linux svn 新建仓库 编辑:程序博客网 时间:2024/05/29 18:05
Do not hybrid compile and link sourcecode by using VC and GCC!
GCC owns cross-compiling abilities in Windows. Thenormal environment is MinGW or Cygwin. This article focuses on the MinGW, andothers are similar with it.
If comparing with the calling convention of VC, GCChas some gaps in the environment of MinGW/Cygwin. The program will be crashedif SSEx instructions are adopted in the source coded built by GCC, however theyare linked with VC. It is a common case, such as many open source codes are portedfrom Linux.
To ease to understand these serious risks, thearticle will set about an example. If readers follow it step by step, theresult will become obvious.
Preface:
1. foo_gcc.c/foo_gcc.h is compiled by GCC.
2. foo_vc_call_gcc.c is compiled by VC.
C Source codes:
1. foo_gcc.h/c
Header file
Source code
#ifndef _FOO_GCC_H
#define _FOO_GCC_H
#if defined( __cplusplus ) || defined( c_plusplus )
extern "C" {
#endif
#ifdef BUILD_DLL
#define GCC_API __declspec( dllexport )
#else
#define GCC_API __declspec( dllimport )
#endif
GCC_API int foo_gcc( int i );
#if defined( __cplusplus ) || defined( c_plusplus )
}
#endif
#endif
#include "foo_gcc.h"
GCC_API int foo_gcc( int i )
{
char unused[ 16 ] __attribute__ ((__aligned__ ( 16 )));
__asm__ __volatile__( "movdqa %%xmm0, %0/n/t" : "=m"(unused) );
return i * i;
}
2. foo_vc_call_gcc.c
#include "foo_gcc.h"
int foo_vc( int i )
{
__declspec( align( 16 ) ) char unused[ 16 ];
_asm
{
lea esi, unused
movdqa xmm0, xmmword ptr[ esi ]
}
i = foo_gcc( i );
return i * i;
}
int main( void )
{
foo_vc( 10 );
return 0;
}
Compile
A bash file aconvenient for this boring task, and please refer it herein.
#!/bin/sh
rm ./foo_gcc.o
rm ./foo_gcc.dll
rm ./foo_gcc.s
rm ./foo_gcc.lib
rm ./libfoo_gcc.a
rm ./foo_gcc.exp
rm ./foo_gcc.def
gcc -S ./foo_gcc.c
gcc -c -O3 -DBUILD_DLL ./foo_gcc.c
gcc -shared -o ./foo_gcc.dll ./foo_gcc.o -Wl,--out-implib,./libfoo_gcc.a
pexports.exe ./foo_gcc.dll > ./foo_gcc.def
lib /machine:i386 /def:foo_gcc.def /out:foo_gcc.lib
rm ./foo_vc_call_gcc.obj
rm ./foo_vc_call_gcc.asm
rm ./foo_vc_call_gcc.exe
cl -Fa -O2 ./foo_vc_call_gcc.c ./foo_gcc.lib
Reader can referto Howto use GCC to build DLL by DEF file in MinGW? and How togenerate DLL files by GCC in the MinGW? articles to build DLL by GCC inMinGW.
Execute
$ ./foo_vc_call_gcc.exe
What will behappened? I think that the program will be crashed in your system, right?!
Herein, you maybe wonder why?????? Please keep patience! It is an issue of the callingconvention. Before making it clear, the source codes of ASM must beinvestigated.
Root cause
1. foo_gcc.s
Foo_gcc.s
.file "foo_gcc.c"
.text
.globl _foo_gcc
.def _foo_gcc; .scl 2; .type 32; .endef
_foo_gcc:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
/APP
# 7 "./foo_gcc.c" 1
movdqa %xmm0, -24(%ebp)
# 0 "" 2
/NO_APP
movl 8(%ebp), %eax
imull 8(%ebp), %eax
leave
ret
A. eax is used totransfer parameter. It is __stdcall calling function of DLL.
B. eax is used toreturn value.
C. GCC uses static strategy toalign stack if SSEx instructions are used. The AMS marked by red color showsthe rule(32bytes = 4bytes (returning address) + 4bytes (save ebp) + 24bytes).It hits that the esp must be aligned when invoking foo_gcc function.
2. foo_vc_call_gcc.asm
foo_icl_call_gcc.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.42
TITLE c:/temp/risks/foo_vc_call_gcc.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC __$ArrayPad$
PUBLIC _foo_vc
EXTRN __imp__foo_gcc:PROC
EXTRN ___security_cookie:DWORD
EXTRN @__security_check_cookie@4:PROC
; Function compile flags: /Ogtpy
; COMDAT _foo_vc
_TEXT SEGMENT
_unused$ = -32 ; size = 16
__$ArrayPad$ = -4 ; size = 4
_i$ = 8 ; size = 4
_foo_vc PROC ; COMDAT
; File c:/temp/risks/foo_vc_call_gcc.c
; Line 4
push ebp
mov ebp, esp
and esp, -16 ; fffffff0H
sub esp, 44 ; 0000002cH
mov eax, DWORD PTR ___security_cookie
xor eax, esp
mov DWORD PTR __$ArrayPad$[esp+44], eax
push esi
; Line 9
lea esi, DWORD PTR _unused$[esp+48]
; Line 10
movdqa xmm0, XMMWORD PTR [esi]
; Line 12
mov eax, DWORD PTR _i$[ebp]
push eax
call DWORD PTR __imp__foo_gcc
; Line 14
imul eax, eax
; Line 15
mov ecx, DWORD PTR __$ArrayPad$[esp+52]
add esp, 4
pop esi
xor ecx, esp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
_foo_vc ENDP
_TEXT ENDS
PUBLIC __$ArrayPad$
PUBLIC _main
; Function compile flags: /Ogtpy
; COMDAT _main
_TEXT SEGMENT
_unused$699 = -32 ; size = 16
__$ArrayPad$ = -4 ; size = 4
_main PROC ; COMDAT
; Line 18
push ebp
mov ebp, esp
and esp, -16 ; fffffff0H
sub esp, 44 ; 0000002cH
mov eax, DWORD PTR ___security_cookie
xor eax, esp
mov DWORD PTR __$ArrayPad$[esp+44], eax
push esi
; Line 19
lea esi, DWORD PTR _unused$699[esp+48]
movdqa xmm0, XMMWORD PTR [esi]
push 10 ; 0000000aH
call DWORD PTR __imp__foo_gcc
; Line 22
mov ecx, DWORD PTR __$ArrayPad$[esp+52]
add esp, 4
pop esi
xor ecx, esp
xor eax, eax
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
A. Stack is usedto transfer parameter.
B. eax is used toreturn value.
C. Dynamically align the address ofstack. “and esp, -16” equals “and esp, 0xFFFFFFF0”, and it makes address aligned by16bytes. However, when invoking foo_gcc function, the esp does not been aligned((44 + 4 + 4) % 16 = 4, they are marked by red color). The operations will leadto faults of SSEx instruction, and the symptom is that program is crashed inthe runtime.
Summarization:
1. The callingconvention among compilers has gaps, and it will lead to crash if SSExinstructions are adopted.
2. It is a commonissue, so all compilers compatible with VC have same results.
3. If thefunctions using SSEx instructions are not APIs of DLL, maybe the program can berun. In fact, it depends on the optimizing method of GCC. The risks are big!
- Do not hybrid compile and link source code by using VC and GCC!
- GCC Compile and Link options
- Dowload and compile android source code implemented by qualcomm
- gstreamer source code compile and install
- Compile and build specific Hadoop source code branch using Azure VM
- NASM Intro - Compile and Link
- Using Eclipse to compile Android source code
- python source compile and upgrade
- Minimize Code by Using jQuery and Data Templates
- Hybrid application using QML and Qt C++
- 编译和链接(compile and link)
- Visual Studio Compile and Link error LNK2005
- Numbers of source Raster bands and source color space components do not match异常的处理
- How to compile and debug VLC player source code in eclipse IDE on Ubuntu 10.04 (lucid)?
- How to compile and debug VLC player source code in eclipse IDE on Ubuntu 10.04 (lucid)
- Source Code Tags and Builds
- Compile and install GCC in home directory
- Hadoop: Compile and Run URLCat example code
- Ycnd核心模块已可以支持多种语言!
- 运输层
- ejb3 in action Chapter1、2 读书笔记
- 到计时关闭窗口
- select * from sp_who的解决方案
- Do not hybrid compile and link source code by using VC and GCC!
- JNDI 在 J2EE 中的角色
- Shell 基本语法
- ___记住应该要记住,忘记应该忘记的!
- 敏捷:系统测试的噩梦? zz
- BSP树--制作3D Engine
- How to update YASM from 0.7.2 to 0.8.0 in MinGW?
- Shell程序设计的流程控制
- eclipse contentassist快捷键