Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104953
  • 博文数量: 11
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 172
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-17 09:26
文章分类
文章存档

2009年(11)

我的朋友

分类: C/C++

2009-05-10 16:17:45

C源程序->预编译处理(.c)->编译、优化程序(.s)->汇编程序(.o)->链接程序(ELF)
接下来就以hello world为例进行说明。

  1 #include <stdio.h>
  2 int main(void)
  3 {
  4   printf("hello ubuntu.\n");
  5   return 0;
  6 }

arm-linux-gcc -o helloworld helloworld.c
利用-v选项我们可以清楚的看到编译过程:
arm-linux-gcc -v -o helloworld helloworld.c

Reading specs from /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/specs Configured with:

/home/bigtree/embedded/tools/crosstool-0.43/build/arm-linux/gcc-3.4.5-glibc-2.3.6/gcc-3.4.5/configure

 --target=arm-linux

 --host=i686-host_pc-linux-gnu

 --prefix=/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux

--with-float=soft

 --with-headers=/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux/include

 --with-local-prefix=/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux

 --disable-nls

 --enable-threads=posix

 --enable-symvers=gnu

 --enable-__cxa_atexit

 --enable-languages=c,c++

 --enable-shared

 --enable-c99

 --enable-long-long

Thread model: posix

 gcc version 3.4.5

 /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/libexec/gcc/arm-linux/3.4.5/cc1 -quiet -v -D__ARM_ARCH_3__ helloworld.c -quiet -dumpbase helloworld.c -msoft-float -auxbase helloworld -version -o /tmp/ccaykq0x.s

#include "..." search starts here:

#include <...> search startshere:

 /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/include

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/sys-include

 /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/include

End of search list.

GNU C version 3.4.5 (arm-linux) compiled by GNU C version 4.2.4 (Ubuntu 4.2.4-1ubuntu4).

GGC heuristics: --param ggc-min-expand=62 --param ggc-min-heapsize=60367 /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/bin/as -mfpu=softfpa -o /tmp/cccj0q5Z.o /tmp/ccaykq0x.s

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/libexec/gcc/arm-linux/3.4.5/collect2

 --eh-frame-hdr

 -dynamic-linker

 /lib/ld-linux.so.2 -X -m armelf_linux -p -o helloworld

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib/crt1.o

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib/crti.o

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/crtbegin.o

 -L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5 -L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib

 /tmp/cccj0q5Z.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/crtend.o

 /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib/crtn.o

以下摘取关键部分:

cc1 helloworld.c -o /tmp/ccaykq0x.s

as /tmp/cccj0q5Z.o /tmp/ccaykq0x.s

collect2 -o helloworld crt1.o crti.o  crtbegin.o /tmp/cccj0q5Z.o crtend.o crtn.o

crt1.o crti.o  crtbegin.o crtend.o crtn.o都是启动文件,还有一些库文件,
-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s
以上三个命令分别对应于编译步骤中的预处理+编译、汇编和连接。预处理和编译还是放在了一个命令(cc1)中进行的,可以把它再次拆分为以下两步:

arm-linux-cpp -o helloworld helloworld.c
cc1 helloworld.i -o ccaykq0x.s

以上就是helloworld的编译过程。现在我们来看看编译选项-nostartfiles -nostdlib

arm-linux-gcc -v -nostartfiles -o helloworld helloworld.c

出现以下错误:

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/libexec/gcc/arm-linux/3.4.5/collect2

--eh-frame-hdr -dynamic-linker

 /lib/ld-linux.so.2 -X -m armelf_linux -p -o helloworld -L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5

-L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib

/tmp/ccYin8Ke.o

-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/bin/ld: warning: cannot find entry symbol _start; defaulting to 00008184

arm-linux-gcc -v -nostdlib -o helloworld helloworld.c

出现以下错误:

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/libexec/gcc/arm-linux/3.4.5/collect2

--eh-frame-hdr

 -dynamic-linker

/lib/ld-linux.so.2

 -X -m armelf_linux -p -o helloworld

-L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5

-L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/lib

 /tmp/ccuvtqHS.o

/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/../../../../arm-linux/bin/ld

: warning: cannot find entry symbol _start; defaulting to 00008074

 /tmp/ccuvtqHS.o(.text+0x10): In function `main': : undefined reference to `printf' collect2: ld returned 1 exit status

因为printf函数在库文件中实现。

上面可以看出要想编译出可以在Linux上运行的应用程序要经过,预处理、编译、汇编、链接。
预处理:

  1 # 1 "helloworld.c"
  2 # 1 ""
  3 # 1 ""
  4 # 1 "helloworld.c"
...
909 # 2 "helloworld.c" 2
910 int main(void)
911 {
912 printf("hello ubuntu.\n");
913 return 0;
914 }

可以看见预处理器把所有要包含(include)的文件(包括递归包含的文件)的内容都添加到了原始的C源文件中,然后把其输出到输出文件,除此之外,它还展开了所有的宏定义,所以在预处理器的输出文件中你将找不到任何宏。这也提供了一个查看宏展开结果的简便方法。

第二步“编译”,就是把C/C++代码“翻译”成汇编代码:

    .file    "helloworld.c"
    .section    .rodata
    .align    2
.LC0:
    .ascii    "hello ubuntu.\n\000"
    .text
    .align    2
    .global    main
    .type    main, %function
main:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 1, uses_anonymous_args = 0
    mov    ip, sp
    stmfd     {fp, ip, lr, pc}
    sub    fp, ip, #4
    ldr    r0, .L2
    bl    printf
    mov    r3, #0
    mov    r0, r3
    ldmfd    sp, {fp, sp, pc}
.L3:
    .align    2
.L2:
    .word    .LC0
    .size    main, .-main
    .ident    "GCC: (GNU) 3.4.5"

这个汇编文件比预处理后的C/C++文件小了很多,去除了很多不必要的东西,比如说没用到的类型声明和函数声明等。

第三步“汇编”,将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux上一般表现为ELF目标文件。

bigtree@just:~$ file helloworld.o

helloworld.o: ELF 32-bit LSB relocatable, ARM, version 1, not stripped


 

arm-linux-as -mfpu=softfpa -o hello.o hello.S
arm-linux-gcc -S main.c
arm-linux-as -mfpu=softfpa -o main.o main.s

arm-linux-ld --eh-frame-hdr -dynamic-linker /lib/ld-linux.so.2 -X -m armelf_linux -p -o main /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux/lib/crt1.o /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux/lib/crti.o /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/crtbegin.o -L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5 -L/home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux/lib main.o hello.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib/gcc/arm-linux/3.4.5/crtend.o /home/bigtree/embedded/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/arm-linux/lib/crtn.o

阅读(3815) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~