ld链接器

ELF文件解析器 前言 最近选了Linux内核原理的选修课,虽然因为课时比较短涉及到的内容只能涵盖Linux知识的一小部分,但是老师的水平确实很高,讲的知识也很深入,这次布置的小作业是编写Linux平台下的C语言程序实现如下功能: 模仿实现Linux下readelf工具的部分功能,能够对ELF可执行文件进行简单分析。(至少支持readelf工具的-h、-S、-s三个命令选项功能) 关于原理部分自认为没有能力和大佬们讲得一样透彻清楚,所以参考文章链接贴在了文章的末尾,看了一定就会明白的。 1.ELF文件介绍 在 Linux 系 阅读详情

ld链接器

TODO:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加



前言

ld是GNU操作系统上的连接器,把二进制文件连接成可执行文件。了解ld之前需要对可执行文件的节(section)和段(segment)有一定了解。

一、ELF文件解析

Executable and Linking Format,即可执行和可链接的格式,是Unix/Linux系统ABI (Application Binary Interface)规范的一部分。文件格式可参考官方文档:ELF FORMAT

1. 常见的ELF文件解析工具

objdump /readelf

通常使用以上工具完成,对ELF文件格式的查询,段/节查看等。比如 readelf -S/objdump -h 显示节(section);readelf -l可以显示文件的program header信息,其中包含段(segment)以及节与段的映射信息;readelf -h 可以显示ELF文件头信息。

nm/objdump -t查看符号表
对于每一个符号来说,其类型如果是小写的,则表明该符号是local的;大写则表明该符号是global(external)的。
类型 D 该符号位于初始化数据段中。一般来说,分配到data section中
类型 T 该符号位于代码区text section。

把一个C/C++程序编译为一个目标文件时,一个定义的函数和全局或静态变量,会得到一个定义的符号;在输入文件(.o,.a)中只是一个引用而未定义的函数或全局变量会变成一个未定义的符号.

2. 段和节的概念

section是从连接视角描述一个二进制文件布局的,而segment是从运行视角描述。常见节section有 .text .bss .data,但从程序运行开始section将被重新组织成segment,每个segment都是由若干section组成的,ld时可以指定segment由哪些section构成。通常所说运行程序的代码段数据段指的就是segment,可以从ELF的program header里查看segment及其映射关系。

这里对section与segment的关系再多谈一点:ld脚本可以创建segment,支持设置类型访问权限等;可以指定某些section从属于一个或多个segment。

readelf -l xx.elf
...
Program Headers:
  Type  Offset  VirtAddr PhysAddr FileSiz MemSiz Flags Align
...
Type {PHDR,LOAD,INTERP,DYNAMIC...}
Flags {RWX}

二、ld常见的一些概念

参考 ld中文手册完全版

1. ld命令

一般用于将目标文件与库链接为可执行文件或库文件,完成从输入文件目标文件(.o,.a)–>lds脚本(’-T’命令行选项指定)–>输出文件(可执行文件elf)的过程。

几个常用的参数:

[链接时的分组选项] -start-group archives --end-group: archives 可以是一组文件,这里允许重复搜索未定义符号,而一般情况archive只会搜索一次。链接的时候库文件只会按它们出现在命令行的顺序搜索一遍,如果包里有未定义的引用标号,而且该包还被放在命令行的后面,这样链接器就无法解决该标号的引用问题。通过给包分组,这些包可以被循环搜索直到所有的引用都可以解决为止。使用该选项将降低性能。只有在无法避免多个包之间互相引用的情况下才使用。

[指定某section的绝对地址] --section-start SECTIONNAME=ORG,通过指定ORG(十六进制整数),指定节在输出文件中的绝对地址。-Tbss ORG' -Tdata ORG' -Ttext ORG 跟-section-start 同义,不过把SECTIONNAME 替换为.bss, .data或.text。

/* 
 * -Wl为选项前缀,链接器通过编译器间接引用的例子
 */
gcc -Wl,--start-group foo.o bar.o -Wl,--end-group
/* Makefile 直接调用ld生成可执行文件 */
foo.elf: foo.o $(FOO_LDS)
	$(CROSS_COMPILE)ld -T $(FOO_LDS) -o $@ $(LDFLAGS) $<						\            
		--start-group															\
		$(LIB)/xxxlibs.a $(LIB)/libgcc.a ...									\
		--end-group																\
		-Ttext=$(TEXT_START)

2.链接脚本

