七、揭开链接器的面纱(上)

1. 问题

源文件被编译后生成目标文件,这些目标文件如何生存最终的可执行程序?

2. 链接器的意义

链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。

3. 目标文件的秘密

  • 各个段没有具体的起始地址,只有段大小信息
  • 各个标识符没有实际地址,只有段中的相对地址
  • 段和标识符的实际地址需要链接器具体确定

4. 链接器的工作内容

  • 将目标文件和库文件整合为最终的可执行程序

    • 合并各个目标文件中的段( .text, .data, .bss )
    • 确定各个段和段中标识符的最终地址(重定位)
    • 链接前后对比

5. 问题

main()函数是第一个被调用执行的函数吗?

6. 默认情况下( gcc )

  1. 程序加载后,_start()是第一个被调用执行的函数
  1. _start()函数准备好参数后立即调用__libc_start_main()函数
  2. __libc_start_main()初始化运行环境后调用main()函数执行
  • _start()函数的入口地址就是代码段( .text )的起始地址!

7. __libc_start_main()函数的作用

  1. 调用__libc_csu_init()函数(完成必要的初始化操作)
  2. 启动程序的第一个线程(主线程),main()为线程入口
  3. 注册__libc_csu_fini()函数(程序运行终止时被调用)

8. 程序的启动过程

9. 自定义程序入口函数

  • gcc提供-e选项用于在链接时指定入口函数
  • 自定义入口函数时必须使用-nostartfiles选项进行链接

10. 思考

链接选项-nostartfiles的意义是什么?

链接时不要使用标准的系统启动文件。标准的系统库通常使用,除非使用-nostdlib或-nodefaultlibs。

八、揭开链接器的面纱(中)

1. 思考

链接器根据什么原则完成具体的工作?

2. 链接脚本的概念和意义

  • 链接脚本用于描述链接器处理目标文件和库文件的方式

    • 合并各个目标文件中的段
    • 重定位各个段的起始地址
    • 重定位各个符号的最终地址

3. 链接脚本的本质

