您的位置:首页 > 其它

不同操作系统下的程序入口点分析

2011-08-22 10:05 459 查看
转自 http://hi.baidu.com/liu_bin0101/blog/item/03e3a9ec4e0fd5d72e2e21b9.html
程序入口与编译器没有什么关系, 关键是链接链接器(UNIX的用的ld和WINDOWS下用的LINK.EXE)

ld 用参数-e entry参数指定程序入口为entry

LINK.EXE 用/ENTRY:symbol指定程序入口为symbol

通常, ld/LINK.EXE 不是被直接运行的, 而是由编译器用适当的参数去调用的.

C/C++编译器的完成编译之后会用适当的参数去调用ld/LINK.EXE告诉链接器程序的入口.

WINDOWS下VC编译的程序程序入口点是WinMainCRTStartup(/SUBSYSTEM:WINDOWS, WIN32 GUI 程序)或mainCRTStartup(/SUBSYSTEM:CONSOLE 即WIN32控制台程序).

UNIX下cc/gcc设置的缺省程序入口是_start.

不论是WinMainCRTStartup, mainCRTStartup还是_start, 在链接器生成可执行程序之后, 入口点信息都保存在可执行文件中了.

WinMainCRTStartup, mainCRTStartup或_start函数都是由C标准库实现的, 这些里面通常做一些初始化工作, 包括一些需要用汇编语言才能完成的工作, 然后调用的main函数(WIN32 GUI 程序是WinMain).

这个过程可以用一个例子来说明, 下面是FreeBSD 6.2 的libc的crt1.c, 里面有_start函数的实现:

C/C++ code
/* LINTLIBRARY */
/*-
* Copyright 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef lint
#ifndef __GNUC__
#error "GCC is needed to compile this file"
#endif
#endif /* lint */

#include <stdlib.h>

#include "libc_private.h"
#include "crtbrand.c"

extern int _DYNAMIC;
#pragma weak _DYNAMIC

typedef void (*fptr)(void);

extern void _fini(void);
extern void _init(void);
extern int main(int, char **, char **);
extern void _start(char *, ...);

#ifdef GCRT
extern void _mcleanup(void);
extern void monstartup(void *, void *);
extern int eprol;
extern int etext;
#endif

char **environ;
const char *__progname = "";

static __inline fptr
get_rtld_cleanup(void)
{
fptr retval;

#ifdef  __GNUC__
__asm__("movl %%edx,%0" : "=rm"(retval));
#else
retval = (fptr)0; /* XXXX Fix this for other compilers */
#endif
return(retval);
}

/* The entry function. */
void
_start(char *ap, ...)
{
fptr cleanup;
int argc;
char **argv;
char **env;
const char *s;

#ifdef __GNUC__
__asm__("and $0xfffffff0,%esp");
#endif
cleanup = get_rtld_cleanup();
argv = ≈
argc = *(long *)(void *)(argv - 1);
env = argv + argc + 1;
environ = env;
if (argc > 0 && argv[0] != NULL) {
__progname = argv[0];
for (s = __progname; *s != '\0'; s++)
if (*s == '/')
__progname = s + 1;
}

if (&_DYNAMIC != NULL)
atexit(cleanup);
else
_init_tls();

#ifdef GCRT
atexit(_mcleanup);
#endif
atexit(_fini);
#ifdef GCRT
monstartup(&eprol, &etext);
#endif
_init();
exit( main(argc, argv, env) );
}

#ifdef GCRT
__asm__(".text");
__asm__("eprol:");
__asm__(".previous");
#endif

__asm__(".ident\t\"$FreeBSD: src/lib/csu/i386-elf/crt1.c,v 1.14 2005/05/19 07:36:07 dfr Exp $\"");

至于楼主想知道的"如何让没有main函数的C程序变成可执行文件?"
涉及到自己链接给链接程序传参数, 有一个例子可以试试.

C/C++ code
/*-
* name: entry_start.c
* auth: mymtom
* date: 2008-02-18
*/

#include <unistd.h>
#include <string.h>

void
_start(void)
{
(void)write(1, __func__, strlen(__func__));
(void)write(1, "\n", 1);
_exit(0);
}


这个程序在FreeBSD 6.2 和Fedora Core 6上可以用下面的命令编译, 也可以运行.

gcc -c entry_start.c

ld -o entry_start -static -e _start entry_start.o -lc

但是在运行Loongson Debian Linux V4.0的龙芯福珑迷你(龙芯2E处理器)的机器上会core dump,

原因应该是没有初始化C运行环境而调用了C库函数引起的. 毕竟这不是写C程序的正规方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息