实际上使用ld命令进行编译后的链接操作时,连接都被一个’连接脚本’所控制,如果不指定链接脚本,ld会使用默认的链接脚本(ld --verbose可查看)。链接脚本是用连接命令语言书写,主要目的是,描述输入文件中的“section”节如何被映射到输出文件中, 并控制输出文件的内存排布等。另外,ld命令行的选项基本都可以写进链接脚本里。

连接脚本是文本文件但可include其他头文件,语法包含 命令语句(带有参数的关键字),赋值语句。
几个常用的语法:

ENTRY(symbol)【命令】设置入口点,符号symbol的值作为用户进程第一条指令的地址。
SECTIONS 【命令】来描述如何把输入节映射到输出节, 并如何把输出节放入到内存中(内存布局):

SECTIONS
{
	SECTIONS-COMMAND
	SECTIONS-COMMAND
	...
}
/* 如果你在连接脚本中不使用'SECTIONS'命令, 连接器会按在输入文件中遇到的节的顺序把每一个输入节放到同名的输出节中 */
SECTIONS里用SECTION(不带S)来描述一个输出节:
	SECTION [ADDRESS] [(TYPE)] : [AT(LMA)]
	{
		OUTPUT-SECTION-COMMAND
		OUTPUT-SECTION-COMMAND
		...
	} [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP]
/* ld手册中的例子:代码应当被载入到地址'0x10000'处, 而数据应当从0x8000000 处开始. 命令的开始处, 定位计数器拥有值'0'.*/
SECTIONS
{ 
/*【赋值】第一行是对一个特殊的符号'.'赋值, 这是一个定位计数器. 
 *如果你没有以其它的方式指定输出节的地址(其他方式在后面会描述), 
 *那地址值就会被设为定位计数器的现有值
 */
. = 0x10000; 
/*【赋值】节名后面的花括号中,你列出所有应当被放入到这个输出节中的输入节的名字.
 * '*'是一个通配符,匹配任何文件名。表达式'*(.text)'意思是所有的输入文件中的'.text'输入节. 
 *  因为当输出节'.text'定义的时候, 定位计数器的值是'0x10000',
 * 连接器会把输出文件中的'.text'节的地址设为'0x10000'
 */
.text : { *(.text) } 
. = 0x8000000;
/*【命令】这里的*是所有连接文件的意思,.data : {} 是定义输出节及其具体包含内容;
 * .data后没接地址,就按照“.” 定位计数器的地址对齐边界计算。
 * .text ALIGN(0x10) : { *(.text) } 'ALIGN'返回当前的定位计数器,并向上对齐到指定的值.
 */
.data : { *(.data) } 
/*【命令】连接器放好'.data'输出节之后, 定位计数器的值是'0x8000000'加上'.data'输出节的长度. 
 * 得到的结果是连接器会把'.bss'输出节放到紧接'.data'节后面的位置
 */
.bss : { *(.bss) }
}

OUTPUT_ARCH(BFDARCH) 【命令】指定机器架构, objdump -f 可以查看elf文件的架构信息。
INPUT(FILE, FILE, ...)【命令】指示连接器在连接时包含文件,事实上, 可以把所有的输入文件列在连接脚本中, 然后在连接的时候什么也不需要,只要一个’-T’选项就够了.
INPUT (-lFILE) 【命令】ld 会把文件名转换为’libFILE.a’, 就象命令行参数’-l’一样
OUTPUT(FILENAME)【命令】命名输出文件 与 ld的’-oFILENAME’命令参数是完全等效的
KEEP【命令】背景:使用gcc参数-Wl,–gc-sections,不链接未用函数,可以减小可执行文件大小. 另外在连接命令行内使用了选项–gc-sections,连接器可将某些它认为没用的section过滤掉,此时如果有必要强制连接器保留一些特定的 section,可用KEEP()关键字达此目的。

如KEEP(*(.text))或KEEP(SORT(*)(.text))
// 这里sort文件连接器会把匹配通配符的文件和节按在连接中被看到的顺序放置. 

PHDRS【命令】用来控制标准文件格式使用的程序头,它也就是人们熟知的“段”–segment。使用`PHDR’把一个节赋给前面已定义的一个程序段,连接器在缺省状态下会自己创建一个可用的程序头。

PHDRS
{
	NAME TYPE [ FILEHDR ] [ PHDRS ] [ AT ( ADDRESS ) ] // TYPE 比如 `PT_LOAD' (1)表示这个程序头描述了一个被从文件中载入的段, objdump -p/ readelf -l 可以查看elf文件的程序头
	[ FLAGS ( FLAGS ) ] ; // FLAGS 设置段属性的p_flags域, RWX
}
例如,PHDRS { // 一次设置多个段
		textxx PT_LOAD ; 
		testbb PT_LOAD ;
}
SECTIONS { .text : { *(.text) } :textxx:testbbb } 
// 这里引用了textxx,指定了.text节的segment为textxx和testbbb,把节放入指定段内。
// 使用:NONE告诉连接器不要把节放到任何一个段中。

