精华内容
下载资源
问答
  • 位置无关代码

    2021-08-19 14:59:00
    ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。尤其在裸机状态下开发Bootloader程序及进行内核初始化设计;利用位置无关...

    ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。尤其在裸机状态下开发Bootloader程序及进行内核初始化设计;利用位置无关的程序设计方法还可以在具体应用中用于构建高效率动态链接库。

    应用程序必须经过编译、汇编和链接后才变成可执行文件,在链接时,要对所有目标文件进行重定位(relocation),建立符号引用规则,同时为变量、函数等分配运行地址。当程序执行时,系统必须把代码加载到链接时所指定的地址空间,以保证程序在执行过程中对变量、函数等符号的正确引用,使程序正常运行。在具有操作系统的系统中,重定位过程由操作系统自动完成。

    在设计Bootloader程序时,必须在裸机环境中进行,这时Bootloader映像文件的运行地址必须由程序员设定。通常情况下,将Bootloader程序下载到ROM的0x0地址进行启动,而在大多数应用系统中,为了快速启动,首先将Bootloader程序拷贝到SDRAM中再运行。一般情况下,这两者的地址并不相同,程序在SDRAM中的地址重定位过程必须由程序员完成。实际上,由于Bootloader是系统上电后要执行的第一段程序,Bootloader程序的拷贝和在这之前的所有工作都必须由其自身来完成,而这些指令都是在ROM中执行的。也就是说,这些代码即使不在链接时所指定的运行时地址空间,也可以正确执行。这就是位置无关代码,它是一段加载到任意地址空间都能正常执行的特殊代码。

    位置无关代码常用于以下场合:
            程序在运行期间动态加载到内存;
            程序在不同场合与不同程序组合后加载到内存(如共享的动态链接库);
            在运行期间不同地址相互之间的映射(如Bootloader程序)。

    虽然在用GCC编译时,使用-fPIC选项可为C语言产生位置无关代码,但这并不能修正程序设计中固有的位置相关性缺陷。特别是汇编语言代码,必须由程序员遵循一定的程序设计准则,才能保证程序的位置无关性。

    ARM程序的位置无关可执行文件PIE(PositionIndependent Executable)包括位置无关代码PIC和位置无关数据PID(PositionIndependent Data)两部分。

    PID主要针对可读写数据段(.data段),其中保存已赋初值的全局变量。为实现其位置无关性,通常使用寄存器R9作为静态基址寄存器,使其指向该可读写段的首地址,并使用相对于基址寄存器的偏移量来对该段的变量进行寻址。这种方法常用于为可重入程序的多个实例产生多个独立的数据段。在程序设计中,一般不必考虑可读写段的位置无关性,这主要是因为可读写数据主要分配在SDRAM中。

    PIC包括程序中的代码和只读数据(.text段),为保证程序能在ROM和SDRAM空间都能正确运行(如裸机状态下的Bootloader程序),必须采用位置无关代码程序设计。

    PIC遵循只读段位置无关ROPI(ReadOnly Position Independence)的ATPCS(ARMThumb Procedure Call Standard)的程序设计规范:

    (1) 程序设计规范1

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

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

    另外,还可使用ADR或ADRL伪指令将地址标号值读取到PC中实现程序跳转。这是因为ADR或ADRL等伪指令会被编译器替换为对基于PC的地址值进行操作,但这种方式所能读取的地址范围较小,并且会因地址值是否为字对齐而异。

    但在ARM程序中,使用LDR等指令直接将地址标号值读取到PC中实现程序跳转不是位置无关的。例如: LDR PC, =main

    上面的伪指令编译后的结果为: LDR PC, [PC, OFFSET_TO_LPOOL]
                                                                 LPOOL
                                                                                    DCD main

    可见,虽然LDR是把基于PC的一个存储单元LPOOL的内容加载到PC中,但该存储单元中保存的却是链接时所决定的main函数入口的绝对地址,所以main函数实际所在的段不是位置无关。

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

    GPIO_BASE EQU 0x40e00000; GPIO基址寄存器地址
            GPDR0 EQU 0x00c; 相对于GPIO基址寄存器的偏移量
            init_GPDR0 EQU 0xfffbfe00; 寄存器GPDR0初值
            LDR R1, =GPIO_BASE
            LDR R0, =init_GPDR0
            STR R0, [R1, #GPDR0]

    上述汇编代码段经编译后的结果为:

    LDR R1, [PC, OFFSET_TO_GPIO_BASE]
            LDR R0, [PC, OFFSET_TO_init_GPDR0]
            STR R0, [R1, #0xc]
            GPIO_BASE
            DCD 0x40e00000
            GPDR0
            DCD 0x00c
            init_GPDR0
            DCD 0xfffbfe00

    可见,LDR伪指令实际上使用基于PC的偏移量来对符号常量GPIO_BASE和init_GPDR0进行引用,因而是位置无关的。由此可以得出如下结论:使用LDR伪指令将一个常量读取到非PC的其他通用寄存器中可实现位置无关的常量访问;但将一个地址值读取到PC中进行程序跳转时,跳转目标则是位置相关的。

    (2) 程序设计规范2

    其他被ROPI段中的代码引用的必须是绝对地址,或者是基于可读写位置无关(RWPI)段的静态基址寄存器的可写数据。

    使用绝对地址只能引用被重定位到特定位置的代码段中的符号,通过在位置无关代码中引入绝对地址,可以让程序跳转到指定位置。例如,假设Bootloader的阶段1将其自身代码拷贝到链接时所指定的SDRAM地址空间后,当要跳转到阶段2的C程序入口时,可以使用指令“LDR PC, =main”跳转到程序在SDRAM中的main函数入口地址开始执行。这是因为程序在编译链接时给main函数分派绝对地址,系统通过将main函数的绝对地址直接赋给PC实现程序跳转。如果使用相对跳转指令“B main”,那么只会跳转到启动ROM内部的main函数入口。
     

    展开全文
  • -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库...

    -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),

    则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意

    位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

    如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,

    这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于 这个.so文件代码段和数据段内存映射的位置.

    不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码)

    如果被多个应用程序共同使用,那么它们必须每个程序维护一份so的代码副本了.(因为so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)

    non-PIC 与 PIC 代码的区别主要在于 access global data, jump label 的不同。

    如下图所示,是未使用PIC(左侧)和使用了PIC(右侧)后对应函数hello调用的汇编代码。

    bb9dcbbe9b5a7344a7e0e93a89d356a9.png

    比如一条 access global data 的指令,

    non-PIC 的形势是:ld r3, var1

    PIC 的形式则是:ld r3, var1-offset@GOT,意思是从 GOT 表的 index 为 var1-offset 的地方处

    指示的地址处装载一个值,即var1-offset@GOT处的4个 byte 其实就是 var1 的地址。这个地址只有在运行的时候才知道,是由 dynamic-loader(ld-linux.so) 填进去的。

    再比如 jump label 指令

    non-PIC 的形势是:jump printf ,意思是调用 printf。

    PIC 的形式则是:jump printf-offset@GOT,

    意思是跳到 GOT 表的 index 为 printf-offset 的地方处指示的地址去执行,

    这个地址处的代码摆放在 .plt section,

    每个外部函数对应一段这样的代码,其功能是呼叫dynamic-loader(ld-linux.so) 来查找函数的地址(本例中是 printf),然后将其地址写到 GOT 表的 index 为 printf-offset 的地方,

    同时执行这个函数。这样,第2次呼叫 printf 的时候,就会直接跳到 printf 的地址,而不必再查找了。

    转载自:https://dwz.cn/fCIJksbu

    扫码领个红包作为打赏吧~~

    (余额宝支付时可抵现)

    喜欢 (0)or分享 (0)

    展开全文
  • Linux系统编程 28 动态库制作 -生成与位置无关代码 学习笔记 头文件守卫 #ifndef _MYMATH_H_ #define _MYMATH_H_ #endif 动态绑定的概念 只有当调用动态库的函数时候,动态库才会加载到内容, 同时在内存当中绑定...

    Linux系统编程 28 动态库制作 -生成与位置无关代码
    学习笔记

    头文件守卫

    #ifndef _MYMATH_H_
    #define _MYMATH_H_
    #endif

    动态绑定的概念
    只有当调用动态库的函数时候,动态库才会加载到内容,
    同时在内存当中绑定地址进行访问。


    动态库制作及使用:

    1. 将.c 生成.o文件 (要求生成与地址无关的代码-fPIC)

    PIC:Position independent code
    链接的时候:
    数据段合并和地址回填

    hello.o

    main 0
       func1:main+100
       func2:main+200
    |
    |链接
    |
    a.out
        main 1000
          func1:1000+100
          func2:1000+100
          
    动态库的函数在调用的时候,才有它的地址

    动态库的延迟绑定

    汇编中动态库的函数带有@plt 

    这一节没有什么要求
    主要是要记住,生成动态库的时候
    要添加-fPIC 参数

    展开全文
  • 什么是位置有关码和位置无关位置无关码:地址 = PC + 偏移量 位置有关码 :地址 = 链接地址(通过链接脚本指定) 学习代码重定位的时候涉及这两个概念,简单来说:代码运行的时候,是否和所处内存地址相关。...

    什么是位置有关码和位置无关码

    位置无关码:地址 = PC + 偏移量
    位置有关码 :地址 = 链接地址(通过链接脚本指定)
    学习代码重定位的时候涉及这两个概念,简单来说:代码运行的时候,是否和所处内存地址相关。“位置有关码”要求运行时代码必须在特定的地址;而“位置无关码”则没有要求,随便在哪个内存地址都可以运行。
    补充:“位置有关码”和“位置无关码”有点类似于“相对路径”和“绝对路径”,这个不一定对,只是个人这么理解。“位置无关码”的地址是相对于当前PC值的偏移量,类似于“相对路径”,只要相对的偏移量是正确的,放在那里都可以;“位置有关码”的地址是指定的链接地址,类似于“绝对路径”,“绝对路径是唯一的”,所以必须把代码放在指定内存地址。至于为什么位置有关码必须在特定的地址,和链接脚本和硬件平台有关,这个比较底层了,我暂时不需要了解这么深入,以后用到再说吧。

    怎么判断是位置有关码还是位置无关码

    这里简单的总结一下:b、bl、adr、ldr指令是位置无关码,ldr伪指令去加载标号地址是位置有关码。分不清ldr指令和伪指令的可以看博客《LDR指令和LDR伪指令详解》。还想要更深入的了解位置有关码和位置无关码,建议用交叉编译工具链里的objdump工具,通过反汇编文件去查看位置有关码和位置无关码的差异。objdump工具的使用可以参考博客[《反汇编工具objdump的使用以及反汇编文件的解读》]。(https://blog.csdn.net/weixin_42031299/article/details/117577060)

    总结:

    位置有关码和位置无关码是我在学习代码重定位的时候涉及到的概念,作用就是先运行一段位置无关码,将代码重定位到链接地址,接着执行后续的代码。在代码重定位完成之前,是不能运行位置有关码的,否则会出错。所以在写启动代码的时候,要了解这两个概念,用于重定位功能的代码必须都是位置无关码。

    展开全文
  • 当我在Linux上了解到要创建.so文件时,必须为gcc指定-fPIC命令行参数才能创建与位置无关代码,我无法首先相信它。据我所知,elf文件格式支持重定位,就像 - 在我看来更好 - Windows DLL系统工作原理:在Windows上...
  • 为了省去Sqlite3动态链接库在发布时产生不必要的麻烦,这里直接直接使用静态库,同时,由于项目中还存存需要链接sqlite的其他动态库,所以生成的静态库还需要添加“位置无关代码”参数,特此作为笔记。 ##普通...
  • 所以对于位置无关代码区域,跳转一般都使用B指令,而从位置无关代码区域跳转到位置有关指令代码区域去执行就需要借助位置有关跳转指令。 6 加载与运行地址不同 当存储地址与链接地址不同时,多数情况下由于采用位置...
  • 代码重定位到SDRAM后,跳转到SDRAM中的test_uart空函数位置执行,然后返回执行led函数点亮LED,运行后LED不亮,查看反汇编代码如下: 30000050: e59ff010 ldr pc, [pc, #16] ; 30000068 <.text+0x68> 30000068: ...
  • 这样就有了位置无关代码的概念,指代码不在连接时指定的运行地址空间,也可以执行,它一段加载到任意地址空间都能执行的特殊代码。 uboot搬移到DRAM中,然后跳转到DRAM继续运行uboot剩下的代码,那么在搬移之前的这...
  • 大体介绍解释ldr指令B指令二、位置有关无关具体代码分析1.code指令分析B BL指令ADRLDR链接地址和运行地址图解 前言 一、位置有关和无关? 大体介绍 代码的运行分为三个阶段:取指,译码,执行,而取指令肯定要知道...
  • LLVM 目标无关代码生成器1 介绍:LLVM 目标无关代码生成器由 6 个主要的组件组成:1.1 代码生成1.2 代码生成器的高层设计1.3 使用 TableGen 来描述目标平台2 目标描述类2.1 TargetMachine 类2.2 DataLayout 类2.3 ...
  • position-independent code (PIC):用于生成位置无关代码位置无关代码,可以理解为代码无绝对跳转,跳转都为相对跳转。生成动态库时,需要加上-fPIC选项。 在 Linux 系统中,动态链接文件称为动态共享对象 ...
  • 当我了解到在Linux上要创建一个.so文件时,必须为gcc指定-fPIC命令行参数才能创建与位置无关代码,我不敢首先相信它。据我所知,elf文件格式支持重定位,就像-在我看来更好-WindowsDLL系统可以工作:在Windows上,...
  • 云服务器代码放在哪里 内容精选换一换可以。如果您有业务部署在华为云服务器(含弹性公网IP),即可通过华为云备案,与域名注册服务商没有关系。示例:如果您的主体和域名均为第一次备案,即在工信部无任何备案信息。...
  • 关于ARM中的重定位引入:要想弄明白重定义的问题,首先我们需要引入4个概念:链接地址 / 运行地址 / 位置无关码 / 位置有关码这里我们先简单回顾一下三星S5PV210芯片的启动过程(如果想详细了解,请翻我之前的文章):...
  • effective c++条款44 将与参数无关代码抽离templates 首先了解这个条款的含义:使用template可能导致代码膨胀,二进制码会带着重复(或者几乎重复)的代码、数据,或两者。其结果有可能源码看起来合身而整齐,但...
  • 我的理解:在上面公式的定义下,时间步p和时间步p+k的位置编码的内积,即 是与p无关,只与k有关的定值(不妨自行证明下试试)。也就是说,任意两个相距k个时间步的位置编码向量的内积都是相同的,这就相当于蕴含了...
  • 但是我们现在想把该段程序运行时(没法对该段程序进行再次指定地址的编译了)挪动到其它内存区域(程序动态加载功能),要想该段代码仍然能正常运行,就需要对该段代码进行重定位,而不是简单的拷贝该段代码到指定...
  • Swagger(http://swagger.io/) 是一款RESTFUL接口的、基于YAML、JSON语言的文档在线自动生成、代码自动生成的工具。 swagger 2.0 openapi 3.0 nodejs: 12.13.0 swagger-editor : 3.15.8 swagger-codegen : 2.4.9 ...
  • openFoam代码读懂笔记

    2021-08-18 10:13:35
    上一条命令的输出,作为下一条命令参数,如 echo 'yes' | wc -l || 表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo "fail" \ 表示下一行继续 $1在shell中称为“位置参数”,表示传入的第1个...
  • Jacoco是一种为Java VM的环境中的代码覆盖率分析提供的标准技术,重点是提供一个轻量级,灵活且文档齐全的库,以便于和各种构件和开发工具集成,比如当下非常流行的工具:Gradle、IDEA、Jenkins、SonarQube等等,...
  • 发一下牢骚和主题无关:【1、最基本的js弹出对话框窗口代码】这是最基本的js弹出对话框,其实代码就几句非常简略:复制代码 代码如下:因为这是一段javascripts代码,所以它们应当放在标签和之间。是对一些版本低的...
  • CPU执行代码的时候,要么是顺序执行,要么是跳转到其他地址去执行,跳转的话又分为相对跳转和绝对跳转,顺序执行和相对跳转实际上都是相对PC当前位置做一个偏移,这种指令是位置无关指令,而绝对跳转是明确指定跳转...
  • PHP代码注释

    2021-04-29 08:55:30
    写在前面注释可以理解成代码中的解释和说明。使用注释不仅能提高程序的可读性,而且有利于程序的后期维护工作,注释内容不会被程序所执行。个人项目个人站点:LN电影网个人博客:L&N博客PHP 的注释 PHP 注释有 3...
  • 例1: ‘/插入到代码头部,其中 可写成 ,效果一样 例2: ‘/插入到代码中任意位置,其中 可写成 例3: ‘/ 是回车符的16进制形式 例4: ‘/ 是换行符的16进制形式 2.样式表 (1)利用CSS代码@import、expression触发...
  • PHP 代码注释

    2021-03-23 11:18:38
    写在前面注释可以理解成代码中的解释和说明。使用注释不仅能提高程序的可读性,而且有利于程序的后期维护工作,注释内容不会被程序所执行。个人项目个人站点:LN电影网个人博客:L&N博客PHP 的注释PHP 注释有 3 ...
  • HTML代码-边框篇

    2021-06-12 01:06:00
    HTML代码-边框篇2018-09-12表格以和分别作起始标识符。其中,里有一些必要的参数。border参数定义表格边框的粗细,记为border=数值,数值取0,1,2,3等整数。width是我们要定义的参数,它规定表格的宽度,数值通常...
  • Java代码内容概述

    2021-02-26 09:18:02
    B:代码块分类根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。C:常见代码块的应用a:局部代码块在方法中出现;限定变量生命周期,及早释放,提高内存利用率b:构造代码...
  • java中的代码

    2021-03-04 01:43:55
    java中的代码块一共分为以下几种:普通代码块、构造代码块、静态代码块一、普通代码块首先从位置上来说,普通代码块是放在方法中的,普通代码块的执行也是按照代码书写顺序进行执行的,使用代码块可以解决当前方法中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 233,553
精华内容 93,421
关键字:

位置无关代码

友情链接: 实验三.zip