3030import java .util .Set ;
3131import java .util .TreeMap ;
3232
33+ import org .graalvm .compiler .core .common .NumUtil ;
34+
3335import com .oracle .objectfile .BuildDependency ;
3436import com .oracle .objectfile .LayoutDecisionMap ;
3537import com .oracle .objectfile .ObjectFile ;
4749class MachORelocationElement extends MachOObjectFile .LinkEditElement {
4850 /*
4951 * We are a bunch of RelocationInfo.Structs grouped by relocated section, ordered by the offset
50- * within the section.
52+ * within the section. Note also that, when present, an explicit addend for a given offset must
53+ * be stored immediately before is corresponding record
5154 */
5255
5356 private static int compareSectionThenOffset (MachORelocationInfo p , MachORelocationInfo q ) {
5457 if (!p .getRelocatedSection ().equals (q .getRelocatedSection ())) {
5558 return p .getRelocatedSection ().hashCode () - q .getRelocatedSection ().hashCode ();
5659 }
57- return Math .toIntExact (p .getOffset () - q .getOffset ());
60+ if (p .getOffset () != q .getOffset ()) {
61+ return Math .toIntExact (p .getOffset () - q .getOffset ());
62+ }
63+
64+ assert !(p .isAddendKind () && q .isAddendKind ()) : "two addends for same relocation" ;
65+ // want the addend kind first
66+ return -Boolean .compare (p .isAddendKind (), q .isAddendKind ());
5867 }
5968
6069 private Map <MachORelocationInfo , MachORelocationInfo > infos = new TreeMap <>(MachORelocationElement ::compareSectionThenOffset );
@@ -116,6 +125,12 @@ public int countFor(MachOSection s) {
116125 }
117126}
118127
128+ interface MachORelocationType {
129+ boolean isPCRelative ();
130+
131+ int getValue ();
132+ }
133+
119134/**
120135 * These are defined as an enum in
121136 * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173
@@ -124,20 +139,39 @@ public int countFor(MachOSection s) {
124139 * For examples of how these symbols are used, see the linked file above and
125140 * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h.
126141 */
127- enum X86_64Reloc {
128- UNSIGNED , // for absolute addresses
129- SIGNED , // for signed 32-bit displacement
130- BRANCH , // a CALL/JMP instruction with 32-bit displacement
131- GOT_LOAD , // a MOVQ load of a GOT entry
132- GOT , // other GOT references
133- SUBTRACTOR , // must be followed by a X86_64_RELOC_UNSIGNED
134- SIGNED_1 , // for signed 32-bit displacement with a -1 addend
135- SIGNED_2 , // for signed 32-bit displacement with a -2 addend
136- SIGNED_4 , // for signed 32-bit displacement with a -4 addend
137- TLV ; // for thread local variables
142+ enum X86_64Reloc implements MachORelocationType {
143+ UNSIGNED (0 ), // for absolute addresses
144+ SIGNED (1 , true ), // for signed 32-bit displacement
145+ BRANCH (2 ), // a CALL/JMP instruction with 32-bit displacement
146+ GOT_LOAD (3 ), // a MOVQ load of a GOT entry
147+ GOT (4 ), // other GOT references
148+ SUBTRACTOR (5 ), // must be followed by a X86_64_RELOC_UNSIGNED
149+ SIGNED_1 (6 ), // for signed 32-bit displacement with a -1 addend
150+ SIGNED_2 (7 ), // for signed 32-bit displacement with a -2 addend
151+ SIGNED_4 (8 ), // for signed 32-bit displacement with a -4 addend
152+ TLV (9 ); // for thread local variables
153+
154+ private final boolean pcRelative ;
155+ private final int value ;
138156
157+ X86_64Reloc (int value ) {
158+ this .value = value ;
159+ pcRelative = false ;
160+ }
161+
162+ X86_64Reloc (int value , boolean pcRelative ) {
163+ this .value = value ;
164+ this .pcRelative = pcRelative ;
165+ }
166+
167+ @ Override
168+ public boolean isPCRelative () {
169+ return pcRelative ;
170+ }
171+
172+ @ Override
139173 public int getValue () {
140- return ordinal () ;
174+ return value ;
141175 }
142176}
143177
@@ -151,33 +185,53 @@ public int getValue() {
151185 * (for AArch32 information, but does provide some insight) and
152186 * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h.
153187 */
154- enum ARM64Reloc {
155- UNSIGNED , // for pointers
156- SUBTRACTOR , // must be followed by a ARM64_RELOC_UNSIGNED
157- BRANCH26 , // a B/BL instruction with 26-bit displacement
158- PAGE21 , // pc-rel distance to page of target
159- PAGEOFF12 , // offset within page, scaled by r_length
160- GOT_LOAD_PAGE21 , // pc-rel distance to page of GOT slot
161- GOT_LOAD_PAGEOFF12 , // offset within page of GOT slot, scaled by r_length
162- POINTER_TO_GOT , // for pointers to GOT slots
163- TLVP_LOAD_PAGE21 , // pc-rel distance to page of TLVP slot
164- TLVP_LOAD_PAGEOFF12 , // offset within page of TLVP slot, scaled by r_length
165- ADDEND ; // must be followed by PAGE21 or PAGEOFF12
188+ enum ARM64Reloc implements MachORelocationType {
189+ UNSIGNED (0 ), // for pointers
190+ SUBTRACTOR (1 ), // must be followed by a ARM64_RELOC_UNSIGNED
191+ BRANCH26 (2 ), // a B/BL instruction with 26-bit displacement
192+ PAGE21 (3 , true ), // pc-rel distance to page of target
193+ PAGEOFF12 (4 ), // offset within page, scaled by r_length
194+ GOT_LOAD_PAGE21 (5 , true ), // pc-rel distance to page of GOT slot
195+ GOT_LOAD_PAGEOFF12 (6 ), // offset within page of GOT slot, scaled by r_length
196+ POINTER_TO_GOT (7 ), // for pointers to GOT slots
197+ TLVP_LOAD_PAGE21 (8 , true ), // pc-rel distance to page of TLVP slot
198+ TLVP_LOAD_PAGEOFF12 (9 ), // offset within page of TLVP slot, scaled by r_length
199+ ADDEND (10 ); // must be followed by PAGE21 or PAGEOFF12
200+
201+ private final boolean pcRelative ;
202+ private final int value ;
203+
204+ ARM64Reloc (int value ) {
205+ this .value = value ;
206+ pcRelative = false ;
207+ }
208+
209+ ARM64Reloc (int value , boolean pcRelative ) {
210+ this .value = value ;
211+ this .pcRelative = pcRelative ;
212+ }
166213
214+ @ Override
215+ public boolean isPCRelative () {
216+ return pcRelative ;
217+ }
218+
219+ @ Override
167220 public int getValue () {
168- return ordinal () ;
221+ return value ;
169222 }
170223}
171224
172225final class MachORelocationInfo implements RelocationRecord , RelocationMethod {
173226
174227 private final MachORelocationElement containingElement ;
175228 private final MachOSection relocatedSection ;
176- private final RelocationKind kind ;
229+ private final MachORelocationType kind ;
177230 private final int sectionOffset ;
178231 private final Symbol sym ;
179232 private final MachOSection targetSection ;
180233 private final byte log2length ;
234+ private final int addend ;
181235
182236 /**
183237 * Construct a relocation record.
@@ -189,7 +243,9 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod {
189243 * @param kind the kind of relocation to perform at the relocation site
190244 * @param symbolName the symbol against which to relocate
191245 */
192- MachORelocationInfo (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , int requestedLength , RelocationKind kind , String symbolName , boolean asLocalReloc ) {
246+ private MachORelocationInfo (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , int requestedLength , MachORelocationType kind , String symbolName ,
247+ boolean asLocalReloc ,
248+ int addend ) {
193249 this .containingElement = containingElement ;
194250 this .relocatedSection = relocatedSection ;
195251 this .sectionOffset = offset ; // gets turned into a vaddr on write-out
@@ -215,6 +271,20 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod {
215271 // if the symbol is defined in the same file, i.e. locally, we have a target section
216272 assert !asLocalReloc || this .sym .isDefined ();
217273 this .targetSection = asLocalReloc ? (MachOSection ) this .sym .getDefinedSection () : null ;
274+ this .addend = addend ;
275+ }
276+
277+ /* Creates an ARM64_RELOC_ADDEND relocation type. */
278+ static MachORelocationInfo createARM64RelocAddend (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , String symbolName , long addend ) {
279+ int length = 4 ; // This relocation record holds the addend for a 4-byte AArch64 instruction
280+ return new MachORelocationInfo (containingElement , relocatedSection , offset , length , ARM64Reloc .ADDEND , symbolName , false , Math .toIntExact (addend ));
281+ }
282+
283+ static MachORelocationInfo createRelocation (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , RelocationKind kind , String symbolName ) {
284+ int length = ObjectFile .RelocationKind .getRelocationSize (kind );
285+ MachORelocationType type = getMachORelocationType (relocatedSection , kind );
286+ return new MachORelocationInfo (containingElement , relocatedSection , offset , length , type , symbolName , false , 0 );
287+
218288 }
219289
220290 public static int getEncodedSize () {
@@ -225,7 +295,12 @@ public void write(OutputAssembler oa, @SuppressWarnings("unused") Map<Element, L
225295 /* We need to convert in-section offsets to vaddrs if we are writing dynamic object. */
226296 // "extern" means symbolNum is a symbol not a section number
227297 int symbolNum ;
228- if (isExtern ()) {
298+ if (isAddendKind ()) {
299+ assert !isExtern () : "addend must be encoded as a local" ;
300+ assert NumUtil .isSignedNbit (24 , addend );
301+ // store addend as symbolnum
302+ symbolNum = addend ;
303+ } else if (isExtern ()) {
229304 // we're non-local, so use a symbol
230305 symbolNum = relocatedSection .getOwner ().getSymbolTable ().indexOf (sym );
231306 } else {
@@ -249,11 +324,11 @@ public void write(OutputAssembler oa, @SuppressWarnings("unused") Map<Element, L
249324 */
250325 int remainingWord = 0 ;
251326 //@formatter:off
252- remainingWord |= symbolNum & 0x00ffffff ;
253- remainingWord |= isPCRelative () ? ( 1 << 24 ) : 0 ;
254- remainingWord |= (log2length & 0x3 ) << 25 ;
255- remainingWord |= isExtern () ? ( 1 << 27 ) : 0 ;
256- remainingWord |= ( getMachORelocationType () & 0xf ) << 28 ;
327+ remainingWord |= symbolNum & 0x00ffffff ;
328+ remainingWord |= ( kind . isPCRelative () ? 1 : 0 ) << 24 ;
329+ remainingWord |= (log2length & 0x3 ) << 25 ;
330+ remainingWord |= ( isExtern () ? 1 : 0 ) << 27 ;
331+ remainingWord |= ( kind . getValue () & 0xf ) << 28 ;
257332 //@formatter:on
258333 oa .write4Byte (remainingWord );
259334 assert oa .pos () - startPos == 8 ; // check we wrote how much we expected
@@ -271,42 +346,41 @@ public Symbol getReferencedSymbol() {
271346 return sym ;
272347 }
273348
349+ public boolean isAddendKind () {
350+ return kind == ARM64Reloc .ADDEND ;
351+ }
352+
353+ public long getAddend () {
354+ return addend ;
355+ }
356+
274357 public MachOSection getRelocatedSection () {
275358 return relocatedSection ;
276359 }
277360
278361 private boolean isExtern () {
279- // we record localness by grabbing the target section (see constructor)
280- return targetSection == null ;
281- }
282-
283- private boolean isPCRelative () {
284- switch (kind ) {
285- case PC_RELATIVE_1 :
286- case PC_RELATIVE_2 :
287- case PC_RELATIVE_4 :
288- case PC_RELATIVE_8 :
289- case AARCH64_R_AARCH64_ADR_PREL_PG_HI21 :
290- return true ;
291- default :
292- return false ;
293- }
362+ /*
363+ * We record localness by grabbing the target section (see constructor). Note that the
364+ * addend kind is not considered an extern.
365+ */
366+
367+ return targetSection == null && !isAddendKind ();
294368 }
295369
296- private int getMachORelocationType () {
297- switch (getRelocatedSection () .getOwner ().cpuType ) {
370+ private static MachORelocationType getMachORelocationType (MachOSection relocatedSection , RelocationKind kind ) {
371+ switch (relocatedSection .getOwner ().cpuType ) {
298372 case X86_64 :
299373 switch (kind ) {
300374 case DIRECT_1 :
301375 case DIRECT_2 :
302376 case DIRECT_4 :
303377 case DIRECT_8 :
304- return X86_64Reloc .UNSIGNED . getValue () ;
378+ return X86_64Reloc .UNSIGNED ;
305379 case PC_RELATIVE_1 :
306380 case PC_RELATIVE_2 :
307381 case PC_RELATIVE_4 :
308382 case PC_RELATIVE_8 :
309- return X86_64Reloc .SIGNED . getValue () ;
383+ return X86_64Reloc .SIGNED ;
310384 default :
311385 case UNKNOWN :
312386 throw new IllegalArgumentException ("unknown relocation kind: " + kind );
@@ -317,15 +391,15 @@ private int getMachORelocationType() {
317391 case DIRECT_2 :
318392 case DIRECT_4 :
319393 case DIRECT_8 :
320- return ARM64Reloc .UNSIGNED . getValue () ;
394+ return ARM64Reloc .UNSIGNED ;
321395 case AARCH64_R_AARCH64_ADR_PREL_PG_HI21 :
322- return ARM64Reloc .PAGE21 . getValue () ;
396+ return ARM64Reloc .PAGE21 ;
323397 case AARCH64_R_AARCH64_LDST64_ABS_LO12_NC :
324398 case AARCH64_R_AARCH64_LDST32_ABS_LO12_NC :
325399 case AARCH64_R_AARCH64_LDST16_ABS_LO12_NC :
326400 case AARCH64_R_AARCH64_LDST8_ABS_LO12_NC :
327401 case AARCH64_R_AARCH64_ADD_ABS_LO12_NC :
328- return ARM64Reloc .PAGEOFF12 . getValue () ;
402+ return ARM64Reloc .PAGEOFF12 ;
329403 default :
330404 case UNKNOWN :
331405 throw new IllegalArgumentException ("unknown relocation kind: " + kind );
@@ -342,7 +416,7 @@ public boolean equals(Object obj) {
342416 }
343417 if (obj != null && getClass () == obj .getClass ()) {
344418 MachORelocationInfo other = (MachORelocationInfo ) obj ;
345- return sectionOffset == other .sectionOffset && log2length == other .log2length && Objects .equals (containingElement , other .containingElement ) &&
419+ return sectionOffset == other .sectionOffset && log2length == other .log2length && Objects .equals (containingElement , other .containingElement ) && addend == other . addend &&
346420 Objects .equals (getRelocatedSection (), other .getRelocatedSection ()) && kind == other .kind &&
347421 Objects .equals (sym , other .sym ) && Objects .equals (targetSection , other .targetSection );
348422 }
@@ -351,7 +425,6 @@ public boolean equals(Object obj) {
351425
352426 @ Override
353427 public int hashCode () {
354- return (((((containingElement .hashCode () * 31 + relocatedSection .hashCode ()) * 31 + kind .hashCode ()) * 31 +
355- sectionOffset ) * 31 + sym .hashCode ()) * 31 + targetSection .hashCode ()) * 31 + log2length ;
428+ return Objects .hash (containingElement , relocatedSection , kind , sectionOffset , sym , targetSection , log2length , addend );
356429 }
357430}
0 commit comments