Программно вызвать исключение Undefined Instruction

Я хочу вызвать исключение неопределенной инструкции ARM Cortex-M3 для теста моего тестового прибора. Компилятор IAR поддерживает это с помощью встроенной сборки следующим образом:

asm ("udf.w # 0");

К сожалению, встроенный ассемблер GNU CC не знает этот код операции для NXP LPC177x8x. Это пишет диагностику:

ccw3kZ46.s:404: Error: bad instruction `udf.w #0'

Как я могу создать функцию, которая вызывает исключение Undefined Instruction?

4 ответа

Опираясь на ответ Masta79:

В справочном руководстве по архитектуре ARMv7-M приведена кодировка "навсегда неопределенная" - ARM DDI 0403D ( заполнитель документации, требуется регистрация). Кодировка - 0xf7fXaXXX (где "X" игнорируется). Конечно, выборки инструкций имеют младший порядок, поэтому (без тестирования):

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

должен давать гарантированную неопределенную инструкцию на любом процессоре ARMv7-M или новее.

Некоторая дополнительная информация...

Одна из встроенных функций GCC

void __builtin_trap (void)

Эта функция приводит к аварийному завершению программы. GCC реализует эту функцию, используя целевой механизм (например, намеренное выполнение недопустимой инструкции) или вызывая прерывание. Используемый механизм может варьироваться от релиза к релизу, поэтому не стоит полагаться на какую-либо конкретную реализацию.

Его реализация для 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")]
)

Так что для режима ARM сгенерирует gcc 0x7f000f0 (f0 00 f0 07)и для других режимов 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)

Для LLVM __builtin_trap генерируемые значения 0xe7ffdefe а также 0xdefe:

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;
}

В [1] есть разные официальные неопределенные инструкции (ищите UDF; . ниже можно заменить любой шестнадцатеричной цифрой):

  • 0xe7f...f. - кодировка ARM или A1 (ARMv4T, ARMv5T, ARMv6, ARMv7)
  • 0xde.. - кодирование большого пальца или T1 (ARMv4T, ARMv5T, ARMv6, ARMv7)
  • 0xf7f.a... - кодировка Thumb2 или T2 (ARMv6T2, ARMv7)

Есть и другие, но они, вероятно, так же, как и будущее.

Что касается генерации кода, который его запускает, вы можете просто использовать .short или же .word, как это:

  • asm volatile (".short 0xde00\n"); / * большой палец незаконная инструкция */
  • asm volatile (".word 0xe7f000f0\n"); / * вооружить незаконную инструкцию */
  • asm volatile (".word 0xe7f0def0\n"); / * рука + палец недопустимая инструкция */

Обратите внимание, что последний будет декодировать в 0xdef0, 0xe7f0 в контексте большого пальца, и, следовательно, также вызвать неопределенное исключение инструкции.

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

Версия thumb-16 постоянно неопределенной инструкции 0xDExx, Таким образом, вы можете сделать это в своем коде, чтобы вызвать исключение:

.short 0xde00

Ссылка: Справочное руководство по архитектуре ARMv7-M, раздел A5.2.6.

(Обратите внимание, что кодирование 0xF7Fx, 0xAxxx также постоянно не определено, но является 32-битной инструкцией.)

Другие вопросы по тегам