位置无关代码(PIC)的思考

IAR设置堆栈和进程内存布局 虚拟内存:重点栈、堆、数据段、代码段等涉及到的参数程序内存分配问题,将写代码想象成内存存储的方式,更深了解自己写的逻辑代码。 阅读详情

    应用程序必须经过编译、汇编和链接后才变成可执行文件,在链接时,要对所有目标文件进行重定位(relocation),建立符号引用规则,同时为变量、函数等分配运行地址。当程序执行时,系统必须把代码加载到链接时所指定的地址空间,以保证程序在执行过程中对变量、函数等符号的正确引用,使程序正常运行。在具有操作系统的系统中,重定位过程由操作系统自动完成。  在设计Bootloader程序时,必须在裸机环境中进行,这时Bootloader映像文件的运行地址必须由程序员设定。通常情况下,将Bootloader程序下载到ROM的0x0地址进行启动,而在大多数应用系统中,为了快速启动,首先将Bootloader程序拷贝到SDRAM中再运行。一般情况下,这两者的地址并不相同。

    首先来看下面的链接脚本文件:

ENTRY(_start)
  ;指定输出可执行文件的起始代码段为_start.
SECTIONS
{
        .= BOOTADDR ; bootloader的开始地址/
        .= ALIGN(4); 代码以4字节对齐
        .text :;指定代码段
        {
          cpu/arch/start.o (.text) ; bootloader中的text段
          *(.text)                 ;其它text段   
        }
        .= ALIGN(4)
        .rodata :{*(.rodata)};指定只读数据段
        .= ALIGN(4);
        .data :{*(.data)};指定读/写数据段
        .= ALIGN(4);
        __bss_start =.; 把__bss_start赋值为当前位置,即bss段的开始位置
        .bss :{*(.bss)}; 指定bss段
        _end =.; 把_end赋值为当前位置,即bss段的结束位置
}

需要指出的是,链接脚本中所描述的输出段地址为虚拟地址VMA(VirtualMemoryAddress)。这里的“虚拟地址”仅指映像文件执行时,各输出段所重定位到相应的存储地址空间,与映像文件烧写到的实际的地址无关(即映像的加载地址)。因此,上面的链接脚本实际上指定了Bootloader映像在执行时,将被重定位到BOOTADDR开始的存储地址空间,以保证在相关位置对符号进行正确引用,使程序正常运行。

假设这里指定BOOTADDR= 0x0。以ARM为例,ARM处理器复位后总是从0x0地址取第1条指令,因此只需把BOOTADDR设置为0,再把编译后生成的可执行二进制文件下载到ROM的0x0地址开始的存储空间,程序便可正常引导;但是,一旦在链接时指定映像文件从0x0地址开始,那么Bootloader就只能在0x0地址开始的ROM空间内运行,而无法拷贝到SDRAM空间运行实现快速引导。当然,搬运代码最后的跳转语句可以写成绝对地址,如jmp 0x10000,这样可以正确的跳到RAM中的0x10000地址处,但当执行继续执行碰到其他符号地址计算,或全局数据访问的时候,由于此时不是位置无关代码,此时地址的计算需要查询map表,但是map表中的地址仍然在ROM空间中,所以还会跳回ROM空间,另外,还会有其他问题,如动态内存申请等。

有了位置无关代码,只需修改链接脚本文件的BOOTADDR=0x10000即可,即将整个镜像文件都映射到RAM空间,但是bootloader最开始的搬运代码必须是位置无关的代码,这样虽然搬运代码被映射到RAM地址空间,但它在0x0开始的ROM中也能正确执行,搬运代码最后的跳转语句就可以跳转到某个标号了,因为此时标号的地址已经被映射到了ram空间,之后的代码执行将没有任何问题。

当然,可以将搬运代码和搬运完成跳转到的代码分段映射,即搬运代码映射到ROM地址空间,其他代码映射到RAM空间。但是这样会存在一个问题:生成的bin文件变得非常大。生成的bin文件将会按照映射到地址空间来生成,如果ROM空间与RAM空间地址不连续,假设ROM地址空间为0x0 ~ 0x1000 , RAM地址空间为0x10000~0x20000,那么, 0x1000~0x10000之间的地址空间都被填充为0,除非在生成bin文件时重新进行拼装。

如何编写位置无关代码呢?

