Когда используется.ARM.exidx

Я работаю над Contiki 2.7 с целью mbxxx. При создании моего кода компоновщик жаловался на перекрытие разделов.ARM.exidx и.data. После некоторой работы со скриптом компоновщика contiki-2.7/cpu/stm32w108/gnu-stm32w108.ld я исправил проблему, заменив:

__exidx_start = .;
__exidx_end = .;

с:

.ARM.exidx : {
    __exidx_start = .;
    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    __exidx_end = .;
} >ROM_region

Позже, когда я попытался просмотреть список заголовков некоторых других примеров приложений с помощью objdump -h, я не нашел этот конкретный раздел.ARM.exidx, хотя он присутствует в моем приложении. Поиск в Google.ARM.exidx привел меня к тому факту, что он используется для обработки некоторых исключений в C++. Поскольку мой код является чистым кодом C, почему этот раздел присутствует в моем коде? Когда, как правило,.ARM.exidx присутствует в коде и в чем его полезность?

================================================== ================================

Ну нет, у меня нет таких опций компилятора. Я на самом деле использую API AxTLS, вырвал код обработки сертификата и портировал его на contiki. При дальнейшем копании я обнаружил подозрительное поведение в реализации bigint. Чтобы быть кратким... вот тело функции из файла bigint.c:

static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
{
   int j = 0, n = bia->size;
   bigint *biR = alloc(ctx, n + 1);
   comp carry = 5;
   comp *r = biR->comps;
   comp *a = bia->comps;

   check(bia);

   /* clear things to start with */
   memset(r, 0, ((n+1)*COMP_BYTE_SIZE));


   do
   {
       long_comp tmp = *r + (long_comp)a[j]*b + carry;
   //    *r++ = (comp)tmp;              /* downsize */
       carry = (comp)(tmp >> COMP_BIT_SIZE);
   } while (++j < n);

  // *r = carry;
  bi_free(ctx, bia);

  return trim(biR);
}

если закомментированные части (присвоение переменной r) не закомментированы, появляется вещь.ARM.exidx, в противном случае это не так! Теперь это можно объяснить???

================================================== ================================

Я не нашел ничего необычного в реализации alloc(), Было 2 упоминания alloca() используется в какой-то отдельной области кода, который я заменил malloc() а также free(), но это тоже не решило проблему. alloc() реализация имеет только призывы к malloc(),realloc() а также free()

2 ответа

.ARM.exidx это раздел, содержащий информацию для разматывания стека. Если в вашей C-программе есть функции, которые выводят обратный след стека, функции, скорее всего, будут зависеть от наличия этого раздела.

Может быть, искать -funwind-tables или же -fexceptions пометьте в настройках вашего компилятора.

Эта функция используется в 'C'. ARM APCS использует только указатель кадра для восстановления стека. Более новый AAPCS иногда использует таблицы. Размотка стека, обработчики сигналов и другие асинхронные функции C используют этот механизм. В случае встроенного устройства без покрытия его можно использовать для трассировки стека. Например, в Linux unwind.c используются обаexidx а также extab разделы для трассировки стека.

Вкратце exidx представляет собой отсортированную таблицу стандартных начальных адресов и extabуказатель таблицы. Бинарный поиск поexidx найдет соответствующий extabвход. Вextabзапись содержит подробную информацию о стеке в этой подпрограммеПримечание1. Он дает подробную информацию о том, что процедура хранит в стеке.

если закомментированные части (присвоение переменной r) раскомментированы, появится.ARM.exidx, в противном случае - нет! Теперь это можно объяснить???

Когда у вас есть заявление *r++ = (comp)tmp;, компилятор не может хранить все переменные в регистрах и должен использовать стек (или, по крайней мере, fp). Это заставляет его излучать иexidx а также extab данные.


Есть несколько решений. Это нормально отказаться от обоихexidx а также extabесли вам не нужна трассировка стека или асинхронная функциональность. Более простая раскрутка стека может быть выполнена с помощью gnu tools / gcc, используя-mapcs-frame; тогдаfp всегда будет использоваться для хранения предыдущего кадра стека (в котором хранятся его вызывающие fp, так далее). Фактические столы не такие уж большие, а процедуры раскрутки довольно просты. Это может быть <3% накладных расходов, чтобы иметь таблицы, которые не загрязняют нормальный путь к программе или не используют регистр, например-mapcs-frame. Желательно для процессора Cortex-A с кешем и обычно большим объемом памяти.

Ссылка: Объяснение указателя ссылки и кадра ATPCS

Примечание 1: это происходит после того, как пролог вносит изменения в стек.
Примечание 2:ex предназначен для исключения, но не только для исключений C++.

Добавляя к ответу tangrs, если вы используете gcc -v, вы можете сбросить параметры по умолчанию, используемые во время компиляции.

Все опции (неявные и явные) опции GCC передаются в программу cc1 GCC.

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