I'm reverse engineering an ARM binary written in Go, and the following code sequence occurs fairly often (from runtime.cgoIsGoPointer):
BL runtime.panicindex
DCD 0xF7FABCFD
or, from runtime.panicmem:
BL runtime.gopanic
DCD 0xF7FABCFD
0xF7FABCFD is an undefined instruction, so I'm curious what it's purpose is. I think the answer may be related to this question, because compiling for x86 produces the following sequence of instructions in the corresponding functions:
callq runtime.panicindex
ud2
and
callq runtime.gopanic
ud2
It looks like the linux kernel uses different instructions for this purpose. From arch/arm/include/asm/bug.h:
/*
* Use a suitable undefined instruction to use for ARM/Thumb2 bug handling.
* We need to be careful not to conflict with those used by other modules and
* the register_undef_hook() system.
*/
#ifdef CONFIG_THUMB2_KERNEL
#define BUG_INSTR_VALUE 0xde02
#define BUG_INSTR(__value) __inst_thumb16(__value)
#else
#define BUG_INSTR_VALUE 0xe7f001f2
#define BUG_INSTR(__value) __inst_arm(__value)
#endif
But there is reference to 0xf7fabcfd in some of the Go internals. From cmd/internal/obj/arm/asm5.go:
// This is supposed to be something that stops execution.
// It's not supposed to be reached, ever, but if it is, we'd
// like to be able to tell how we got there. Assemble as
// 0xf7fabcfd which is guaranteed to raise undefined instruction
// exception.
case 96: /* UNDEF */
o1 = 0xf7fabcfd
Anyway, can anyone confirm this suspicion and/or shed more light into why this is done? Also, why not just use 0xe7f001f2 like the linux kernel does?