引用同一位置无关段或相对位置固定的另一位置无关段中的符号时,必须是基于PC的符号引用,即使用相对于当前PC的偏移量来实现跳转或进行常量访问。

1.位置无关的程序跳转。使用相对跳转指令实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。

2.位置无关的常量访问。在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。为增强程序的可读性,利用EQU伪指令对一些常量进行赋值,但在访问过程中,必须实现位置无关性。

3. 使用绝对地址进行跳转,一般是在不同的位置无关代码段之间跳转。

最后,总结一下位置无关代码段的优点:

1.简化设计,方便实现系统的快速引导。位置无关代码可以避免在引导时进行地址映射,并方便地跳转到RAM中实现快速引导

2.实现复位处理智能化。位置无关的代码可以被加载到任意地址空间运行

3.便于调试。Bootloader的调试通常也是一个繁琐的过程,使用位置无关代码,则可以将映像文件加载到RAM中进行调试,这既能真实地反映程序从ROM中   进行系统引导的情况,又可以避免频繁烧写程序存储器。


iPhone用户必看:不装App也能搞定GitHub 2FA验证的3种方法(附恢复码管理技巧) 本文为iPhone用户提供了无需安装第三方App即可完成GitHub双重身份验证(2FA)的三种原生方案:利用相机扫码与iCloud钥匙串自动填充、使用iCloud钥匙串内置的TOTP验证码生成器,以及借助Safari浏览器扩展。文章详细解析了每种方法的操作步骤、适用场景,并重点强调了恢复码的安全管理与多层备份策略,帮助开发者在提升账户安全的同时,享受苹果生态的无缝便捷体验。 阅读详情

相关推荐

深入解析ADC采样电容:从充电误差到LSB精度的关键设计

本文深入解析了ADC采样电容在模数转换中的核心作用,重点探讨了充电时间常数与采样误差的博弈关系。通过推导最小采样时间公式,揭示了精度、速度、源阻抗与内部电容之间的制约关系,并提供了从理论计算到外部驱动电路设计的实战指南,是确保ADC达到LSB精度的关键。

android的专栏 1103

IAR编译“地址无关代码”(PID)选项

固件升级时,会擦写当前程序的代码段。故,擦写前,需考虑将代码搬移到sram内运行。 前提条件是这段代码是“地址无关代码”。 阅读IAR手册,发现编译选项有对“地址无关代码”的支持: --pi_veneers Syntax --pi_veneers   Description Use this option to make the linker generate position-

iamlbccc的专栏 2053

matlab kwave模拟超声换能器学习笔记

kwave模拟超声换能器的学习笔记,从零开始造车轮

SolvingMaster的博客 3197

痞子衡嵌入式:深扒IAR启动函数流程之段初始化实现中可用的压缩选项

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是IAR启动函数流程里段初始化实现中可用的压缩选项。   接着 《IAR启动函数流程之段初始化函数__iar_data_init3实现》 一文,咱们再深入一步。对于 .bss 段的初始化,其实没什么好说的,就是简单的清零操作,但是 .data/.textrw 段的初始化工作是可以做一点文章的,尤其是当这些段数据量非常大的时候,可...

痞子衡嵌入式 1436

科研党必备:5个高效查找论文开源代码的宝藏网站(附实战技巧)

本文为科研工作者推荐5个高效查找论文开源代码的宝藏网站,包括ResearchCode和PapersWithCode等工具,提供实战技巧如进阶搜索语法和代码质量评估体系,帮助快速定位高质量实现并提升复现效率。特别分享隐藏代码库的检索方法和智能工作流配置,助力科研党高效完成论文复现。

weixin_28829629的博客 401

5分钟搞懂异构图注意力网络(HAN):从元路径到节点聚合的全流程解析

本文深入解析异构图注意力网络(HAN)的核心原理与实战应用,从元路径设计到多级注意力实现的全流程。HAN通过节点级和语义级双重注意力机制,有效处理包含多种节点和边类型的异构图数据,在电商推荐、学术网络分析等场景展现卓越性能。文章提供DGL实现代码和调参技巧,帮助开发者快速掌握这一强大工具。

weixin_29056701的博客 311

IAR的变量初始化浅析

Hi,大家好,今天是落汤的肌肉,因为成都的天像是漏了一样。昨天的文章最后留了一个小坑,今天把他填了。再赠送一段使用JLINK RTT串口模拟,这样在调试时节省一个串口资源。

