我一直在想.我知道编译器会将您编写的代码转换为二进制文件,但链接器的作用是什么?对我来说,它们一直是个谜.
我粗略地理解'链接'是什么.当对库和框架的引用添加到二进制文件时.除此之外我什么都不懂.对我来说它"只是有效".我也理解动态链接的基础知识,但没有太深入.
有人可以解释这些条款吗?
我正在浏览本教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html
第一行组装是:
ldr r0,=0x20200000
第二个是:
mov r1,#1
我以为ldr是将值从内存加载到寄存器中.但似乎=意味着0x20200000是一个值而不是内存地址.两条线似乎都在加载绝对值.
我正在跟随剑桥大学的Baking Pi课程,其中一个简单的操作系统是在ARMv6指令集中构建的,目标是Raspberry Pi.
ldr到目前为止,我们一直使用两种方法通过指令将数据加载到寄存器中,现在我意识到我正在使用它们,我不完全理解它们的作用.
所以我使用的东西ldr r0,=0x20200000,我实际上理解为"将存储在存储单元0x20200000的数据读入寄存器r0.
然后我用过以下的东西:
ldr r0,[r1,#4]
我已经理解为"读取存储在r1指向的存储器地址的数据,以4字节的偏移量进入寄存器r0".
然后我遇到了这个:
ldr r0,=pattern
ldr r0,[r0]
pattern这里是一个.int在.data部分(表示接通/断开状态的用于LED的序列的位图).我在阅读本文时意识到,我之前的理解=foo一定是错的,否则上述两条指令都会做同样的事情.
是=x语法基本都像在C的指针,而[x]语法如果被指向的内存x实际上是读?
让我们说ptr下面的C是一个int*,我的评论是否考虑等效组装(概念上,不是字面意思)有意义吗?
r0 = ptr;     /* equivalent to: ldr r0,=ptr     */
r0 = *ptr;    /* equivalent to: ldr r0,[ptr]    */
r0 = *(ptr+4) /* equivalent to: ldr r0,[ptr,#4] */
我一直在阅读 gcc 生成的一些不同的arm汇编代码,并且遇到了一些我在规范中找不到的东西。
movw    r0, #39784
movt    r0, 1
显然,第一个是将值 39784 移动到底部 16 位或 r0,但 movt 的操作数“1”很奇怪,因为它前面没有哈希,而且我的印象是立即值需要哈希。在某些情况下它是可选的吗?或者我错过了一些神奇的东西?
我正在使用GNU AS作为汇编程序,我正在尝试编写与位置无关的二进制文件,并且在编写外部符号的PC相对地址时遇到了一些问题.Normaly是一个相对地址
adr r0, symbol
但这仅适用于汇编文件中同一部分中定义的符号.另一种加载符号的方法是
ldr r0, =symbol
它将符号的绝对地址存储在一个常量中,并从那里加载它的pc.所以你得到这样的代码:
  48:   e59f0008        ldr     r0, [pc, #8]    ; 58 <text+0xc>
  ...
  58:   00000008        .word   0x00200018
                        58: R_ARM_ABS32 symbol
但我需要的是一个R_ARM_REL32链接器引用.
我想出的是这段代码:
tmp1:    ldr    r0, [pc, #tmp2 - tmp1 - 8]
         ldr    r0, [pc, r0]
tmp2:    .word  symbol - tmp1
这会产生:
0000003c <tmp1>:
  3c:   e59f0000        ldr     r0, [pc]        ; 44 <tmp2>
  40:   e79f0000        ldr     r0, [pc, r0]
00000044 <tmp2>:
  44:   00000008        .word   0x00000008
                        44: R_ARM_REL32 symbol
我几乎可以将它放入一个宏中,因此它可以重用于我需要的任何符号.除了我不知道如何告诉汇编程序tmp2需要转到常量块而不是在代码中间结束.
但是在GNU AS中是不是已经存在一些现有的语法或宏?
我注意到ARM 64位程序集的GNU asm 重定位语法.什么是喜欢那件#:abs_g0_nc:和:pg_hi21:?他们在哪里解释?他们是否有一种模式,或者他们是否在旅途中弥补?我在哪里可以了解更多?
首先,我尝试对其进行一些逆向工程:
printf '
#include <stdio.h>
int main() {
    puts("hello world");
}
' > main.c
gcc -std=c99 -pie -fpie -ggdb3 -o pie main.c
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
readelf -s ./pie | grep -E 'main$'
gdb -batch -nh \
  -ex 'set disable-randomization off' \
  -ex 'start' -ex 'info line' \
  -ex 'start' -ex 'info line' \
  -ex 'set disable-randomization on' \
  -ex 'start' -ex 'info line' \
  -ex 'start' -ex 'info line' \
  ./pie \
;
输出:
64: 000000000000063a    23 …assembly ×5
arm ×4
gcc ×2
linker ×2
aslr ×1
c++ ×1
glibc ×1
linux ×1
linux-kernel ×1
relocation ×1