Linux 内核入门学习笔记(二) Linux开发工具链简介

    技术2022-05-19  25

     

    第二课时: Linux开发工具链简介

    1. gcc使用-v选项,可以看到许多被隐藏的信息

    gcc -o test test.c -v

    2. c程序编译过程 预处理->编译成汇编代码->汇编成目标代码->链接

    3. 只进行预处理 -E参数

    gcc -E -o test.cpp test.c

    4. 比较两个文件的前后差异 wc 命令

    wc test.c test.cpp

    5. -x 根据指定的步骤进行工作,预处理文件到汇编代码cpp-output,生成汇编代码后停止工作-S

    gcc -x cpp-output -S -o test.s test.cpp

    直接编译得到汇编代码

    gcc -S test.c

    6. 汇编代码->目标代码 gcc -x assembler -c gcctest.s

    直接编译成目标代码 gcc -c gcctest.c

    使用汇编器生成目标代码as -o gcctest.o gcctest.s

    7.目标代码->执行代码gcc -o gcctest gcctest.o

    直接生成执行代码gcc -o gcctest gcctest.c

    8.-Wall:打开所有的警告信息

    9.优化编译选项:-O0缺省情况,不优化-O1 -O2 -O3等等

    gcc -01 -o m1 test.c

    10. 使用time命令统计程序的运行 time ./m1

     

    GNU binutils 工具简介

    1. ar(建立归档文件(库文件))

    (1)假设有两个源程序add.c minus.c,包含两个函数文件

    将这两个源程序编译成目标文件

    gcc -c add.c minus.c

    (2)生成库文件,然后复制到/usr/lib目录下

    ar rv libtest.a add.o minus.o

    sudo cp libtest.a /usr/lib/

    (3) 在其他源代码文件中使用了之前库文件中的函数,在链接时用"-l<name>"指明库文件

    gcc -o test test.c -llibtest

    /***********这里课件上是-ltest 不知道是否正确**************/

    2. nm列出目标文件中的符号

    A:符号的值是绝对值,并且不会被将来的链接所改变

    B:符号位于未初始化数据部分(BSS段)

    C:符号是公共的。公共符号是未初始化的数据。在链接时,

    多个公共符号可能以相同的名字出现。如果符号在其他地方

    被定义,则该文件中的这个符号会被当作引用来处理

    D:符号位于已初始化的数据部分

    T:符号位于代码部分

    U:符号未被定义?:符号类型未知,或者目标文件格式特

    nm test.o

    3.objcopy可以将一种格式的目标文件内容进行转换,并输出为另一种格式的目标文件。

    将test转换为srec格式的文件ts

    objcopy -O srec test ts

    使用file命令查看文件信息

    file ts

    4. objdump显示一个或多个目标文件的信息,由其选项来控制显示哪些信息。这个工具可以方便的查看执行文件或者库文件的信息

    (1) “-f”选项显示文件头的内容

    objdump -f test

    (2) “-d”选项进行反汇编

    objdump -d add.o

    5. readelf 显示一个或多个ELF格式的目标文件信息。

    readelf -h test

    Gdb = GNU debuger

    1. gdb调试bug:gdb bug

    2. gcc -g参数:gcc -g -o bug bug.c

     

    GNU make

    Make可以识别出makefile中哪些文件已经被修改,并且在再次编译的时候只编译这些文件,从而提高编译的效率

    (1) 一般规则:

    目标文件   : 依赖文件列表

    (注意是tab)命令组

    target ... : prerequisites ...

    <tab>command

    <tab>...

    <tab>...

    test:test.c;

    gcc -O -o test test.c

    (2) 缺省情况下从makefile中的第一个目标开始执行,类似深度遍历

    (3) 使用变量

    $(objects)

    objects=main.o kbd.o command.o

    edit:$(objects)

    <tab>cc -o edit $(objects)

    (4)预定义变量:Make使用了许多预定义的变量,如AR、AS、CC、CXX、CFLAGS、CPPFLAGS等等

    (5)关于.PHONY例如:

    .PHONY:clean

    clean:

    <tab>rm *.o exec_file

    .PHONY通常会放在最后PHONY,作用是告诉make这个target不是真正的文件,只是一个虚拟的target。如果目录下恰好有一个名字为clean的文件。加上那一行和不加那一行就完全不同。如果没有那一行,make clean应该是提示"clean is up-to-date".如果有那一行,则是编译执行rm命令,也就是告诉程序,这个命令是要执行下面的命令,而不是对文件clean进行编译

    (6)内部变量

    $@扩展成当前规则的目的文件名

    $<扩展成依赖列表中的第一个依赖文件

    $ˆ扩展成整个依赖列表(除掉了里面所有重复的文件名)

    不需要括号括住

    CC = gcc

    CFLAGS = -Wall -O -g

    foo.o : foo.c foo.h bar.h

    $(CC) $(CFLAGS) -c $< -o $@

    相当于 gcc -Wall -O -g -c foo.c -o foo.o

     

    (7) Makefile中的函数

    典型的函数:

    7.1 $(subst from,to,text)

    $(subst ee,EE,feet on the street)

    得到结果等于fEEt on the strEEt’

    7.2 $(patsubst pattern,replacement,text)

    $(patsubst %.c,%.o,x.c.c bar.c)

    相当于‘x.c.o bar.o‘

    7.3 $(wildcard pattern) 扩展通配符 

    $(wildcard *.c)

    7.4 $(notdir patter) 去除文本中的路径

    dir=$(notdir ./abc/a.c)

    得到结果是 a.c 

    (8) 四种条件语句

    ifeq...else...endif 如果等于

    ifneq…else…endif 如果不等于

    ifndef…else…endif

    ifndef...else…endif

    /*********这两个一样?**************/

    GNU ld 链接器

    ld软件的作用是把各种目标文件(.o文件)和库文件链接在

    一起,并定位数据和函数地址,最终生成可执行程序

    gcc可以间接的调用ld,使用gcc的-Wl参数可以传递参数给ld

    目标文件 

    由多个节(section)组成,常见的节有:

    text节保存了可执行代码,

    data节保存了有初值的全局标量。已经初始化的数据

    bss节保存了无初值的全局变量。没有初始化的数据,只有名称和大小

    text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;而bss段不在可执行文件中,由系统初始化。有值

    链接描述文件(Linker script )

    分类:

    设置入口点命令

    处理文件的命令

    处理文件格式的命令

     

    常用的命令:

    1. 设置入口点

    格式:ENTRY(symbol)

    设置symbol的值为执行程序的入口点。

    ld有多种方法设置执行程序的入口点,确定程序入口点的顺序如下:

    (1)ld命令的-e选项指定的值

    (2)Entry(symbol)指定的值

    (3).text节的起始地址

    (4)入口点为0

    2.包含其他filename的链接描述文件

    INCULDE filename

    3.指定多个输入文件名

    INPUT(file,file,…)

    4.指定输出文件的格式 

    OUTPUT FORMAT(bfdname)  

    5.指定目标机器体系结构..

    OUTPUT ARCH ( bfdname ) 

    例如: 

    OUTPUT ARCH(arm)

    6.MEMORY:这个命令在用于嵌入式系统的链接描述文件中经常出现, 它描述了各个内存块的起始地址和大小。格式如下:

    MEMORY

    {

    name [(attr)]:ORIGIN = origin,LENGTH = len

    }

    例如: 

    MEMORY

    {

    rom : ORIGIN=0x1000, LENGTH=0x1000

    }

    7. SECTIONS

    告诉ld如何把输入文件的各个节映射到输出文件的各个节中。在一个链接描述文件中只能有一个SECTIONS命令

    在SECTIONS命令中可以使用的命令有三种:

    (1)定义入口点

    (2)赋值

    (3)定义输出节 

    定义输出节:

    SECTIONS

    {

    secname :

    {

    contents

    }

    }

    例子:

    SECTIONS

    {

    ROM:{*(.text)}>rom

    }

    8.定位计数器 

    一个特殊的ld变量,使用“.”表示

    总是在SECTIONS中使用 

    例如:

    SECTIONS

    {

    output:

    {

    file1(.text);

    . = . + 1000;

    file2(.text);

    . = . + 1000;

    file3(.text);

    }   = 0x1234;

    /*********有问题的地方******************/

    链接描述符文件

    SECTIONS

    定位输出点


    最新回复(0)