最終的な質問から始めましょう:gccのCでは、__func__
(または同等には、__FUNCTION__
)の値を取得できますか? .rodata
(または-mrodata=
ポイント)またはそのサブセクション以外のセクションでは、特定のコンパイラ生成変数を特定のELFセクションに強制する
十分な説明:
私はログマクロを持って言う:
#define LOG(fmt, ...) log_internal(__FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
(その単項文脈で使用される文字列連結演算子##
があれば、前にカンマを消費し、__VA_ARGS__
リストが空の場合にのみこれにより、引数の有無にかかわらず書式文字列を使用できるようになります)。
マクロは通常次のように使用できます。
void my_function(void) {
LOG("foo!");
LOG("bar: %p", &bar);
}
(log_internal
の実装に依存明らかに)印刷されることがあります
foo.c:201(my_function) foo!
foo.c:202(my_function) bar: 0x12345678
この場合、フォーマット文字列("foo"
と"bar: %p"
)とプリプロセッサ文字列("foo.c"
と"my_function"
)はデータのみを読んで、匿名です自動的に.rodata
セクションに配置されます。
しかし、私はそれらを別の場所に移動したいと言います(私は、スピードはRAMのほとんどすべてを実行する組み込みプラットフォームですが、いくつかのものをROMに移動するためにはメモリの制約があります)。それは__FILE__
と書式文字列を移動するには、「簡単」だ:
#define ROM_STR(str) (__extension__({static const __attribute__((__section__(".rom_data"))) char __c[] = (str); (const char *)&__c;}))
#define LOG(fmt, ...) log_internal(ROM_STR(__FILE__), __LINE__, __func__, ROM_STR(fmt), ##__VA_ARGS__)
評価し、その後、あなたが匿名の文字列に__attribute__
を置くことができないので、ROM_STR
マクロはそれを過渡名前を与え、特定のセクションにそれを貼付します開始アドレスに移動するので、きれいに置き換えることができます。これは、変数をフォーマット文字列としてLOG
に渡そうとすると機能しませんが、そのユースケースを除外します。
通常、同一である匿名の文字列は、コンパイラによって1つの格納場所に結合されるため、1つのファイル内のすべてのインスタンス__FILE__
は同じ実行時アドレスを共有します。 ROM_STR
の明示的な命名では、各インスタンスは独自の格納場所を取得するため、__FILE__
で実際に使用するのは実際には意味がありません。
しかし、私は__func__
で使用したいと思います。問題は__func__
が__FILE__
と同じ種類の魔法ではないということです。
かのように識別子
__func__
が暗黙的に翻訳者によって宣言され、すぐに各関数定義の開口ブレース以下、宣言
static const char __func__[] = "function-name";
:gccのマニュアル、「文字列として関数名」から
が表示されます。ここで、function-nameは語彙を囲む関数の名前です。この名前は、機能の未装飾の名前です。 ... これらの識別子はプリプロセッサマクロではありません。 GCC 3.3以前とCのみでは、
__FUNCTION__
と__PRETTY_FUNCTION__
は文字列リテラルとして扱われました。 char配列を初期化するために使うことができ、他の文字列リテラルと連結することができます。 GCC 3.4以降では、__func__
のように変数を変数として扱います。
したがって、あなたがROM_STR
で__func__
をラップしている場合、あなたは
error: invalid initializer
を取得し、あなたが__func__
の使用前または後のセクション属性を置くしようとした場合、あなたは
error: expected expression before ‘__attribute__’
を取得しますまたは
error: expected ‘)’ before ‘__attribute__’
それでは、オープニングの質問に戻ります:自分が選んだセクションに__func__
を保存することはできますか?おそらく-fdata-sections
を使用して、.rodata.__func__.*
を.rodata
の残りから除外するには、リンカスクリプトの魔法を使うことができますか?もしそうなら、リンカスクリプトで除外を使ってグロブするための構文は何ですか?言い換えれば、*(.rodata*)
のどこかに - 私はを別の場所に置くことができますが、2つのコピーを取得しないように元のglobを変更して除外する必要があります。
便利な[リンカースクリプトの構文への参照](http://www.xgc.com/manuals/gcc-1750-ug/p5node10.html) –
2015年の時点で、gccはこれを行わなくなりました。参照:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192 –