简图记录-交叉编译链 使用基础总结

2023-10-19 19:18

本文主要是介绍简图记录-交叉编译链 使用基础总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 

一、概念

二、编译器GCC

1、基本编译命令 与 执行

2、编译流程分解-预处理/编译/汇编/链接

3、编译代码优化 与 常用编译参数

三、查看工具binutils

1、地址转化为符号所在位置 addr2line (编译需要带-g)

2、档案(库)管理工具 ar

3、列出目标文件符号表 nm

4、查看目标文件信息(反汇编)objdump

5、显示可执行文件信息 readelf

6、减少目标文件(瘦身) strip

7、查看文件各段大小 size

四、C库 glibc


一、概念

交叉编译链:在一个平台(如Windows PC)生成另一个平台(如基于ARM芯片的嵌入式linux环境)可执行代码的工具链,主要由编译工具如gcc,查看工具集binutils(包含地址定位addr2line、支持反汇编objdump,文件瘦身strip等),库glibc组成。

学习目标人群:如果你要做嵌入式开发相关工作, 交叉工具编译链是你必须掌握的工具。

二、编译器GCC

GCC:GNU Compiler Collection,GNU编译器套件,是由GNU开发的编程语言译器。

学习gcc,必须了解他的编译指令(预处理 编译 汇编 链接),和常见编译参数使用(加调试信息 头文件路径添加 库路径添加 指定库等)。实际工作中往往是配合Makefile一起使用,Makefile中一些相关的隐含参数也需要了解。

1、基本编译命令 与 执行

以下面举例:

// hello.c 源文件
#include <stdio.h>
void test_func(char *str) {printf("hello world %s\n", str);return;
}
int main(void) {test_func("good boy!");return 0;
}

直接编译命令gcc hello.c -o hello;(将hello.c编译为可执行文件hello,-o xxx 为指定可执行文件名称,缺省则默认为a.out)

goodboy@ubuntu:~/gcc_study$ gcc hello.c -o hello
goodboy@ubuntu:~/gcc_study$ ./hello 
hello world good boy!

2、编译流程分解-预处理/编译/汇编/链接

实际编译过程: 经历了 以下四个主要步骤(如果缺省-E/-S/-C编译器会全部编译)。

(1)预处理-E:处理宏定义和include,去除注释,不会对语法进行检查

(2)编译-S:检查语法,生成汇编代码

(3)汇编-c:生成ELF格式的目标代码

(4)链接-O :生成可执行代码。链接分为两种,一种是静态链接,另外一种是动态链接。使用静态链接的好处是,依赖的动态链接库较少,对动态链接库的版本不会很敏感,具有较好的兼容性;缺点是生成的程序比较大。使用动态链接的好处是,生成的程序比较小,占用较少的内存.

编译过程 文件扩展名规范:预处理文件.i 汇编文件.s 目标文件.o

goodboy@ubuntu:~/gcc_study$ gcc -E hello.c -o hello.i #预处理
goodboy@ubuntu:~/gcc_study$ gcc -S hello.i -o hello.s #编译
goodboy@ubuntu:~/gcc_study$ gcc -c hello.s -o hello.o #汇编
goodboy@ubuntu:~/gcc_study$ gcc hello.o -o hello #链接
goodboy@ubuntu:~/gcc_study$ ls -al
total 52
drwxrwxr-x 2 goodboy goodboy  4096 Jun 13 10:12 .
drwxr-xr-x 7 goodboy goodboy  4096 Jun 13 09:56 ..
-rwxrwxr-x 1 goodboy goodboy  8555 Jun 13 10:12 hello
-rw-rw-r-- 1 goodboy goodboy   157 Jun 13 09:56 hello.c
-rw-rw-r-- 1 goodboy goodboy 17239 Jun 13 10:11 hello.i
-rw-rw-r-- 1 goodboy goodboy  1680 Jun 13 10:12 hello.o
-rw-rw-r-- 1 goodboy goodboy   894 Jun 13 10:11 hello.s

3、编译代码优化 与 常用编译参数

代码优化 :实际编译器在编译过程,一个重要的工作就是做代码优化。简单来说就是 代码进行等价变换,使得变换后的代码运行结果相同,但是 运行速度加快或者占用空间减少。代码优化举例:如中间代码优化技术,对局部优化(删除公共表达式、合并已知量,临时变量改名,代数变换等)、循环优化(循环层次外提、变换循环控制条件,循环展开与合并等)。