4. 链接脚本初探( Round 1

5. 注意事项

  • 各个段的链接地址必须符合具体平台的规范
  • 链接脚本中能够直接定义标识符(源代码的变量)并指定存储地址
  • 链接脚本中能够指定源代码中标识符的存储地址

在Linux中,进程代码段(.text)的合法起始地址为[0x08048000,0x08049000]

6. 编程实验:链接脚本初体验

8-1.lds

7. MEMORY命令

  • 默认情况下

    • 链接器认为程序应该加载进入同一个存诸空间
  • 嵌入式系统中(可能不存在MMU)
    • 如果存在多个存储空间,必须使用MEMORY 进行存储区域定义

8. MEMORY命令的使用( Round 2

9. MEMORY命令的属性定义

10. ENTRY命令指定入口点( Round 3

11. 编程实验:链接脚本指定入口函数

8-2.Ids

查看默认的链接脚本 ld --verbose > default.lds

默认进入 _start()

12. 小结

  • 链接器根据链接脚本中的描述完成具体的工作
  • 链接脚本用于指定各个段的地址和标识符的地址
  • SECTIONS命令确定可执行程序中的段信息
  • MEMORY命令对存储区域进行重定义
  • ENTRY命令指定可执行程序的入口函数

九、汇编语言的内嵌编程

1. C 语言中的内嵌汇编

内嵌汇编的语法格式:

2. 内嵌汇编示例

  • mov 类似于 赋值操作符
  • 占位符 %1  %0 需要被后面的参数所替换。(%0 ==>result)
  • asm … ==> result = input;

3. 编译器做了什么?

  • 将result关联到某个适合的寄存器
  • 将input关联到另一个适合的寄存器
  • 通过通用寄存器间接操作变量

= 限制符 意味着后面是输出参数

4. 常用限制符的说明

5. 编程实验:内嵌汇编初体验

9-1.c

6. 问题

如何在不使用printf()的情况下打印字符串?

7. 通过INT 80H使用内核服务

  • INT指令用于使用Linux内核服务(中断指令)
  • 80H是一个中断向量号,用于执行系统调用
  • 如何指定具体的系统调用(如∶sys_write )以及调用参数?

    • 通过寄存器指定具体的系统调用及参数

8. INT 80H使用示例一

限制符r 让编译器决定用什么寄存器与s和l关联,但是不能使用保留列表的寄存器。

9. INT 80H使用示例二

10. 注意事项

  • 嵌入汇编时,除汇编模板外,其余参数可以全部省略
  • 当省略的参数在中间时,对应分隔符":"不可省略
  • 当省略保留列表时,对应分隔符":"可省略
  • 当省略可选参数时,寄存器前使用单个%作为前缀
  • 当存在可选参数时,寄存器前使用两个%作为前缀

11. 编程实验:深入体验内嵌汇编

打印刚退出进程的进程码

echo $?

12. 小结

  • C 程序中支持直接嵌入汇编语言进行编程
  • 通过寄存器到变量的关联完成汇编到C语言的交互
  • 内嵌汇编代码时,通过占位符指定交互的变量
  • 限制符指示编译器将适合的寄存器关联到变量
  • 通过内嵌汇编能够直接使用系统服务

十、揭开链接器的面纱(下)

1. 课程实验(模拟嵌入式开发)

  • 编写一个"体积受限"的可执行程序
  • 通过makefile完成代码编译
  • 运行后在屏幕上打印"D.T.Software"

2. 深度分析

3. 解决方案设计

  • 通过内嵌汇编自定义打印函数和退出函数( INT 80H )
  • 通过链接脚本自定义入口函数(不依赖任何库和GCC内置功能)
  • 删除可执行程序中的无用信息(无用段信息,调试信息,等)

4. 打印函数设计

5. 退出函数设计

6. 链接脚本设计

.rodate和.text都是只读属性,放在一起达到减少段的目的。

.rodate只读数据区

7. 最后的准备(一)

  • ld命令

    • GNU的链接器,将目标文件链接为可执行程序
    • GCC编译器集中的一员,重要的幕后工作者
  • ld -static
    • -static表示ld使用静态链接的方式来产生最终程序,而不是默认的动态链接方式

8. 最后的准备(二)

  • - gcc -fno-builtin

    • -fno-builtin参数用于关闭GCC内置函数的功能

GCC提供了很多内置函数(Built-in Function),它会把一些常用的C库函数替换成编译器的内置函数,以达到优化的目的。

9. 编程实验:模拟嵌入式开发

program.out

10. 小结

  • 对于资源受限的嵌入式设备,需要考虑可执行程序的大小
  • 通过内嵌汇编直接使用系统服务能够避开相关库的使用
  • 可以通过如下方法控制可执行程序的体积大小
    • 最小化库的使用(必要情兄下考虑自己实现相关函数)
    • 自定义链接脚本,删除无用段信息

Linux调试私房菜(四)揭开链接器的面纱、汇编语言的内嵌编程相关推荐

  1. Linux中ELF格式 可执行文件+动态链接器 的加载

    两种加载方式 (1)加载可执行文件,通过PT_INTERP加载动态链接器 (2)直接加载动态链接器,再由其加载可执行文件 On a typical ELF system such as Linux, ...

  2. linux动态可执行文件,Linux中ELF格式 可执行文件+动态链接器 的加载

    两种加载方式 (1)加载可执行文件,通过PT_INTERP加载动态链接器 (2)直接加载动态链接器,再由其加载可执行文件 On a typical ELF system such as Linux, ...

  3. Linux开发常见问题:GCC:链接器输入文件未使用,因为链接尚未完成

    问:我在Linux中运行一个make文件去编译C语言代码,然后得到了如下的错误信息: gcc  -Wall  -fPIC  -DSOLARIS  -DXP_UNIX  -DMCC_HTTPD  -D_ ...

  4. Linux常用命令介绍(20个)——《鸟哥的Linux的私房菜》

    ls [选项] [目录名] -a, -l 列出当前目录下的所有文件和目录 -a 所有文件,包含以点开头的隐藏文件和目录.一个点代表当前目录,两个点代表上一层目录. -l 列出文件和目录的详细信息:包含 ...

  5. linux鸟叔私房菜读后感,鸟叔的Linux私房菜 读书笔记 第一章

    目录dom 硬盘数学 第一章 计算机概论 知识点总结 计算机的定义为:接受使用者输入指令与资料,经由中央处理器的数学与逻辑单元运算处理后,以产生或储存成有用的资讯:程序 电脑的五大单元包括:输入单元. ...

  6. VLC多媒体播放器将字幕srt等 内嵌在视频中且能合并到视频,保存为带字幕的新视频 自媒作首选工具

    VLC 是一款自由.开源的跨平台多媒体播放器,可播放大多数多媒体文件,以及 DVD.音频 CD.VCD 及各类流媒体协议.可以说是一款万能的多媒体播放器. 官方网站:http://www.videol ...

  7. vue打开其他项目的页面/打开外部链接,window模态框或内嵌在项目里

    写这篇文章的时候心情很emo,希望自己更强大吧 在项目里通过点击列表当前行,拿到每行的id之后,跳转到新页面打开外链或者以window模态框的形式在当前页打开,并且叉掉后不影响原来的页面. 一:在项目 ...

  8. 《鸟哥的linux私房菜-服务器篇 第三版》 RHCA亲授

    经典再现,<鸟哥的linux私房菜-服务 器篇(第三版)>远程班隆重推出! 鸟哥的linux的私房菜是linux教材中的 经典中的经典!是学习linux的绝佳资 料! 上课时间: 周一到周 ...

  9. 使用gcc编译和链接C语言程序,用GCC编译链接程序--编译链接器GCC常用功能(菜鸟级)...

    转载自:http://daimajishu.iteye.com/blog/1089740 对gcc认识的一篇文章,就转载了,截取了自己感兴趣部分. 一,GCC编译器简介 虽然我们称Gcc是C语言的编译 ...

最新文章

  1. ROS中launch文件使用笔记
  2. 阿里云服务器 安全狗外部访问mysql_阿里云linux/centos服务器安全狗安装
  3. pom.xml设置mysql连接_maven工程配置pom.xml实现mybatis的访问数据库操作
  4. Remove Duplicates from Sorted List
  5. 别再用假任务做小样本学习实验了!来试试这个全新基准数据集
  6. HTML rel 属性
  7. 新书《深入理解Kafka:核心设计与实践原理》上架,感谢支持~
  8. 计算机考题中有关反码的考题,2019陕西信合招聘笔试模拟试题-计算机知识8
  9. 一文搞懂List 、ListObject、List?的区别以及? extends T与? super T的区别
  10. golang 捕获堆栈信息_一篇文章教你如何捕获前端错误
  11. word是多线程的程序_线程的基本概念,实现多线程的四种基本方式
  12. Java中的Object 类的常见方法
  13. element-ui 引用阿里云矢量图不显示图标,显示的为小方框
  14. 大数据早报:极课大数据获得1亿元融资 美科学家利用机器学习挖出人们背后的自杀行为(11.1)
  15. c语言的条件运算符,条件运算符c语言
  16. 标题怎样选择适合自己的导图结构
  17. 圆圈怎么用html实现,如何利用css实现圆形效果?
  18. oracle中skimmer的意思,skimmer to是什么意思
  19. 在Python中使用StanfordOpenIE
  20. android studio appt2,一步一坑学android之禁用Appt2(andriod studio3.0)

热门文章

  1. Android Context 到底是什么?
  2. 计算机电源维修教学,笔记本电源维修方法详解【图文教程】
  3. jzoj5990. 【北大2019冬令营模拟2019.1.6】Bear (状压dp)
  4. Farey sequences
  5. Kali-现代化工具基础建设
  6. 对sizeof的一点点理解
  7. D3 天眼查 股权穿透 股权结构,默认第一行,异步添加,加减号居中,拖拽,缩放, hover。
  8. 基于物联网的智能家居系统设计QY-LYZN
  9. Java实习面试(2018春)
  10. 浏览器有些图片不能显示