[英]Jump to a label from inline assembly to C
I have a written piece of code in assembly and at some points of it, I want to jump to a label in C
.我在汇编中有一段编写好的代码,在某些方面,我想跳转到
C
的标签。 So I have the following code (shortened version but still, I am having the same problem):所以我有以下代码(缩短版本,但我仍然遇到同样的问题):
#include <stdio.h>
#define JE asm volatile("jmp end");
int main(){
printf("hi\n");
JE
printf("Invisible\n");
end:
printf("Visible\n");
return 0;
}
This code compiles, but there is no end
label in the disassembled version of the code.这段代码可以编译,但在反汇编版本的代码中没有
end
标签。
If I change the label name from end
to any other thing (let's say l1
, both in asm code( jmp l1
) and in the C
code), the compiler says that如果我将标签名称从
end
更改为任何其他名称(假设是l1
,无论是在 asm 代码( jmp l1
)还是在C
代码中),编译器都会说
main.c:(.text+0x6b): undefined reference to `l1'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'main' failed
make: *** [main] Error 1
I have tried different things(different length, different cases, upper, lower, etc.) and I think it only compiles with end
label.我尝试了不同的东西(不同的长度、不同的情况、上、下等),我认为它只能用
end
标签编译。 And with end
label, I am receiving segmentation fault because, there is no end
label in the disassembled version.对于
end
标签,我收到分段错误,因为反汇编版本中没有end
标签。
Compiled with: gcc -O0 main.c -o main编译: gcc -O0 main.c -o main
Disassembled code:反汇编代码:
000000000000063a <main>:
63a: 55 push %rbp
63b: 48 89 e5 mov %rsp,%rbp
63e: 48 8d 3d af 00 00 00 lea 0xaf(%rip),%rdi # 6f4 <_IO_stdin_used+0x4>
645: e8 c6 fe ff ff callq 510 <puts@plt>
64a: e9 c9 09 20 00 jmpq 201018 <_end> # there is no _end label!
64f: 48 8d 3d a1 00 00 00 lea 0xa1(%rip),%rdi # 6f7 <_IO_stdin_used+0x7>
656: e8 b5 fe ff ff callq 510 <puts@plt>
65b: 48 8d 3d 9f 00 00 00 lea 0x9f(%rip),%rdi # 701 <_IO_stdin_used+0x11>
662: e8 a9 fe ff ff callq 510 <puts@plt>
667: b8 00 00 00 00 mov $0x0,%eax
66c: 5d pop %rbp
66d: c3 retq
66e: 66 90 xchg %ax,%ax
So, the questions are:所以,问题是:
l1
but can find end
?l1
但可以找到end
?This is what asm goto
is for.这就是
asm goto
的用途。 GCC Inline Assembly: Jump to label outside block GCC 内联汇编:跳转到块外的标签
Note that defining a label inside another asm statement will sometimes work (eg with optimization disabled) but IS NOT SAFE.请注意,在另一个 asm 语句中定义标签有时会起作用(例如禁用优化)但不安全。
asm("end:"); // BROKEN; NEVER USE
// except for toy experiments to look at compiler output
GNU C does not define the behaviour of jumping from one asm statement to another without asm goto
. GNU C 没有定义从一个 asm 语句
asm goto
到另一个没有asm goto
。 The compiler is allowed to assume that execution comes out the end of an asm
statement and eg put a store after it.允许编译器假设执行出现在
asm
语句的末尾,例如在它之后放置一个存储。
The C end:
label within a given function won't just have the asm symbol name of end
or _end:
- that wouldn't make sense because separate C functions are each allowed to have their own end:
label.给定函数中的 C
end:
标签不会只有end
或_end:
的 asm 符号名称_end:
- 这没有意义,因为每个单独的 C 函数都允许有自己的end:
标签。 It could be something like main.end
but it turns out GCC and clang just use their usual autonumbered labels like .L123
.它可能类似于
main.end
但事实证明 GCC 和 clang 只是使用他们通常的自动编号标签,如.L123
。
Then how this code works: https://github.com/IAIK/transientfail/blob/master/pocs/spectre/PHT/sa_oop/main.c
那么这段代码是如何工作的: https : //github.com/IAIK/transientfail/blob/master/pocs/spectre/PHT/sa_oop/main.c
It doesn't;它没有; the
end
label that asm volatile("je end");
asm volatile("je end");
的end
标签asm volatile("je end");
references is in the .data
section and happens to be defined by the compiler or linker to mark the end of that section .引用位于
.data
节中,恰好由编译器或链接器定义以标记该节的结尾。
asm volatile("je end")
has no connection to the C label in that function. asm volatile("je end")
与该函数中的 C 标签没有联系。
I commented out some of the code in other functions to get it to compile without the "cacheutils.h" header but that didn't affect that part of the oop()
function;我注释掉了其他函数中的一些代码,让它在没有“cacheutils.h”头的情况下编译,但这并没有影响
oop()
函数的那部分; see https://godbolt.org/z/jabYu3 for disassembly of the linked executable with JE_4k changed to JE_16 so it's not huge.请参阅https://godbolt.org/z/jabYu3以了解链接的可执行文件的反汇编,其中 JE_4k 更改为 JE_16,因此它不是很大。 It's disassembly of a linked executable so you can see the numeric address of
je 6010f0 <_end>
while the oop
function itself starts at 4006e0 and ends at 400750. (So it doesn't contain the branch target).它是链接可执行文件的反汇编,因此您可以看到
je 6010f0 <_end>
的数字地址,而oop
函数本身从 4006e0 开始并在 400750 结束。(因此它不包含分支目标)。
If this happens to work for Spectre exploits, that's because apparently the branch is never actually taken.如果这恰好适用于 Spectre 漏洞利用,那是因为显然该分支从未真正被采用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.