14

私は mbxxx ターゲットで Contiki 2.7 に取り組んでいます。私のコードをビルドしている間、リンカは .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 セクションが見つかりませんでしたが、それはアプリケーションに存在していました。.ARM.exidx についてグーグルで調べたところ、C++ の例外処理に使用されていることがわかりました。私のコードは純粋な C コードなので、なぜこのセクションが私のコードにあるのですか? 通常、.ARM.exidx がコードに存在するのはいつで、そのユーティリティは何ですか?

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

いいえ、そのようなコンパイラ オプションはありません。私は実際に AxTLS API を使用しており、証明書を処理するコードを切り取って 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()

4

3 に答える 3

19

.ARM.exidxスタックをアンワインドするための情報を含むセクションです。C プログラムにスタック バックトレースを出力する関数がある場合、関数はこのセクションの存在に依存する可能性があります。

-funwind-tablesコンパイラ オプションでまたは-fexceptionsフラグを探してください。

于 2014-02-03T12:45:43.197 に答える
3

この機能は「C」で使用されます。ARM APCS は、フレーム ポインタのみを使用してスタックを復元します。新しい AAPCS では、テーブルを使用する場合があります。スタックの巻き戻し、シグナル ハンドラ、およびその他の非同期'C' 機能は、これらのメカニズムを使用します。ベアメタル組み込みデバイスの場合、スタックのトレースに使用できます。たとえば、Linux のunwind.cexidxは、セクションとセクションの両方を使用extabしてスタック トレースを実行します。

簡単に言うと、ルーチンの開始アドレスとテーブル インデックスexidxのソートされたテーブルです。extabをバイナリ検索するexidxと、対応するextabエントリが見つかります。エントリには、このルーチン注 1extabのスタックに関する詳細が含まれています。ルーチンがスタックに格納しているものについての詳細を提供します。

コメントアウトされた部分 (r 変数の割り当て) がコメント解除されている場合、.ARM.exidx が表示されますが、そうでない場合は表示されません! これで説明できる???

ステートメントがある場合*r++ = (comp)tmp;、コンパイラはすべての変数をレジスタに保持できず、スタック (または少なくともfp) を使用する必要があります。これにより、 andexidxおよびextabdata が発行されます。


いくつかの解決策があります。スタック トレースや非同期機能が必要ない場合は、exidxとの両方を破棄しても問題ありません。extabより簡単なスタックの巻き戻しは、gnu tools/gcc を使用して行うことができます-mapcs-frame。thenfpは常に前のスタック フレーム (呼び出し元などを格納するfp) を格納するために使用されます。実際のテーブルはそれほど大きくなく、アンワインドのルーチンはかなり単純です。通常のプログラム パスを汚染しない、または のようなレジスタを使用しないテーブルを持つことは、おそらく 3% 未満のオーバーヘッド-mapcs-frameです。キャッシュと通常より多くのメモリを備えた Cortex-A CPU で望ましい。

参考:ATPCS リンクとフレームポインタの説明
                  ARM extab の構造

注 1:これは、プロローグがスタックを調整した後です。
注 2:ex例外用ですが、C++ 例外専用ではありません。

于 2019-08-12T14:53:07.010 に答える
2

tangrs の応答に加えて、gcc -v を実行すると、コンパイル中に使用されたデフォルト オプションをダンプできます。

GCC のすべてのオプション (暗黙的および明示的) オプションは、GCC の cc1 プログラムに渡されます。

于 2015-01-27T09:48:28.057 に答える