why ld accepts a single .o as the least unit for linking?
eg:1.c contains:
main()
{
f1();
}
2.c contains:
f1(){}
f2(){}
gcc 1.c 2.c
a.out contains code segment from 2.o even though f2() is not invoked by main().
can ld accept a function or global variable as the least linking input unit?
thanks in advance and sorry for english, i can't type chinese now... ld script ld 的操作单位是section,因为重定位的时候也是按section来的,而不是按照 function, 那么太麻烦了。 如非要给一个函数单独排,可以使用 attribute 语法将函数放到一个特定的section中,然后去排这个section 就可以了 实验1:
filename: 1.c
extern int max(int x, int y);
int main()
{
max(1, 2);
return 0;
}
filename: 2.c
int max(int x, int y)
{
return (x)>(y)? (x): (y);
}
int min(int x, int y)
{
return (x)<(y)? (x): (y);
}
$ gcc -v 1.c 2.c
使用内建 specs。
目标:i386-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
线程模型:posix
gcc 版本 4.1.2 20070925 (Red Hat 4.1.2-33)
/usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 -quiet -v 1.c -quiet -dumpbase 1.c -mtune=generic -auxbase 1 -version -o /tmp/ccs4uRsk.s
忽略不存在的目录“/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include”
#include "..." 搜索从这里开始:
#include <...> 搜索从这里开始:
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/4.1.2/include
/usr/include
搜索列表结束。
GNU C 版本 4.1.2 20070925 (Red Hat 4.1.2-33) (i386-redhat-linux)
由 GNU C 版本 4.1.2 20070925 (Red Hat 4.1.2-33) 编译。
GGC 准则:--param ggc-min-expand=98 --param ggc-min-heapsize=128202
Compiler executable checksum: ab322ce5b87a7c6c23d60970ec7b7b31
as -V -Qy -o /tmp/ccGOPQ7x.o /tmp/ccs4uRsk.s
GNU assembler version 2.17.50.0.18 (i386-redhat-linux) using BFD version version 2.17.50.0.18-1 20070731
/usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 -quiet -v 2.c -quiet -dumpbase 2.c -mtune=generic -auxbase 2 -version -o /tmp/ccs4uRsk.s
忽略不存在的目录“/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../i386-redhat-linux/include”
#include "..." 搜索从这里开始:
#include <...> 搜索从这里开始:
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/4.1.2/include
/usr/include
搜索列表结束。
GNU C 版本 4.1.2 20070925 (Red Hat 4.1.2-33) (i386-redhat-linux)
由 GNU C 版本 4.1.2 20070925 (Red Hat 4.1.2-33) 编译。
GGC 准则:--param ggc-min-expand=98 --param ggc-min-heapsize=128202
Compiler executable checksum: ab322ce5b87a7c6c23d60970ec7b7b31
as -V -Qy -o /tmp/ccuRCiKK.o /tmp/ccs4uRsk.s
GNU assembler version 2.17.50.0.18 (i386-redhat-linux) using BFD version version 2.17.50.0.18-1 20070731
/usr/libexec/gcc/i386-redhat-linux/4.1.2/collect2 --eh-frame-hdr --build-id -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.. /tmp/ccGOPQ7x.o /tmp/ccuRCiKK.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o
$ objdump -j .text -S a.out >dump_file
......省略......
129 080483e9 <min>:
13080483e9: 55 push %ebp
13180483ea: 89 e5 mov %esp,%ebp
13280483ec: 83 ec 08 sub $0x8,%esp
13380483ef: 8b 45 08 mov 0x8(%ebp),%eax
13480483f2: 89 45 f8 mov %eax,-0x8(%ebp)
13580483f5: 8b 45 0c mov 0xc(%ebp),%eax
13680483f8: 89 45 fc mov %eax,-0x4(%ebp)
13780483fb: 8b 45 f8 mov -0x8(%ebp),%eax
13880483fe: 39 45 fc cmp %eax,-0x4(%ebp)
1398048401: 7e 06 jle 8048409 <min+0x20>
1408048403: 8b 45 f8 mov -0x8(%ebp),%eax
1418048406: 89 45 fc mov %eax,-0x4(%ebp)
1428048409: 8b 45 fc mov -0x4(%ebp),%eax
143804840c: c9 leave
实验2:
filename:1.c
extern int max(int x, int y);
int main()
{
max(1, 2);
return 0;
}
filename:2.c
int max(int x, int y)
{
return (x)>(y)? (x): (y);
}
filename:3.c
int min(int x, int y)
{
return (x)<(y)? (x): (y);
}
$ gcc -c 2.c 3.c
$ ar rcs libtest.a 2.o 3.o
$ gcc -c 1.c
$ gcc -static -o ldstudy 1.o libtest.a
$ objdump -j .text -S ldstudy >dump_file
不包含min()了
关于原因,请参考《深入理解计算机系统》7.6.3 链接器如何使用静态库来解析引用
今天晚上刚好看到这一章,还有很多问题不懂,囫囵吞枣中:em17: 确实也只能曲线救国,呵呵 C语言可以把所有的执行代码分成一个个的函数.
到汇编层就做不到了.
汇编(或者说机器码)不是基于函数的语言.
汇编器没有办法区分普通的标号和函数名,也没办法识别函数体.
直接做是不可能的,如果要求gcc做这样的识别,倒是有可能做到.
曲线救国........好名字
页:
[1]