我有以下代码:
void print(const char* str){
system_call(4,1,str,strlen(str)); }
void foo2(void){ print("goo \n");}
void buz(void){ ...}
int main(){
char buf[256];
void (*func_ptr)(void)=(void(*)(void))buf;
memcpy(buf,foo2, ((void*)buz)-((void*)foo2));
func_ptr();
return 0;
}
问题是,为什么这个代码会掉线?
答案是,关于调用函数而不是通过指针的东西是相对地址,但我还没弄清楚这里有什么问题?哪一行是有问题的?
谢谢你的帮助
答案 0 :(得分:3)
首先,没有任何内容表明foo2()和buz()必须在内存中彼此相邻。另一方面,正如您所猜测的那样,代码必须是相对于像这样的特技工作的相对代码。但最重要的是,标准不允许这样做。
正如Chris Luts所提到的,堆栈(自动)变量在许多操作系统上都不可执行,以防止攻击。
答案 1 :(得分:2)
main()函数中的前两行是有问题的。
第1行。(void(*)(void))buf
将buf转换为函数指针是未定义的
第2行。((void*)buz)-((void*)foo2)
除非指针指向同一个数组,否则指针的减法是未定义的。
此外,Section 5.8 Functions
的{{1}}说“虽然指向函数的指针通常被认为是内存中函数代码的地址,但在某些计算机上,函数指针实际指向一个块调用函数所需的信息。“
答案 2 :(得分:1)
首先,C函数指针机制用于等签名函数调用抽象。如果没有这些特技,这是非常强大且容易出错的。
我无法看到尝试将代码从一个地方复制到另一个地方的优势/意义。正如一些人所评论的那样,在C函数中判断相对性/可重新定位代码的数量并不容易。
您尝试将函数的代码复制到数据存储区域。一些微控制器会告诉你“嗡嗡声!”。在具有数据/程序分离存储器的机器体系结构上,给定非常理解的编译器(或识别数据/代码修饰符/属性的编译器),它将编译为特定的代码数据移动指令。接缝它会起作用......但是,即使在数据/代码分离的内存中,也不可能执行数据存储器指令。
另一方面,在“普通”数据/代码共享存储器PC中,可能它也不起作用,因为在处理器的MMU上(由加载器)声明了数据/代码段。根据处理器和操作系统的不同,尝试在数据段上运行代码是一种分段错误。