在 x86 中,GCC 想要调用时会生成以下指令__stack_chk_fail
:
; start of the basic block
00000757 call sub_590 ; __stack_chk_fail@plt
0000075c add byte [ds:eax], al
0000075e add byte [ds:eax], al
; start point of another function
类似的行为发生在 ARM 中:
; start of the basic block
00001000 bl __stack_chk_fail@PLT
00001004 dd 0x0000309c ; data entry, NOT executable indeed!
在静态分析工具中,当人们想要构建一个 CFG 时,CFG 算法无法确定__stack_chk_fails
调用的基本块的最后一条指令。
在调用后有某种返回__stack_chk_fail
指令是合理的,以防止 CPU 执行它不应该执行的指令(或潜在的数据条目)。
在这些情况下,CFG 生成器算法假定它是一个常规函数调用,并继续遍历另一个函数的代码(在前一个示例中)或数据条目(在后一个示例中),这是完全不需要的。
所以,我的问题是为什么 GCC 不在基本块的终点插入return(或branch )指令?