PHDRS设置的段属性将在程序头(描述了segment与section的关系,描述了segment的属性)体现出来,objdump -p 和 readelf -l 都可以查看。


总结

以上内容多参考 ld中文手册

通过readelf工具解析ELF可重定位目标文件 通过readelf工具解析ELF可重定位目标文件创建可重定位目标文件(main.o)ELF可重定位目标文件结构查看ELF头信息 创建可重定位目标文件(main.o) //main.c int sum(int *a,int n); int array[2]={1,2}; int mian() { int val=sum(array,2); return val; } //linux中利用gc... 阅读详情

相关推荐

链接器ld与lld的区别

VMA 是执行输出文件时 section 所在的地址,而 LMA 是加载输出文件时 section 所在的地址。一般而言,某 section 的 VMA == LMA. 但在嵌入式系统中,经常存在加载地址和执行地址不同的情况:比如将输出文件加载到开发板的 flash 中(由 LMA 指定), 而在运行时将位于 flash 中的输出文件复制到 SDRAM 中(由 VMA 指定)。您所要做的就是构建对象文件 和命令行参数,就像调用 外部链接器,然后从代码中调用链接器的 main 函数。

m0_48434559的博客 3207

ELF解析工具 —— 使用介绍

ELF解析工具 函数栈大小

alios、linux、rtos等OS技术分析 7万+

深入 iOS 静态链接器(一)— ld64

作者:字节跳动终端技术——李翔 前言 静态链接(static linking)是程序构建中的一个重要环节,它负责分析 compiler 等模块输出的 .o、.a、.dylib 、经过对 symbol 的解析、重定向、聚合,组装出 executable 供运行时 loader 和 dynamic linker 来执行,有着承上启下的作用。 对于 iOS 工程而言,目前负责静态链接的主要是 ld64。苹果对 ld64 加持了一些功能,以适配 iOS 项目的构建,比如: 现在在 Xcode 中即使不主动管.

YZcoder的博客 2148

ELF文件解析

linux xtensa elf

musiclvme的专栏 2071

GNU链接器(LD):分区命令、输出分区、输入分区定义

GNU链接器(LD):分区命令、输出分区、输入分区定义

kevin1499的博客 1480

ELF解析工具 v1.7(elf格式解析工具)

支持全部ELF类型解析。支持32位/64位elf文件自适应解析、可解析elf文件头、程序头、节头、字符表、符号表、hash表、版本定义表、版本依赖表、动态信息表等。 更多详细介绍请访问:https://blog.youkuaiyun.com/tanming1987/article/details/126445826 可以解析linux及大部分嵌入式的编译输出文件,如gcc、keil mdk、iar、ccs等编译器的输出文件格式均为ELF。

ld链接器基本命令

通过-Wl,--exclude-libs,libssl.a -Wl,--exclude-libs,libcrypto.a 设置链接器命令

我的博客 957

【Unity人物动画】SALSA With RandomEyes (语音生成嘴型/人物说话) 使用

SALSA使用探索 之前做项目时想做人物说话的嘴部动作,因为我们的语音是AI合成的,语音片段很多,如果能根据语音生成嘴部动画,那将极大便利我们的工作。后面是找到了SALSA的这款插件,并摸索出使用方法。 1 插件介绍 官方网站:https://crazyminnowstudio.com/ 一个能做2D纸片人和3D人物模型嘴部和眼睛动画的插件,由两人组成的独立工作室(疯狂米诺工作室)开发。 插件全名为SALSA With RandomEyes,2014年上架Asset Store,目前是已下架,替换为新版本

里约热内驴的博客 1万+

GCC链接器ld中文手册完全版

GCC链接器ld中文手册完全版 【下载地址】GCC链接器ld中文手册完全版 《GCC链接器ld中文手册完全版》是开发者深入理解GCC链接器ld的权威指南。手册全面解析了ld命令的使用方法、链接器脚本的语法与编写技巧,以及链接过程中的优化选项和错误处理策略。无论您是初学者还是经验丰富的开发者,这份手册都能为您提供清晰的指导...

gitblog_06701的博客 321

NHANES数据库的介绍及使用(一)