警告相关编译参数:-w 禁止全部警告; -Werror把警告报告为错误; -Wcomment 注释嵌套警告;-Wformat 检查printf\scanf等格式化io函数 参数类型与类型说明是否一致;-Wreturn-type检查返回值类型是否一致;-Wuninitialized 自动变量未初始化就使用警告;-Wsign-compare 有无符号比较警告; 

调试选项:-g 生成调试信息(用于gdb访问);

优化选项:-O1优化(编译过程更耗时、占内存,试图减少最终size合运行时间);-O2 进一步优化(常用);-O3 打开全部优化;-O0不进行优化;-Os 只优化大小;

预编译选项:-D宏名称[=宏值] 编译过程加入宏,如果缺省赋值默认为“1”;-U宏名 取消宏定义;

查找目录与查找库选项:-l<DIR> 添加一个头文件查找目录;-I<LIBRARY> 连接时搜索指定的函数库LIBRARY;-L<DIR> 添加一个库文件查找目录;

Linux平台 附加编译选项:-fPIC 地址无关化(重定位 .o、动态库);-fPIE -pie 随机化;GOT表保护 -Wl,-z,relro(链接命令,用户态程序使用);-fstack-check 编译时检查申请栈空间是否超过4K(大小可调),运行时超过会segmentation fault;

三、查看工具binutils

对于binutils,要掌握场景工具用法帮助问题的分析定位,如addr2line,ar,nm,objdump,readelf,strip,size。

1、地址转化为符号所在位置 addr2line (编译需要带-g)

用法举例:addr2line 0x12345 -f -e test.o;#-f参数会打印函数名称(默认只打印位置) -e 为指定调试文件(缺省为a.out)
 

void test_func(void) {int b = 0;int a = 10 / b; # 故意搞一个除零错误printf("a = %d\n", a); return;
}
int main(void) {test_func();return 0;
}

 我们搞一个除零错误,然后通过dmesg看coredump找到对应报错信息,找到崩溃时ip地址,再用工具addr2line定位 到 是hello.c文件第四行,函数 test_func中,行号也能对应上出错位置。

goodboy@ubuntu:~/gcc_study$ gcc hello.c -g -o hello
goodboy@ubuntu:~/gcc_study$ ./hello 
Floating point exception (core dumped)
goodboy@ubuntu:~/gcc_study$ dmesg #demsg查看coredump信息(省略一部分无关信息)
[219664.542213] traps: hello[49208] trap divide error ip:400542 sp:7ffedb0c0ba0 error:0 in hello[400000+1000]
goodboy@ubuntu:~/gcc_study$ addr2line 0x400542 -f -e hello 
test_func
/home/goodboy/gcc_study/hello.c:4
goodboy@ubuntu:~/gcc_study$ cat -n hello.c 1	#include <stdio.h>2	void test_func(void) {3	    int b = 0;4	    int a = 10 / b; 5	    printf("a = %d\n", a); 

 

2、档案(库)管理工具 ar

生成静态库:ar -c libtest.a a.o b.o; 把a.o和b.o生成libtest.a静态库---使用方式 gcc main.c -L<库路径> -ltest

解包静态库:ar -x libtest.a

生成动态库: gcc a.c b.c -fPIC -shared -o libtest.so;

3、列出目标文件符号表 nm

用法举例:nm -n(按地址)/-L(按符号所在位置)/(缺省按名称) xxx.o

第一列为地址,第二列 为类型(A绝对地址 B bss段 C 未初始化 D data段 R 只读data T 代码段 U未定义),第三列为符号名称

