Nios II Gen2 プロセッサー・リファレンス・ガイド

ID 683836
日付 10/28/2016
Public
ドキュメント目次

7.9.5. Linux 位置独立コード

グローバルデータまたはグローバル関数を使用するすべての位置独立コード (PIC) 関数は、GOT ポインターの値をレジスターにロードする必要があります。使用可能な任意のレジスターが使用されます。呼び出し元退避レジスターが使用されている場合は、呼び出しを保存して復元する必要があります。呼び出し先退避レジスターを使用する場合は、現在の関数の周辺に保存して復元する必要があります。本資料の例では、GOT ポインターにr22を使用しています。

GOT ポインターは、PC 相対オフセットを使用して_gp_got シンボルにロードされます。

GOT ポインターのロード

nextpc r22 1: orhi r1, %hiadj(_gp_got - 1b) # R_NIOS2_PCREL_HA _gp_got addi r1, r1, %lo(_gp_got - 1b) # R_NIOS2_PCREL_LO _gp_got - 4 add r22, r22, r1 # GOT pointer in r22

データは、GOT からその位置をロードすることでアクセスできます。シングルワード GOT エントリーが、参照される各シンボルに対して生成されます。

グローバルシンボルでの小さな GOT モデルエントリー

addi r3, r22, %got(x) # R_NIOS2_GOT16 GOT[n] R_NIOS2_GLOB_DAT x

グローバルシンボルでの大きな GOT モデルエントリー

movhi r3, %got_hiadj(x) # R_NIOS2_GOT_HA addi r3, r3, %got_lo(x) # R_NIOS2_GOT_LO add r3, r3, r22 GOT[n] R_NIOS2_GLOB_DAT x

ローカルシンボルでは、xへのシンボリック・リファレンスは、次の例に示すように、リンク・タイム・アドレスxを加数としてシンボルゼロに対する相対的な再配置に置き換えられます。

小さな GOT モデルでのローカルシンボル

addi r3, r22, %got(x) # R_NIOS2_GOT16 GOT[n] R_NIOS2_RELATIVE +x

大きな GOT モデルでのローカルシンボル

movhi r3, %got_hiadj(x) # R_NIOS2_GOT_HA addi r3, r3, %got_lo(x) # R_NIOS2_GOT_LO add r3, r3, r22 GOT[n] R_NIOS2_RELATIVE +x

call命令およびjmpi命令は、位置独立コードでは使用できません。代わりに、すべての呼び出しは GOT を通じて行われます。関数アドレスは%callでロードすることができ、遅延バインディングが可能でます。関数ポインターを初期化するには、代わりに%gotで関数のアドレスをロードします。関数のアドレスを必要とする入力オブジェクトがない場合、次の例に示すように、遅延バインディングのために GOT エントリーが PLT GOT に配置されます。

PLT について詳しくは、「プロシージャのリンク表」を参照してください。

PLT GOT の小さな GOT モデルエントリー

ldw r3, %call(fun)(r22) # R_NIOS2_CALL16 fun callr r3 PLTGOT[n] R_NIOS_JUMP_SLOT fun

PLT GOT の大きな GOT モデルエントリー

movhi r3, %call_hiadj(x) # R_NIOS2_CALL_HA addi r3, r3, %call_lo(x) # R_NIOS2_CALL_LO add r3, r3, r22 ldw r3, 0(r3) callr r3 PLTGOT[n] R_NIOS_JUMP_SLOT fun

関数または変数がコンパイル時に現在の共有オブジェクトに存在する場合は、次に示すように、PC 相対オフセットまたは GOT 相対オフセットを使用してアクセスできます。

現在の共有オブジェクトの関数または変数へのアクセス

orhi r3, %gotoff_hiadj(x) # R_NIOS2_GOTOFF_HA x addi r3, r3, %gotoff_lo(x) # R_NIOS2_GOTOFF_LO x add r3, r22, r3 # Address of x in r3

switch 文のような多方向分岐は、次に示すように、GOT 相対オフセットの表で実装可能です。

表で実装された switch 文

# Scaled table offset in r4 orhi r3, %gotoff_hiadj(Ltable) # R_NIOS2_GOTOFF_HA Ltable addi r3, r3, %gotoff_lo(Ltable) # R_NIOS2_GOTOFF_LO Ltable add r3, r22, r3 # r3 == &Ltable add r3, r3, r4 ldw r4, 0(r3) # r3 == Ltable[index] add r4, r4, r22 # Convert offset into destination jmp r4 ... Ltable: .word %gotoff(Label1) .word %gotoff(Label2) .word %gotoff(Label3)