读书笔记|《程序员的自我修养》-01前言(代码片段)

yxhuangCH yxhuangCH     2022-12-11     126

关键词:

图片来自极客时间深入浅出计算机原理

学习链接知识的意义

  • 理解链接将帮助你构建大型程序
    构建大型程序的程序员经常会遇到由于缺少模块、缺少库或者不兼容的库版本引起的连接器错误。除非你理解连接器是如何解析引用、什么是库以及链接器是如何使用库来解析引用的,否则这类错误将令你感到迷惑或挫折。

  • 理解链接器将帮助你避免一些危险的编译错误

  • 理解链接将帮助你理解语言的作用域是如何实现的
    例如,全局和局部变量之间的区别是什么?当你定义一个具有 static 属性的变量或者函数时,到底意味着什么

  • 理解链接将帮助你理解其他重要的系统概念
    链接器产生的可执行文件在重要的系统中扮演着关键角色,例如加载和运行程序、虚拟内存、分页和内存映射

  • 理解链接将使你能够利用共享库
    这个在 Android 的动态加载 so 文件以及 Native hook 中会用,我会在后续提供这方面的应用

前言

链接器是把程序的各个部分合并成一个文件,处理器可以将这个文件加载到存储器,并且执行它。

链接可以在编译的时候有静态编译器来完成,也可以在加载时和运行时有动态链接器完成。

静态链接器(static linker)以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。

被编译为位置无关代码的共享库可以加载到任何地方,也可以在运行时被多个进程共享。为了加载、链接和访问共享的函数和数据,应用程序还可以在运行时使用动态链接器。

链接器的任务

链接器的主要两个任务是

  • 符号解析(symbol resolution)
  • 重定位(relocation)

符号解析
目标文件定义和引用符号,符号解析是将目标文件中的每个全局符号都绑定到一个唯一定义。

重定位
编译器和汇编器生成从地址 0 开始的代码和数据节。
链接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节

目标文件

目标文件是源代码编译后但为进行链接的那些中间文件(Window 的 .obj 和 Linux 下的 .o)

目标文件存粹是字节块的集合。

目标文件的型式

  • 可重定位目标文件
  • 可执行目标文件
  • 共享目标文件

可重定位的目标文件

可重定位的目标文件是静态连接器合并成一个可执行的目标文件,它可以加载到存储器中并执行

可重定位的目标文件包含二进制代码和数据,它是有在编译时与其他可重定位目标文件合并起来,形成一个可执行目标文件

共享目标文件

共享目标文件(共享库)是在运行时有动态链接器和加载的,在调用程序被加载和开始执行时,或者需要在程序调用 dlopen 库的函数。

目标共享文件是一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态加载到存储器并链接。

加载

加载器将可以执行文件的内容映射到存储器,并运行这个程序。链接器还可能生出部分链接的可执行文件,这样的文件中有对定义在共享库中的程序和数据的未解析的引用。在加载时,加载器将部分链接的可执行文件映射到存储器,然后调用动态链接器,它通过加载共享库和重定位程序中的引用来完成链接任务。

相关命令

命令

gcc -c SimpleSection.c  // 生成目标文件
readelf -s link_example.o //查看符号表
objdump -r link_example.o //查看重定位表

> $readelf -h SimpleSection.o  // linex 用 

> $otool -h SimpleSection.o  // mac 使用

Mac 使用 readelf

Mac 上没有 ‘readelf 命令’ 可以使用 ’greadelf‘ 和 ’gobjdump‘
安装步骤:

  1. 使用命令

brew update && brew install binutils

2.路径添加到 ’~/.bash_profile‘ 文件中

# binutils
export PATH="/usr/local/opt/binutils/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/binutils/lib"
export CPPFLAGS="-I/usr/local/opt/binutils/include"

查看 so 的文件格式

> file libdycloudmedia.so
libdycloudmedia.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=2bcf3eae561f0f6ca25b0f2abd0728eef68f9ea3, stripped

参考

https://fengmuzi2003.gitbook.io/csapp3e/di-er-zhang-zhong-dian-jie-du
https://www.bilibili.com/video/BV1a54y1k7YE?p=13

读书笔记第二周《程序员的自我修养》

...程序的自我修养》??刚看到书名的时候以为这是一本讲述程序员为人处世,享受生活的文章,当我抱着当小说看消遣的心情从群里下载下来的时候,却发现这实际上是一本干货满满的书。当我看到副标题——链接,装载与库,我意... 查看详情

《程序员的自我修养》读书笔记--第二章

  2.1被隐藏了的过程     我们将源代码变成可执行文件的过程实际包含4个步骤,分别是预处理、编译、汇编和链接。(1)预处理过程主要处理源代码中以“#”开头的预编译指令,主要的处理规则如... 查看详情

读书笔记第三周《程序员的自我修养》

第三周读书笔记《程序员的自我修养》 ??计划对这本书是精读,这周读了3,4章。 第三章目标文件里有什么??首先介绍了目标文件的格式,Windows下是pe-coff,linux下是elf,他们都源于coff,这与操作系统的发展历史有关,而... 查看详情

