2

コードで次の文字列を定数として宣言しています。目的は、コンパイルされた出力に単純なメタデータを格納するための粗雑で単純な方法を提供することです。

const char myString1[] ="abc123\0";
const char myString2[] = {'a','b','c','1','2','3','\0'};

16 進エディタで出力を調べると、他の文字列定数が表示されますが、「abc123」は表示されません。これにより、有効になっている最適化が原因で、行がプログラムで参照されないため、行がコンパイルされていないと考えられます。

これを強制的にコンパイルするコード内の方法、またはこのメタデータをバイナリに取得する別の方法 (コード内) はありますか? バイナリのポストコンパイルを操作したくありません。目標は、可能な限り単純にすることです。

コンパイラ フラグ

-O2 -g -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -mcpu=cortex-m3 -mthumb

4

4 に答える 4

3

used属性を探していると思います:

「中古」

変数に付加されたこの属性は、変数が参照されていないように見えても、変数を発行する必要があることを意味します。

C++ クラス テンプレートの静的データ メンバーに適用された場合、この属性は、クラス自体がインスタンス化される場合にメンバーがインスタンス化されることも意味します。

のように適用します。

__attribute__((used))
const char myString1[] ="abc123\0";
__attribute__((used))
const char myString2[] = {'a','b','c','1','2','3','\0'};

あなたが投稿したコンパイラフラグを考えると、それはほぼ確実にリンカです。この-ffunction-sectionsフラグは、各定義をオブジェクト ファイル内の独自のセクションに配置します。これにより、リンカーは、データ項目または関数が参照されていないことを簡単に判断し、最終的なバイナリから除外できます。

于 2012-09-13T20:20:16.030 に答える
1

stringsこれらの文字列がバイナリに存在するかどうかを確認するには、binutils コマンドを使用します。

それらが最適化されている場合は、volatileそれらを宣言するときに修飾子を使用することができます。修飾子を使用していない場合でも、volatile一部のコンパイラはそれらを最適化できることに注意してください。

于 2012-09-13T20:10:47.203 に答える
1

私は、属性を使用し、リンク スクリプトを変更することを含む解決策を考え出しました。

まず、「.metadata」というカスタム セクションを定義します。

__attribute__ ((section(".metadata")))

次に、SECTIONS.ld スクリプトのブロックに、使用されていない場合でもKEEP(*(.metadata))リンカーに強制的に含めるa を追加しました。.metadata

.text :
{
    KEEP(*(.isr_vector))
    KEEP(*(.metadata))
    *(.text*)
    *(.rodata*)

} > MFlash32

ノート

.metadata セクションはメモリ マップに表示されますが、キーワードは変数と同じ行にある必要があることがわかりました。__attribute__そうしないと、実際にはバイナリに表示されませんでした。

于 2012-09-13T22:25:37.893 に答える
0

これらの変数がファイルスコープにある場合、コンパイラは文字列を提供する必要があります。これは、それらが別のコンパイル単位から使用されるかどうかを知ることができないためです。したがって、これらの変数を配置する「.o」ファイルには、文字列が含まれている必要があります。

巧妙なリンカは、これらの定数が必要ない最終的なバイナリを決定することができます。(ただし、私はそれを観察したことはありません。)これがあなたのプラットフォームに当てはまる場合は、実際にはプログラムが決して取らない「仮想」パスで変数を使用する必要があります。何かのようなもの

int main(int argc, char*argv[]){
  switch (argv[0][0]) {
    case 1: return myString1[argv[0][1]];
    case 2: return myString2[argv[0][1]];
  }
  ...
}
于 2012-09-13T21:05:25.287 に答える