一、数据库概况 NHANES(National Health and Nutrition Examination Survey)是一项旨在评估美国成人和儿童健康和营养状况的研究计划,计划始于20世纪60年代初期,是一项针对不同人群或健康主题的调查。 1999年该调查成为一项持续计划,涉及各种健康和营养测量,项目每年调查一个全国代表性的样本,约5000人,这些人群位于全国各县,每年对其中15个县进行访问。 NHANES访谈部分包括人口统计学、社会经济学、饮食和健康相关问题。体检部分包括生理测量、实验室检查等

Christina 5万+

LSTM cell结构的理解和计算

LSTM是传统RNN网络的扩展,其核心结构是其cell单元,网上LSTM的相关资料繁多,质量参差不齐,下面主要结合LSTM神经网络的详细推导和 Christopher Olah的blog两篇文章中的内容进行说明。主要介绍网络如何计算,为何这么算先不展开:)。前者一副图加上29个公式,简洁明了;后者娓娓道来,适合初学者。首先是LSTM cell最常见的结构图: 这是变形的版本(找不到更清晰的版本了),

songhk0209的博客 2万+

Centos 下 ld 链接器版本更新

最近在编译一个工程的时候, 偶然遇到一个报错 /usr/bin/ld: 某个库 : unrecognized relocation (0x2a) in section `.text` /usr/bin/ld: final link failed: 错误的值 这个错大致意思在符号链接过程中, 链接失败, 而出现下面这样的情况,大概率就是链接器版本不正确导致的 而 ld 是 GUN 下提供的库链接器, 通过和同事比较了一下 ld 工具的版本后, 果然是我的版本较低, 所以接下来主要就是更新 ld 这个工具

会偷懒的程序猿 7935

SAP_SD模块销售开票计划预收款系统配置及前台操作说明

在 SAP SD 中,开票计划(Billing Plan)是一种允许根据时间节点或里程碑对销售订单进行分期开票的功能。其中最常见的一种应用就是预收款(Down Payment Billing),即在销售订单中直接定义某个百分比或金额作为预收款,系统在开票时自动生成预收账单。大额合同或长期项目型销售(先收 20%,交货前收 30%,交货后收 50%)。分期付款模式(分阶段收款)。必须预收款才能安排生产或交货的业务。后台路径:SPRO—销售与分享—销售—销售凭证—销售凭证项目—定义项目类别。

我小时候很黑的博客 1409

ld链接器脚本(一)

为了能够看懂uboot,顺便把ld的脚本看了一下。笔记记录下来 翻译自《The GNU linker-ld(Sourcery G++ Lite 2010q1-188)Version 2.19.51》 ld链接器脚本 每种链接器都由链接器脚本控制,这个脚本使用连接器命令语言编写 这个脚本的主要目的是:将输入文件中的段,组织成输出文件,并且控制输出段的内存布局。 次要目的:链接脚本可以使用下面描述的命令,使链接器执行其他操作。 链接器始终使用链接脚本。 如果用户不提供,则链接器将使用内置的脚本,这个内置脚本被编

安仔的博客 1589

matlab 一维相位解缠

一维相位解缠算法的matlab代码实现。

点云侠的博客 372

如何在Ubuntu 22.04系统上安装CUDA 12.9

本文提供Ubuntu22.04系统上安装CUDA12.9的简明指南:1)确认已安装适配575驱动;2)清理旧版本后安装必需依赖库;3)通过deb包方式添加英伟达源并安装CUDA12.9工具包;4)配置环境变量;5)通过nvcc-V和nvidia-smi命令验证安装。文中包含常见问题解决方法及多显卡使用说明,全程约需10分钟完成安装。

2501_93651177的博客 1480

ld - GNU链接器(Linux手册页)上

概要 ld [ options ] objfile ... 描述 ld结合了许多对象和归档文件,重新定位其数据并绑定符号引用。通常,编译程序的最后一步是运行ld。 ld接受以AT&T的链接编辑器命令语言语法的超集编写的链接器命令语言文件,以提供对链接过程的显式和完全控制。 该手册页未描述命令语言; 有关命令语言和GNU链接器其他方面的完整详细信息,请参阅“info”中的ld条目。 此版...

wogezheerne的博客 2047

Far planner代码系列(2)

