hcq0411 发表于 2008-03-25 21:20

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...

cjaizss 发表于 2008-03-29 09:49

ld script

bamu1984 发表于 2008-03-30 19:16

ld 的操作单位是section,因为重定位的时候也是按section来的,而不是按照 function, 那么太麻烦了。 如非要给一个函数单独排,可以使用 attribute 语法将函数放到一个特定的section中,然后去排这个section 就可以了

everytime 发表于 2008-03-31 01:37

实验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:

cjaizss 发表于 2008-03-31 12:42

确实也只能曲线救国,呵呵

dxcnjupt 发表于 2008-03-31 16:21

C语言可以把所有的执行代码分成一个个的函数.
到汇编层就做不到了.
汇编(或者说机器码)不是基于函数的语言.
汇编器没有办法区分普通的标号和函数名,也没办法识别函数体.
直接做是不可能的,如果要求gcc做这样的识别,倒是有可能做到.

曲线救国........好名字
页: [1]
查看完整版本: why ld accepts a single .o as the least unit for linking?