以编程方式导致未定义的指令异常

har*_*per 8 gcc arm cortex-m3 inline-assembly

我想在测试夹具的测试中引起ARM Cortex-M3未定义指令异常.IAR编译器支持这种内联汇编,如下所示:

asm("udf.w#0");

不幸的是,GNU CC内联汇编程序不知道NXP LPC177x8x的这个操作码.它写诊断:

ccw3kZ46.s:404: Error: bad instruction `udf.w #0'
Run Code Online (Sandbox Code Playgroud)

如何创建导致未定义指令异常的函数?

uni*_*urf 10

Masta79的回答基础上:

ARMv7-M体系结构参考手册中列出了"永久未定义"编码 - ARM DDI 0403D(文档占位符,需要注册).编码为0xf7fXaXXX(其中"X"被忽略).当然,指令提取是little-endian,所以(没有测试):

asm volatile (".word 0xf7f0a000\n");

应该在任何ARMv7-M或更高版本的处理器上产生有保证的未定义指令.

  • Cortex-M3只有Thumb模式.但Thumb是Thumb-2扩展,这意味着有16位和32位指令."永久未定义"的是32位的. (2认同)
  • 我认为你不应该在这里手动更改字节序。汇编器将根据需要自动交换字节序。 (2认同)

JP *_*oad 6

永久未定义指令的thumb-16版本为0xDExx。因此,您可以在代码中执行此操作以触发异常:

.short 0xde00
Run Code Online (Sandbox Code Playgroud)

参考:《 ARMv7-M体系结构参考手册》,第A5.2.6节。

(请注意,0xF7Fx,0xAxxx编码也是永久未定义的,但它是32位指令。)


aus*_*len 6

一些额外的信息...

GCC的内置程序之一

void __builtin_trap(void)

此功能导致程序异常退出。GCC通过使用依赖于目标的机制(例如有意执行非法指令)或通过调用abort 来实现此功能。发行版本之间使用的机制可能有所不同,因此您不应依赖任何特定的实现。

对ARMv7实现

(define_insn "trap"
  [(trap_if (const_int 1) (const_int 0))]
  ""
  "*
  if (TARGET_ARM)
    return \".inst\\t0xe7f000f0\";
  else
    return \".inst\\t0xdeff\";
  "
  [(set (attr "length")
    (if_then_else (eq_attr "is_thumb" "yes")
              (const_int 2)
              (const_int 4)))
   (set_attr "type" "trap")
   (set_attr "conds" "unconditional")]
)
Run Code Online (Sandbox Code Playgroud)

因此,对于ARM模式,gcc将生成0x7f000f0 (f0 00 f0 07);对于其他模式,gcc将生成0xdeff (ff de)(在拆卸/调试时非常方便)。

另请注意

these encodings match the UDF instruction that is defined in the most
recent edition of the ARM architecture reference manual.

Thumb: 0xde00 | imm8  (we chose 0xff for the imm8)
ARM: 0xe7f000f0 | (imm12 << 8) | imm4  (we chose to use 0 for both imms)
Run Code Online (Sandbox Code Playgroud)

对于LLVM __builtin_trap生成的值是0xe7ffdefe0xdefe

case ARM::TRAP: {
  // Non-Darwin binutils don't yet support the "trap" mnemonic.
  // FIXME: Remove this special case when they do.
  if (!Subtarget->isTargetDarwin()) {
    //.long 0xe7ffdefe @ trap
    uint32_t Val = 0xe7ffdefeUL;
    OutStreamer.AddComment("trap");
    OutStreamer.EmitIntValue(Val, 4);
    return;
  }
  break;
}
case ARM::tTRAP: {
  // Non-Darwin binutils don't yet support the "trap" mnemonic.
  // FIXME: Remove this special case when they do.
  if (!Subtarget->isTargetDarwin()) {
    //.short 57086 @ trap
    uint16_t Val = 0xdefe;
    OutStreamer.AddComment("trap");
    OutStreamer.EmitIntValue(Val, 2);
    return;
  }
  break;
}
Run Code Online (Sandbox Code Playgroud)


dom*_*men 5

[1]中有不同的官方未定义说明(查找UDF;.下面可以用任何十六进制数字代替):

  • 0xe7f...f. -ARM或A1编码(ARMv4T,ARMv5T,ARMv6,ARMv7,ARMv8)
  • 0xde.. -Thumb或T1编码(ARMv4T,ARMv5T,ARMv6,ARMv7,ARMv8)
  • 0xf7f.a... -Thumb2或T2编码(ARMv6T2,ARMv7,ARMv8)
  • 0x0000.... -ARMv8-A永久未定义

还有其他一些,但是这些可能会尽可能地适应未来的发展。

至于生成触发它的代码,您可以使用.short.word,如下所示:

  • asm volatile (".short 0xde00\n"); / *拇指非法指示* /
  • asm volatile (".word 0xe7f000f0\n"); / *手臂非法指示* /
  • asm volatile (".word 0xe7f0def0\n"); / * arm + thumb非法指令* /

请注意,最后一个将在Thumb上下文中解码为0xdef00xe7f0因此也会导致未定义的指令异常。

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html

[2] DDI0487D_b_armv8_arm.pdf

  • 从Binutils 2.29.51.20170811开始的@PeterCordes GNU as将udf 0x1234组装成f4 23 f1 e7(至少使用统一语法)。 (2认同)