graph_decoder系列(2) 承接上文 我们接着来看decoder_node.cpp的代码部分 void GraphDecoder::Init() { /* initialize subscriber and publisher */ //graph_sub_ 订阅节点/robot_vgraph 其类型是visibility_graph_msg/Graph的消息 graph_sub_ = nh.subscribe("/robot_vgrap...

博客 1534

Linux 链接器 ld 的工作原理与应用实践

链接器是软件开发过程中的一个重要工具,它负责将编译器生成的多个目标文件和库文件合并成一个单一的可执行程序。在 Linux 系统中,ld 是常用的链接器,它执行的任务包括符号解析和重定位。符号解析是指链接器解决目标文件中引用的符号(如函数和变量)与定义这些符号的文件之间的映射关系。重定位则是指调整代码中的地址引用,使之适应最终加载到内存中的位置。通过这些操作,链接器确保程序中的各个部分能够正确地相互引用,并能够在运行时正确加载。在本节中,我们将简要介绍链接器的基本概念和 ld 链接器的主要功能。

Liuqz2009的专栏 508

大津法(OTSU)点云强度信息分割

大津法(OTSU)是一种灰度图像自适应的阈值分割方法,大津法根据图像的灰度分布,将图像分成背景和前景两部分,前景就是需要按照阈值分割出来的部分。由于点云的强度信息的特性,也可以利用此方法进行分类,但需要保证信息干扰较少,例如道路标线分割等场景较为适用。

qq_48694523的博客 965

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

链接器LD的详细信息及其搜索路径揭密

http://blog.chinaunix.net/u3/97319/showart_2064712.html 链接器LD的详细信息及其搜索路径揭密  [root@localhost lib]# ld --verboseGNU ld version 2.17.50.0.6-9.el5 20061020  Suppo

ivan240的专栏 1326

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

GCC链接器ld中文手册完全版:助力开发者深入理解GCC链接器

GCC链接器ld中文手册完全版:助力开发者深入理解GCC链接器 【下载地址】GCC链接器ld中文手册完全版 《GCC链接器ld中文手册完全版》是开发者深入理解GCC链接器ld的权威指南。手册全面解析了ld命令的使用方法、链接器脚本的语法与编写技巧,以及链接过程中的优化选项和错误处理策略。无论您是初学者还是经验丰富的开发者...

gitblog_06774的博客 580

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

对iOS开发中的链接器ld64和-ld_classic的深入理解

通过这一期的介绍,相信各位小伙伴们对iOS开发中的链接器ld64和-ld_classic有了更深入的理解,能够更好地利用这些工具来提升应用程序的性能和稳定性。ld64具备高性能、丰富的特性和广泛的适用性,是现代iOS和macOS开发中使用最广泛的链接器之一。其中,ld64和-ld_classic是两个常见的概念。-ld_classic是一个编译选项,用于指定使用经典版本的ld链接器,而不是默认的ld64。这样做之后,Xcode将在构建过程中使用经典版本的链接器,而不是默认的现代链接器ld64。

gulu230220的博客 946

Ubuntu开发中,gcc默认ld链接器报错的解决办法

前言:所有踩过的坑,都是前进的必须;进坑并不可怕,训练一种脱坑的思维和办法才“可怕”。 最近在Ubuntu做项目移植,用gcc、g++编译程序,总是卡在一个出错的地方: /usr/bin/ld: 2: Syntax error: newline unexpected collect2: error: ld returned 2 exit status 开始还怀疑是程序的问题,后来感觉是这个ld不正常;因为之前没有遇到过此类的问题,而且对这个ld比较陌生,仅仅知道是个链接器。 好歹做过逆向,对于逆向

benben_ho的博客 4489

ld链接器组织obj顺序

makefile文件 OBJFILES = start.o gdt.o  idt.o  irq.o  isrs.o  kb.o  main.o  scrn.o  timer.o   all: iso   .s.o:     nasm -f elf32 -o $@ $   .c.o:     $(CC) $(CFLAGS) -o $@ -c $   kernel.bin:

lzg666456的专栏 1203

ld,GNU 链接器介绍以及命令行参数详解

当我们使用GCC编译源代码生成可执行程序,经过预处理、汇编、编译、链接四个阶段。链接器(Linker)将多个目标文件和库文件链接起来,链接器还解决目标文件之间的符号引用,即函数和变量的外部引用,并确保所有依赖都被正确地包含进来,生成最终的可执行文件或共享库。ld(Linker)是GCC(GNU Compiler Collection)工具链的一个重要组成部分。命令行参数详解输入和输出- o output_file 指定输出文件的名称。

qq_38393271的博客 1735
上一篇: 微核进程间通信
下一篇: [转]bionic aarch64 SYSCALL entry
under_maple
博客等级 码龄12年 15粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值