在C(GCC)中对宽字符字符串调用goto
我发现了这段代码:在C(GCC)中对宽字符字符串调用goto,c,gcc,binary,goto,opcode,C,Gcc,Binary,Goto,Opcode,我发现了这段代码: goto*&L"\xfeeb"; 它导致程序永久挂起,显然是通过调用x64指令0xEB和0xFE(由于x64的小端性,按此顺序)0xEB是符合以下条件的JMP 我理解代码的作用,它相当于运行指令的函数0xEB 0xFE,因此它也可以写成int(*foo)(=L“\xfeeb”;foo(),或者如果我们真的想弄糊涂,((int(*)L“\xfeeb”)()。这是因为在Linux上默认情况下字符串被标记为可执行 然而,goto确实很严格。我不明白为什么goto*&L“\
goto*&L"\xfeeb";
它导致程序永久挂起,显然是通过调用x64指令0xEB
和0xFE
(由于x64的小端性,按此顺序)0xEB
是符合以下条件的JMP
我理解代码的作用,它相当于运行指令的函数0xEB 0xFE
,因此它也可以写成int(*foo)(=L“\xfeeb”;foo()代码>,或者如果我们真的想弄糊涂,((int(*)L“\xfeeb”)()代码>。这是因为在Linux上默认情况下字符串被标记为可执行
然而,goto
确实很严格。我不明白为什么goto*&L“\xfeeb”
完全有效,或者疯狂的指针魔法*&
正在做什么,或者为什么必须使用宽标记L
。有人能解释一下吗?如果我冒昧猜测,编写代码的人是在滥用。此功能旨在制作跳转表、便携式JIT编译器或其他切换…case
速度太慢的东西
C允许您转到标签
label1:
...
goto label1;
GCC允许您使用&&
运算符获取标签的地址。要跳转到地址foo
,只需goto*foo代码>
label1:
void *ptr = &&label1;
...
goto *ptr;
简单回顾一下,C标准指定goto
语句后面的参数是label类型的标记。GCC添加了一个扩展,其中goto
语句后面的参数也可能是指向可执行代码的指针
因此,您可以goto
任何有指针的内存块。在Linux上,这包括字符串文本
goto *&"\xe8\r\0\0\0Hello, World!Yj\1[j\rZj\4X\xcd\x80,\f\xcd\x80";
L“\xfeeb”
是由wchar\u t
类型的字符组成的宽字符串文字,而不是char
。作为旧式字符串文字编写,它应该是“\xeb\xfe”
。我怀疑字符串文本中的L
是用于a的。如果您想尝试所有这些模糊的代码段,而不需要自己单独编译,您可以使用在线C编译器:和GCC()。不支持它。@user202729仍然不理解GCC的哪个部分决定允许它。“编写代码的人”GCC扩展允许goto*foo代码>其中foo
属于void*
类型。由于一个bug,它似乎允许foo
为非void*
的指针类型。另见和。