《程序员的自我修养》读书笔记--第三章

第三章目标文件里有什么3.1目标文件的格式1、目标文件就是源代码编译后还未进行链接的中间文件。因为目标文件与可执行文件的内容和结构很相似,所以一般跟可执行文件的存储形式相同,Linux下统称为ELF可执行文件。动态链... 查看详情

读书笔记|《程序员的自我修养》-02目标文件(代码片段)

文章目录一、目标文件的格式二、目标文件的文件类型三、目标文件的内容3.1可执行文件的内容3.2文件头HEADER3.3代码段.text3.3数据段和只读数据段.data3.4BSS段四、ELF文件结构描述4.1重新定位表.rel.text4.2符号五、其他示例代码Mac使... 查看详情

程序员自我修养阅读笔记——运行库(代码片段)

主要关注程序的启动过程。1入口函数和程序初始化1.1程序真正的入口  通常写代码时,我们认为程序的入口是main函数,但是实际上有一些现象值得我们怀疑该结论是不是正确的。比如全局变量的初始化,C++... 查看详情

程序员自我修养阅读笔记——静态编译(代码片段)

测试环境:➜tmpuname--versionuname(GNUcoreutils)8.25Copyright(C)2016FreeSoftwareFoundation,Inc.LicenseGPLv3+:GNUGPLversion3orlater<http://gnu.org/licenses/gpl.html>.Thisisfreesoftware:youar 查看详情

程序员自我修养阅读笔记——内存(代码片段)

1程序的内存布局  进程的虚拟地址空间一般包含几个部分:内核使用的部分,进程不可访问,不同系统占用的大小不同;栈内存:用于维护程序的临时变量和函数调用使用,分配与销毁由系统完成;... 查看详情

程序员的自我修养笔记第一章(代码片段)

1.2万变不离其宗早期的计算机体系的硬件设计:虽然经过N年变化变成这样:看似复杂,却没有摆脱原来的框架模型,和原来的模型核心几个点:IO、内存、CPU始终没有没有改变。因此是可以看成是最早的模型&#... 查看详情

程序员自我修养阅读笔记——动态链接(代码片段)

1为什么需要动态链接  动态链接,顾名思义,就是只有在程序需要调用对应的库中的实现时才将对应的库的映像文件加载到内存。相比而言,静态链接是在编译阶段就将需要的目标文件中的相关实现连接到可执行... 查看详情

程序员自我修养阅读笔记——windowspe/coff(代码片段)

  本章主要将windowsPE格式和ELF格式的区别。1WindowsPE/COFF  PE是windows引入的一种可执行文件格式,该格式和Linux系统的ELF文件格式同源,都是由COFF格式发展而来。在Windows上可执行文件格式为PE格式,而目标文件的格... 查看详情

程序员自我修养阅读笔记——widnows下的动态链接(代码片段)

  Linux下的共享库为so文件为ELF格式,Windows下的共享库为dll文件PE格式。1dll简介  windows下采用dll共享对象让程序更加模块化方便升级,大多数情况为.dll文件,也可以是``.ocx,.CPL```文件。1.1进程地址... 查看详情

程序员自我修养阅读笔记——linux共享库管理(代码片段)

  有了共享库那么就存在对库版本的管理问题。1共享库版本1.1共享库兼容  共享库更新时一般会存在两种形式的更新,兼容更新和不兼容更新。这里的兼容不仅仅指接口兼容,也指ABI(ApplicationBinaryInterface)... 查看详情

程序员自我修养阅读笔记——可执行文件的装载过程(代码片段)

1可执行文件的装载过程1.1进程虚拟地址空间  一个可执行文件被装载到内存变成程序后(进程和程序的区别在于一个是静态的一个是动态的,程序就是菜谱,进程就是厨师参考菜谱做菜的过程),拥有自己... 查看详情

程序员自我修养阅读笔记——目标文件里有什么(代码片段)

测试环境:➜tmpuname--versionuname(GNUcoreutils)8.25Copyright(C)2016FreeSoftwareFoundation,Inc.LicenseGPLv3+:GNUGPLversion3orlater<http://gnu.org/licenses/gpl.html>.Thisisfreesoftware:youar 查看详情

markdown程序员的自我修养(代码片段)

查看详情

《程序员的自我修养》笔记

...,对自己有很大的借鉴意义。分享给大家~ 写给年轻程序员的启示:1.正确认识自己(通过努力,你会慢慢变成你希望的样子)2.比一般人更加努力3.适时建立个人权威(不要习惯于听命于人,缺少自己的观点和主张)4.遵循最... 查看详情

《程序员自我修养》阅读笔记-动态链接

1、动态链接的含义。动态链接就是将链接时的重定位推迟到加载时。相比于静态链接,动态链接的一个优点是可以节省内存。因为共享文件的代码可以共享。使用动态链接的时候,可执行文件和共享文件都会加载到内存。但是... 查看详情