认真搞搞汽车MCU 1554

广工计组f4b 8位12指令微程序CPU设计实验报告(内含可通过代码以及波形图)

实验目的:模型机是计算机的缩细模型,通过它可以理解计算机整机的结构和功能,理解CPU,存储器,中断控制器,接口的结构及实现逻辑和各部件之前的接口关系。本实验是设计一个8位模型计算机。:一条机器指令可以分解成一个微操作序列,这些微操作是计算机最基本的,不可再细分的操作。:在微程序控制的计算机中。将控制部件向执行部件发出的各种控制命令成为微命令,它是构成控制序列的最小单位。微命令和微操作是一一对应的。微命令是微操作的控制信号,微操作微命令的执行过程。2.:微指令是若干微命令的集合。

weixin_63692154的博客 4705

深入理解 Linux 位置无关代码 PIC

本文主要描述了Linux系统上关于位置无关代码PIC,位置无关可执行程序PIE及地址空间布局随机化ASLR三个主要特性的原理及联系。第一部分首先介绍了应用程序地址空间的基础知识作为铺垫;...

内核工匠 3646

C#串口通信从入门到精通(5)——打开、关闭串口

本文详细介绍如何打开串口

qq_34059233的博客 6781

华为OD机试真题 新系统2026-04-01 Python&JS 实现【空间占用计算】

员工A的磁盘空间经常被耗尽,他需要找到占用空间最大的目录或文件,然后决定如何清理文件释放空间。给定某一目录,请编写程序帮助他统计该目录内一级子目录和文件的占用空间,并返回目标目录一级子项(文件或子目录)中占用空间最大的项。

MISAYAONE的博客 1302

PIC位置无关代码

什么是PLT,如何通过调用“function@PLT”来调用“函数”? 要了解过程链接表(PLT),先让我简要介绍一下共享库! 与静态库不同,共享库代码段在多个进程之间共享,而其数据段对于每个进程是唯一的。这有助于减少内存和磁盘空间。由于代码段在多个进程之间共享,所以应该只有read和execute权限,因此动态链接器不能重新定位代码段中存在的数据符号或函数地址(因为它没有写权限)。那么动态链...

JD san的博客 1798

配置某VLAN下ONU的二层互访(隔离)问题(解决OLT二层隔离问题)

问题:OLT的ONU节点之间在同一VLAN下的终端默认隔离,在确实需要互通的场景下如何解决。

symstandsun的博客 4567

位置无关码PIC详解:原理、动态链接库、代码重定位

本文解释了什么是位置无关代码,以及它如何帮助创建具有可共享只读文本段的共享库。位置无关代码(PIC)通过引入全局偏移表(GOT)和过程链接表(PLT)实现,解决了共享库加载时的重定位问题。GOT提供了数据和函数的间接引用,PLT实现了懒绑定,推迟函数地址的解析。当然这也伴随额外的内存加载和寄存器使用成本,但在权衡之下,现代的编译器都更倾向于使用PIC。

主要分享嵌入式软件、人工智能部分知识 7788

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

c++位置无关代码(PIC)生成

位置无关代码是指编译生成的代码在运行时可以被加载到内存中的任何位置,并且仍然能够正确运行。它不依赖于固定的内存地址,这使得代码可以被多次共享和重用,非常适合动态链接库等场景。

qq_62784677的博客 1127

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

共享库中的位置无关代码(PIC)

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ 在之前的文章里我已经描述过在将共享库载入程序地址空间时需要特殊的处理。简而言之,在链接器创建共享库时,它不能预先知道这个库将在哪里载入。这给在库里访问数据与代码带来了麻烦,应该使...

qinrenzhi的博客 802

【deepseek】位置无关代码介绍

好的,我来为你详细解释这些概念,并附上 RISC-V 的代码示例。PC 相对寻址auipc%pcrel_hi%pcrel_lo0x10000x800000000x200000000x80000000。

ruofengdeyu的博客 945

位置无关码(PIC)详解

位置无关码(Position-Independent Code, PIC)是指编译后的机器代码在内存中任意地址加载执行时,无需修改内部地址引用仍能正确运行。

2303_76316997的博客 1319
上一篇: qemu源码分析之Makefile
下一篇: elf转化成bin后,bin文件变大的问题
刘军卫
博客等级 码龄19年 1143粉丝 245原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值