4

我有这个“程序集”文件(仅包含指令

// declare protected region as somewhere within the stack
.equiv prot_start, $stack_top & 0xFFFFFF00 - 0x1400
.equiv prot_end,   $stack_top & 0xFFFFFF00 - 0x0C00

结合此链接器脚本:

SECTIONS {
   "$stack_top"   = 0x10000;
}

组装产生这个输出

file.s: Assembler messages:
file.s: Error: invalid operands (*UND* and *ABS* sections) for `&' when setting `prot_start'
file.s: Error: invalid operands (*UND* and *ABS* sections) for `&' when setting `prot_end'

我怎样才能使这项工作?

4

2 回答 2

3

为什么不可能?

您已链接到 GAS 文档,但这种无能的原因是什么?

答:GAS 必须通过 ELF 目标文件将操作传达给链接器,像这样可以传达的唯一内容是+and -(-只是+一个负值)。所以这是 ELF 格式的一个基本限制,而不仅仅是 GAS 开发人员的懒惰。

当 GAS 编译到目标文件时,将遵循一个链接步骤,它是重定位将决定符号的最终值。

问题:为什么可以+传达,但不能&

答案:因为+是及物的:(a + b) + c == a + (b + c)+&不是“一起传递的”:(a & b) + c!= a & (b + c)

让我们看看如何+通过 ELF 格式传达来说服自己这&是不可能的。

不熟悉的先了解一下什么是重定位:https ://stackoverflow.com/a/30507725/895245

让我们用另一个会产生相同错误的示例来最小化您的示例:

a: .long s
b: .long s + 0x12345678
/* c: .long s & 1 */
s:

编译和反编译:

as --32 -o main.o main.S
objdump -dzr main.o

输出包含:

00000000 <a>:
   0:   08 00                   or     %al,(%eax)
            0: R_386_32 .text
   2:   00 00                   add    %al,(%eax)

00000004 <b>:
   4:   80 56 34 12             adcb   $0x12,0x34(%esi)
            4: R_386_32 .text

忽略反汇编,因为这不是代码,只看符号、字节和重定位。

我们有两次R_386_32搬迁。根据 IA-32 的 System V ABI(定义 ELF 格式),该类型的重定位计算如下:

S + A

在哪里:

  • S:目标文件中重定位前的值。

    a重定位前的值== 08 00 00 00==8小端

    b重定位前的值== 80 56 34 12==0x12345680小端

  • A: addend,重定位项的字段,在这里0(未显示objdump),所以让我们忘记它。

搬迁发生时:

  • a将替换为:

    address of text section + 8
    

    有一个+ 8因为s:是文本部分的第 8 个字节,前面是 2 个 long。

  • b将替换为:

     address of text section + (0x12345678 + 8)
     ==
     address of text section + 0x12345680
    

    啊哈,这就是为什么0x12345680出现在目标文件上的原因!

所以正如我们刚刚看到的,可以+通过添加到实际偏移量来表达 ELF 文件。

但是用这种机制(或者我知道的任何其他机制)是不可能表达&的,因为我们不知道重定位后文本部分的地址是什么,所以我们不能应用&它。

于 2015-10-22T08:54:53.427 回答
1

该死:

中缀运算符

中缀运算符有两个参数,两边各一个。运算符具有优先级,但具有相同优先级的运算从左到右执行。除了+or -,两个参数都必须是 absolute,结果是绝对的。

于 2013-08-28T19:52:33.677 回答