goodboy@ubuntu:~/gcc_study$ nm hello
0000000000601040 B __bss_start
0000000000601040 b completed.6982
0000000000601030 D __data_start
0000000000601030 W data_start
0000000000400470 t deregister_tm_clones
00000000004004e0 t __do_global_dtors_aux
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000601038 D __dso_handle
0000000000600e28 d _DYNAMIC
0000000000601040 D _edata
0000000000601048 B _end
00000000004005e4 T _fini
0000000000400500 t frame_dummy
0000000000600e10 t __frame_dummy_init_array_entry
0000000000400748 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_w __gmon_start__
00000000004003e0 T _init
0000000000600e18 t __init_array_end
0000000000600e10 t __init_array_start
00000000004005f0 R _IO_stdin_usedw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__w _Jv_RegisterClasses
00000000004005e0 T __libc_csu_fini
0000000000400570 T __libc_csu_initU __libc_start_main@@GLIBC_2.2.5
000000000040055f T mainU printf@@GLIBC_2.2.5
00000000004004a0 t register_tm_clones
0000000000400440 T _start
000000000040052d T test_func
0000000000601040 D __TMC_END__

 

4、查看目标文件信息(反汇编)objdump

用法举例:objdump -h(段信息)/-f(文件头)/-d(反汇编 带-S可同时打印C代码) test.o

goodboy@ubuntu:~/gcc_study$ objdump -d -S hello.o # 省略了部分内容
hello.o:     file format elf64-x86-64
Disassembly of section .init:
00000000004003e0 <_init>:4003e0:	48 83 ec 08          	sub    $0x8,%rsp4003e4:	48 8b 05 0d 0c 20 00 	mov    0x200c0d(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>4003eb:	48 85 c0             	test   %rax,%rax4003ee:	74 05                	je     4003f5 <_init+0x15>4003f0:	e8 3b 00 00 00       	callq  400430 <__gmon_start__@plt>4003f5:	48 83 c4 08          	add    $0x8,%rsp4003f9:	c3                   	retq   
0000000000400410 <printf@plt>:400410:	ff 25 02 0c 20 00    	jmpq   *0x200c02(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>400416:	68 00 00 00 00       	pushq  $0x040041b:	e9 e0 ff ff ff       	jmpq   400400 <_init+0x20>
000000000040052d <test_func>:40052d:	55                   	push   %rbp40052e:	48 89 e5             	mov    %rsp,%rbp400531:	48 83 ec 10          	sub    $0x10,%rsp400535:	c7 45 f8 00 00 00 00 	movl   $0x0,-0x8(%rbp)40053c:	b8 0a 00 00 00       	mov    $0xa,%eax400541:	99                   	cltd   400542:	f7 7d f8             	idivl  -0x8(%rbp)400545:	89 45 fc             	mov    %eax,-0x4(%rbp)400548:	8b 45 fc             	mov    -0x4(%rbp),%eax40054b:	89 c6                	mov    %eax,%esi40054d:	bf f4 05 40 00       	mov    $0x4005f4,%edi400552:	b8 00 00 00 00       	mov    $0x0,%eax400557:	e8 b4 fe ff ff       	callq  400410 <printf@plt>40055c:	90                   	nop40055d:	c9                   	leaveq 40055e:	c3                   	retq   
000000000040055f <main>:40055f:	55                   	push   %rbp400560:	48 89 e5             	mov    %rsp,%rbp400563:	e8 c5 ff ff ff       	callq  40052d <test_func>400568:	b8 00 00 00 00       	mov    $0x0,%eax40056d:	5d                   	pop    %rbp40056e:	c3                   	retq   40056f:	90                   	nop

 

5、显示可执行文件信息 readelf

用方举例:readelf -h(读取头信息)/-S(读取段信息) test.o

goodboy@ubuntu:~/gcc_study$ readelf -h hello.o 
ELF Header:Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class:                             ELF64Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              EXEC (Executable file)Machine:                           Advanced Micro Devices X86-64Version:                           0x1Entry point address:               0x400440Start of program headers:          64 (bytes into file)Start of section headers:          4472 (bytes into file)Flags:                             0x0Size of this header:               64 (bytes)Size of program headers:           56 (bytes)Number of program headers:         9Size of section headers:           64 (bytes)Number of section headers:         30Section header string table index: 27

6、减少目标文件(瘦身) strip

用法:strip -H删除文件头/-l删除行号/-r删除调试信息/-t删除符号表 test.o

7、查看文件各段大小 size

用法:size test.o

goodboy@ubuntu:~/gcc_study$ size hello.o text	   data	    bss	    dec	    hex	filename1284	    560	      8	   1852	    73c	hello.o

四、C库 glibc

对于C库,知道能支持做什么,如何使用,后续可以学习如何编译,升级。

这篇关于简图记录-交叉编译链 使用基础总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/241829

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的