首页 > 代码库 > Ubuntu 16.04下使用gcc输出汇编的.0文件为可执行文件时出现:`_start'被多次定义

Ubuntu 16.04下使用gcc输出汇编的.0文件为可执行文件时出现:`_start'被多次定义

错误如下:

`_start‘被多次定义/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0x0):第一次在此定义/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:在函数‘_start’中:(.text+0x20):对‘main’未定义的引用collect2: error: ld returned 1 exit status

问题分析:

可以看到错误信息提示,提到了一个“crt1.o”这个文件,其中crt是“C runtime library”的缩写,其含义是“C运时库”。

C运行时库除了给我们提供必要的库函数调用(如memcpy、printf、malloc等)之外,它提供的另一个最重要的功能是为应用程序添加启动函数。C运行时库启动函数的主要功能为进行程序的初始化,对全局变量进行赋初值,加载用户程序的入口函数。

从给出的错误提示信息中还可以得知,在crt1.o中,有一个名为“_start”的函数。现在网上找到一份crt1.o的伪代码: 

    section .text:    __start:         :     init stack;     init heap;     open stdin;     open stdout;     open stderr;     :     push argv;     push argc;     call _main; (调用 main)     :     destory heap;     close stdin;     close stdout;     close stderr;     :     call __exit;

从伪代码可以看出,在这个_start函数中,调用了main函数。那么我们可以去修改入口函数,把入口函数改成junco。

执行下面的命令:

gcc 1.c -e junco -nostartfiles

其中-e选项为修改函数的入口地址。-e指的就是entrance。这里把entrance指定为junco函数。-nostartfiles选项的作用是通知编译器不自动加入启动函数以及别的库级别的初始化,这样就不会调用到crt1.o中的_start函数。

 

参考:

http://blog.sina.com.cn/s/blog_76a864e20101ehtp.html(以上问题分析来自此篇文章,但是是讲C语言的,而上面的方法也同样适用汇编)

Ubuntu 16.04下使用gcc输出汇编的.0文件为可执行文件时出现:`_start'被多次定义