我有这个“汇编”文件(仅包含directives)
// 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'
我该如何做到这一点?
答案 0 :(得分:3)
为什么不可能?
您已与GAS文档相关联,但无效的理由是什么?
答案:GAS必须通过ELF目标文件向链接器传达操作,唯一可以传达的事情是+
和-
(-
只是{{} 1}}负值)。所以这是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
次搬迁。从用于IA-32的System V ABI(定义ELF格式),该类型的重定位计算如下:
R_386_32
其中:
S + A
:目标文件中重定位前的值。
在重定位之前S
的值= a
== 08 00 00 00
在小端
重定位前8
的值= b
== 80 56 34 12
小端
0x12345680
:addend,重新分配条目的字段,此处A
(0
未显示),所以让我们忘掉它。
重新安置时:
objdump
将替换为:
a
有address of text section + 8
因为+ 8
是文本部分的第8个字节,前面有2个长。
s:
将替换为:
b
啊哈,这就是 address of text section + (0x12345678 + 8)
==
address of text section + 0x12345680
出现在目标文件上的原因!
正如我们刚刚看到的那样,只需添加到实际偏移量就可以在ELF文件上表达0x12345680
。
但是不可能用这种机制(或我所知道的任何其他机制)来表达+
,因为我们不知道重定位后文本部分的地址是什么,所以我们不能将&
应用于此。
答案 1 :(得分:1)
织补:
Infix Operators
中缀运营商采用两个参数,一个在两边。运算符具有优先权,但具有相同优先级的运算从左到右执行。 除了
+
或-
之外,两个参数都必须是绝对的,结果是绝对的。