@@ -71,6 +71,8 @@ public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
7171
7272 boolean is64bit = true ;
7373
74+ boolean overflowCheck = true ; // *_NC type relocations specify "no overflow check"
75+
7476 Address symbolAddr = elfRelocationContext .getSymbolAddress (sym );
7577 long symbolValue = elfRelocationContext .getSymbolValue (sym );
7678 long newValue = 0 ;
@@ -137,6 +139,87 @@ public RelocationResult relocate(ElfRelocationContext elfRelocationContext,
137139 break ;
138140 }
139141
142+ // MOV[ZK]: ((S+A) >> 0) & 0xffff
143+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G0_NC : {
144+ overflowCheck = false ;
145+ // fall-through
146+ }
147+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G0 : {
148+ int oldValue = memory .getInt (relocationAddress , isBigEndianInstructions );
149+ long imm = (symbolValue + addend ) >> 0 ;
150+
151+ oldValue &= ~(0xffff << 5 );
152+ newValue = oldValue | ((imm & 0xffff ) << 5 );
153+
154+ memory .setInt (relocationAddress , (int ) newValue , isBigEndianInstructions );
155+
156+ if (overflowCheck && imm > 0xffffL ) {
157+ // relocation already applied; report overflow condition
158+ markAsError (program , relocationAddress , "R_AARCH64_MOVW_UABS_G0" , symbolName ,
159+ "Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value" ,
160+ elfRelocationContext .getLog ());
161+ }
162+ break ;
163+ }
164+
165+ // MOV[ZK]: ((S+A) >> 16) & 0xffff
166+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G1_NC : {
167+ overflowCheck = false ;
168+ // fall-through
169+ }
170+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G1 : {
171+ int oldValue = memory .getInt (relocationAddress , isBigEndianInstructions );
172+ long imm = (symbolValue + addend ) >> 16 ;
173+
174+ oldValue &= ~(0xffff << 5 );
175+ newValue = oldValue | ((imm & 0xffff ) << 5 );
176+
177+ memory .setInt (relocationAddress , (int ) newValue , isBigEndianInstructions );
178+
179+ if (overflowCheck && imm > 0xffffL ) {
180+ // relocation already applied; report overflow condition
181+ markAsError (program , relocationAddress , "R_AARCH64_MOVW_UABS_G0" , symbolName ,
182+ "Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value" ,
183+ elfRelocationContext .getLog ());
184+ }
185+ break ;
186+ }
187+
188+ // MOV[ZK]: ((S+A) >> 32) & 0xffff
189+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G2_NC : {
190+ overflowCheck = false ;
191+ // fall-through
192+ }
193+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G2 : {
194+ int oldValue = memory .getInt (relocationAddress , isBigEndianInstructions );
195+ long imm = (symbolValue + addend ) >> 32 ;
196+
197+ oldValue &= ~(0xffff << 5 );
198+ newValue = oldValue | ((imm & 0xffff ) << 5 );
199+
200+ memory .setInt (relocationAddress , (int ) newValue , isBigEndianInstructions );
201+
202+ if (overflowCheck && imm > 0xffffL ) {
203+ // relocation already applied; report overflow condition
204+ markAsError (program , relocationAddress , "R_AARCH64_MOVW_UABS_G0" , symbolName ,
205+ "Failed overflow check for R_AARCH64_MOVW_UABS_G0 immediate value" ,
206+ elfRelocationContext .getLog ());
207+ }
208+ break ;
209+ }
210+
211+ // MOV[ZK]: ((S+A) >> 48) & 0xffff
212+ case AARCH64_ElfRelocationConstants .R_AARCH64_MOVW_UABS_G3 : {
213+ int oldValue = memory .getInt (relocationAddress , isBigEndianInstructions );
214+ long imm = (symbolValue + addend ) >> 48 ;
215+
216+ oldValue &= ~(0xffff << 5 );
217+ newValue = oldValue | ((imm & 0xffff ) << 5 );
218+
219+ memory .setInt (relocationAddress , (int ) newValue , isBigEndianInstructions );
220+ break ;
221+ }
222+
140223 // ADRH: ((PG(S+A)-PG(P)) >> 12) & 0x1fffff
141224 case AARCH64_ElfRelocationConstants .R_AARCH64_ADR_PREL_PG_HI21 :
142225 case AARCH64_ElfRelocationConstants .R_AARCH64_P32_ADR_PREL_PG_HI21 : {
0 commit comments